r7282: ldb_sqlite3 work in progress.
[metze/samba/wip.git] / source4 / lib / ldb / ldb_sqlite3 / ldb_sqlite3.c
1 /* 
2    ldb database library
3    
4    Copyright (C) Andrew Tridgell  2004
5    
6    ** NOTE! The following LGPL license applies to the ldb
7    ** library. This does NOT imply that all of Samba is released
8    ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14    
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19    
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb sqlite3 backend
29  *
30  *  Description: core files for SQLITE3 backend
31  *
32  *  Author: Derrell Lipman (based on Andrew Tridgell's LDAP backend)
33  */
34
35 #include "includes.h"
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38 #include "ldb/ldb_sqlite3/ldb_sqlite3.h"
39
40 #ifndef False
41 # define False  (0)
42 # define True   (! False)
43 #endif
44
45 #define QUERY(lsqlite3, pppValues, pNumRows, bRollbackOnError, sql...)  \
46     do                                                                  \
47     {                                                                   \
48             if (lsqlite3_query(lsqlite3,                                \
49                                pppValues,                               \
50                                pNumRows,                                \
51                                sql) != 0) {                             \
52                 if (bRollbackOnError) {                                 \
53                         lsqlite3_query(lsqlite3,                        \
54                                        NULL,                            \
55                                        NULL,                            \
56                                        "ROLLBACK;");                    \
57                 }                                                       \
58                 return -1;                                              \
59         }                                                               \
60     } while (0)
61
62
63 static int
64 lsqlite3_query(const struct lsqlite3_private *lsqlite3,
65                char ***pppValues,
66                int *pNumRows,
67                const char *pSql,
68                ...)
69 {
70         
71 }
72
73 static int
74 lsqlite3_create_attr_table(struct ldb_module *module,
75                            char * pAttr)
76 {
77
78 }
79
80
81 #if 0
82 p/*
83  * we don't need this right now, but will once we add some backend options
84  *
85  * find an option in an option list (a null terminated list of strings)
86  *
87  * this assumes the list is short. If it ever gets long then we really should
88  * do this in some smarter way
89  */
90 static const char *
91 lsqlite3_option_find(const struct lsqlite3_private *lsqlite3,
92                      const char *name)
93 {
94         int                 i;
95         size_t              len = strlen(name);
96
97         if (!lsqlite3->options) return NULL;
98
99         for (i=0;lsqlite3->options[i];i++) {            
100                 if (strncmp(lsqlite3->options[i], name, len) == 0 &&
101                     lsqlite3->options[i][len] == '=') {
102                         return &lsqlite3->options[i][len+1];
103                 }
104         }
105
106         return NULL;
107 }
108 #endif
109
110 /*
111   callback function used in call to ldb_dn_fold() for determining whether an
112   attribute type requires case folding.
113 */
114 static int lsqlite3_case_fold_attr_required(struct ldb_module *module,
115                                            char *attr)
116 {
117 #warning "currently, all attributes require case folding"
118         return True;
119 }
120
121
122 /*
123  * rename a record
124  */
125 static int
126 lsqlite3_rename(struct ldb_module *module,
127                 const char *olddn,
128                 const char *newdn)
129 {
130         /* ignore ltdb specials */
131         if (olddn[0] == '@' ||newdn[0] == '@') {
132                 return 0;
133         }
134
135 #warning "lsqlite3_rename() is not yet supported"
136         return -1;
137 }
138
139 /*
140  * delete a record
141  */
142 static int
143 lsqlite3_delete(struct ldb_module *module,
144                 const char *dn)
145 {
146         /* ignore ltdb specials */
147         if (dn[0] == '@') {
148                 return 0;
149         }
150         
151         return -1;
152 }
153
154 #if 0 /* not currently used * /
155 /*
156  * free a search result
157  */
158 static int
159 lsqlite3_search_free(struct ldb_module *module,
160                      struct ldb_message **res)
161 {
162         talloc_free(res);
163         return 0;
164 }
165 #endif
166
167
168 /*
169  * add a single set of ldap message values to a ldb_message
170  */
171
172 /* get things to compile before we actually implement this function */
173 struct berval
174 {
175         int x;
176 };
177
178 #warning "lsqlite3_add_msg_attr() not yet implemented or used"
179 #if 0
180 static int
181 lsqlite3_add_msg_attr(struct ldb_context *ldb,
182                       struct ldb_message *msg, 
183                       const char *attr,
184                       struct berval **bval)
185 {
186         int                          i;
187         int                          count;
188         struct ldb_message_element * el;
189
190         count = ldap_count_values_len(bval);
191
192         if (count <= 0) {
193                 return -1;
194         }
195
196         el = talloc_realloc(msg, msg->elements, struct ldb_message_element, 
197                               msg->num_elements + 1);
198         if (!el) {
199                 errno = ENOMEM;
200                 return -1;
201         }
202
203         msg->elements = el;
204
205         el = &msg->elements[msg->num_elements];
206
207         el->name = talloc_strdup(msg->elements, attr);
208         if (!el->name) {
209                 errno = ENOMEM;
210                 return -1;
211         }
212         el->flags = 0;
213
214         el->num_values = 0;
215         el->values = talloc_array(msg->elements, struct ldb_val, count);
216         if (!el->values) {
217                 errno = ENOMEM;
218                 return -1;
219         }
220
221         for (i=0;i<count;i++) {
222                 el->values[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len);
223                 if (!el->values[i].data) {
224                         return -1;
225                 }
226                 el->values[i].length = bval[i]->bv_len;
227                 el->num_values++;
228         }
229
230         msg->num_elements++;
231
232         return 0;
233 }
234 #endif
235
236 /*
237  * search for matching records
238  */
239 static int
240 lsqlite3_search(struct ldb_module *module,
241                 const char *base,
242                 enum ldb_scope scope,
243                 const char *expression,
244                 const char * const attrs[],
245                 struct ldb_message ***res)
246 {
247 #warning "lsqlite3_search() not yet implemented"
248 #if 0
249         int                       count;
250         int                       msg_count;
251         struct ldb_context *      ldb = module->ldb;
252         struct lsqlite3_private * lsqlite3 = module->private_data;
253
254         if (base == NULL) {
255                 base = "";
256         }
257
258         lsqlite3->last_rc = ldap_search_s(lsqlite3->ldap, base, (int)scope, 
259                                       expression, 
260                                       discard_const_p(char *, attrs), 
261                                       0, &ldapres);
262         if (lsqlite3->last_rc != LDAP_SUCCESS) {
263                 return -1;
264         }
265
266         count = ldap_count_entries(lsqlite3->ldap, ldapres);
267         if (count == -1 || count == 0) {
268                 ldap_msgfree(ldapres);
269                 return count;
270         }
271
272         (*res) = talloc_array(lsqlite3, struct ldb_message *, count+1);
273         if (! *res) {
274                 ldap_msgfree(ldapres);
275                 errno = ENOMEM;
276                 return -1;
277         }
278
279         (*res)[0] = NULL;
280
281         msg_count = 0;
282
283         /* loop over all messages */
284         for (msg=ldap_first_entry(lsqlite3->ldap, ldapres); 
285              msg; 
286              msg=ldap_next_entry(lsqlite3->ldap, msg)) {
287                 BerElement *berptr = NULL;
288                 char *attr, *dn;
289
290                 if (msg_count == count) {
291                         /* hmm, got too many? */
292                         ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
293                         break;
294                 }
295
296                 (*res)[msg_count] = talloc(*res, struct ldb_message);
297                 if (!(*res)[msg_count]) {
298                         goto failed;
299                 }
300                 (*res)[msg_count+1] = NULL;
301
302                 dn = ldap_get_dn(lsqlite3->ldap, msg);
303                 if (!dn) {
304                         goto failed;
305                 }
306
307                 (*res)[msg_count]->dn = talloc_strdup((*res)[msg_count], dn);
308                 ldap_memfree(dn);
309                 if (!(*res)[msg_count]->dn) {
310                         goto failed;
311                 }
312
313
314                 (*res)[msg_count]->num_elements = 0;
315                 (*res)[msg_count]->elements = NULL;
316                 (*res)[msg_count]->private_data = NULL;
317
318                 /* loop over all attributes */
319                 for (attr=ldap_first_attribute(lsqlite3->ldap, msg, &berptr);
320                      attr;
321                      attr=ldap_next_attribute(lsqlite3->ldap, msg, berptr)) {
322                         struct berval **bval;
323                         bval = ldap_get_values_len(lsqlite3->ldap, msg, attr);
324
325                         if (bval) {
326                                 lsqlite3_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
327                                 ldap_value_free_len(bval);
328                         }                                         
329                         
330                         ldap_memfree(attr);
331                 }
332                 if (berptr) ber_free(berptr, 0);
333
334                 msg_count++;
335         }
336
337         ldap_msgfree(ldapres);
338
339         return msg_count;
340
341 failed:
342         if (*res) lsqlite3_search_free(module, *res);
343         return -1;
344 #else
345         return 0;
346 #endif
347 }
348
349
350 /*
351  * Issue a series of SQL statements to implement the ADD/MODIFY/DELETE
352  * requests in the ldb_message
353  */
354 static int
355 lsqlite3_msg_to_sql(struct ldb_module *module,
356                     const struct ldb_message *msg,
357                     long long eid,
358                     int use_flags)
359 {
360         int                         flags;
361         unsigned int                i;
362         unsigned int                j;
363         struct lsqlite3_private *   lsqlite3 = module->private_data;
364
365         for (i = 0; i < msg->num_elements; i++) {
366                 const struct ldb_message_element *el = &msg->elements[i];
367
368                 if (! use_flags) {
369                         flags = LDB_FLAG_MOD_ADD;
370                 } else {
371                         flags = el->flags & LDB_FLAG_MOD_MASK;
372                 }
373
374                 if (flags == LDB_FLAG_MOD_ADD) {
375                         /* Create the attribute table if it doesn't exist */
376                         if (lsqlite3_create_attr_table(module,
377                                                        el->name) != 0) {
378                                 return -1;
379                         }
380                 }
381
382                 /* For each value of the specified attribute name... */
383                 for (j = 0; j < el->num_values; j++) {
384
385                         /* ... bind the attribute value, if necessary */
386                         switch (flags) {
387                         case LDB_FLAG_MOD_ADD:
388                                 QUERY(lsqlite3,
389                                       NULL, NULL,
390                                       False,
391                                       "INSERT INTO ldb_attr_%q "
392                                       "    (eid, attr_value) "
393                                       "  VALUES "
394                                       "    (%lld, %Q);",
395                                       eid, el->values[j].data);
396                                 QUERY(lsqlite3,
397                                       NULL, NULL,
398                                       False,
399                                       "UPDATE ldb_entry "
400                                       "  SET entry_data = "
401                                       "        add_attr(entry_data, %Q, %Q) "
402                                       "  WHERE eid = %lld;",
403                                       el->name, el->values[j].data, eid);
404                                       
405                                 break;
406
407                         case LDB_FLAG_MOD_REPLACE:
408                                 QUERY(lsqlite3,
409                                       NULL, NULL,
410                                       False,
411                                       "UPDATE ldb_attr_%q "
412                                       "  SET attr_value = %Q "
413                                       "  WHERE eid = %lld;",
414                                       el->values[j].data, eid);
415                                 QUERY(lsqlite3,
416                                       NULL, NULL,
417                                       False,
418                                       "UPDATE ldb_entry "
419                                       "  SET entry_data = "
420                                       "        mod_attr(entry_data, %Q, %Q) "
421                                       "  WHERE eid = %lld;",
422                                       el->name, el->values[j].data, eid);
423                                 break;
424
425                         case LDB_FLAG_MOD_DELETE:
426                                 /* No additional parameters to this query */
427                                 QUERY(lsqlite3,
428                                       NULL, NULL,
429                                       False,
430                                       "DELETE FROM ldb_attr_%q "
431                                       "  WHERE eid = %lld "
432                                       "    AND attr_value = %Q;",
433                                       eid, el->values[j].data);
434                                 QUERY(lsqlite3,
435                                       NULL, NULL,
436                                       False,
437                                       "UPDATE ldb_entry "
438                                       "  SET entry_data = "
439                                       "        del_attr(entry_data, %Q, %Q) "
440                                       "  WHERE eid = %lld;",
441                                       el->name, el->values[j].data, eid);
442                                 break;
443                         }
444                 }
445         }
446
447         return 0;
448 }
449
450
451 static int
452 lsqlite3_insert_dn(struct lsqlite3_private * lsqlite3,
453                    char * pDN,
454                    long long * pEID)
455 {
456
457 }
458
459
460 /*
461  * add a record
462  */
463 static int
464 lsqlite3_add(struct ldb_module *module,
465              const struct ldb_message *msg)
466 {
467         long long                   eid;
468         struct lsqlite3_private *   lsqlite3 = module->private_data;
469
470         /* ignore ltdb specials */
471         if (msg->dn[0] == '@') {
472                 return 0;
473         }
474
475         /* Begin a transaction */
476         QUERY(lsqlite3, NULL, NULL, False, "BEGIN EXCLUSIVE;");
477
478         /*
479          * Build any portions of the directory tree that don't exist.  If the
480          * final component already exists, it's an error.
481          */
482         if (lsqlite3_insert_dn(lsqlite3,
483                                ldb_dn_fold(module,
484                                            msg->dn,
485                                            lsqlite3_case_fold_attr_required),
486                                          &eid) != 0) {
487                 QUERY(lsqlite3, NULL, NULL, False, "ROLLBACK;");
488                 return -1;
489         }
490
491         /* Add attributes to this new entry */
492         if (lsqlite3_msg_to_sql(module, msg, eid, False) != 0) {
493                 QUERY(lsqlite3, NULL, NULL, False, "ROLLBACK;");
494                 return -1;
495         }
496
497         /* Everything worked.  Commit it! */
498         QUERY(lsqlite3, NULL, NULL, True, "COMMIT;");
499         return 0;
500 }
501
502
503 /*
504  * modify a record
505  */
506 static int
507 lsqlite3_modify(struct ldb_module *module,
508                 const struct ldb_message *msg)
509 {
510         int                         numRows;
511         long long                   eid;
512         char **                     ppValues;
513         struct lsqlite3_private *   lsqlite3 = module->private_data;
514
515         /* ignore ltdb specials */
516         if (msg->dn[0] == '@') {
517                 return 0;
518         }
519
520         /* Begin a transaction */
521         QUERY(lsqlite3, NULL, NULL, False, "BEGIN EXCLUSIVE;");
522
523         /* Get the id of this DN. */
524         QUERY(lsqlite3,
525               &ppValues,
526               &numRows,
527               True, 
528               "SELECT eid "
529               "  FROM ldb_entry "
530               "  WHERE dn = %Q;",
531               ldb_dn_fold(module,
532                           msg->dn,
533                           lsqlite3_case_fold_attr_required));
534
535         /* Did it exist? */
536         if (numRows != 1) {
537                 /* Nope.  See ya! */
538                 sqlite3_free_table(ppValues);
539                 return -1;
540         }
541
542         /* Retrieve the eid */
543         eid = strtoll(ppValues[1], NULL, 10);
544
545         /* Modify attributes as specified */
546         if (lsqlite3_msg_to_sql(module, msg, eid, False) != 0) {
547                 QUERY(lsqlite3, NULL, NULL, False, "ROLLBACK;");
548                 return -1;
549         }
550
551         /* Everything worked.  Commit it! */
552         QUERY(lsqlite3, NULL, NULL, True, "COMMIT;");
553         return 0 ;
554 }
555
556 static int
557 lsqlite3_lock(struct ldb_module *module,
558               const char *lockname)
559 {
560         if (lockname == NULL) {
561                 return -1;
562         }
563
564         /* TODO implement a local locking mechanism here */
565
566         return 0;
567 }
568
569 static int
570 lsqlite3_unlock(struct ldb_module *module,
571                 const char *lockname)
572 {
573         if (lockname == NULL) {
574                 return -1;
575         }
576
577         /* TODO implement a local locking mechanism here */
578
579         return 0;
580 }
581
582 /*
583  * return extended error information
584  */
585 static const char *
586 lsqlite3_errstring(struct ldb_module *module)
587 {
588         struct lsqlite3_private *   lsqlite3 = module->private_data;
589
590         return sqlite3_errmsg(lsqlite3->sqlite);
591 }
592
593
594 static const struct ldb_module_ops lsqlite3_ops = {
595         "sqlite",
596         lsqlite3_search,
597         lsqlite3_add,
598         lsqlite3_modify,
599         lsqlite3_delete,
600         lsqlite3_rename,
601         lsqlite3_lock,
602         lsqlite3_unlock,
603         lsqlite3_errstring
604 };
605
606
607 static int
608 lsqlite3_destructor(void *p)
609 {
610         struct lsqlite3_private *   lsqlite3 = p;
611
612         (void) sqlite3_close(lsqlite3->sqlite);
613         return 0;
614 }
615
616 static int
617 lsqlite3_initialize(struct lsqlite3_private *lsqlite3,
618                     const char *url)
619 {
620         int             ret;
621         int             bNewDatabase = False;
622         char *          p;
623         const char *    pTail;
624         struct stat     statbuf;
625         sqlite3_stmt *  stmt;
626         const char *    schema =       
627                 "-- ------------------------------------------------------"
628
629                 "PRAGMA auto_vacuum=1;"
630
631                 "-- ------------------------------------------------------"
632
633                 "BEGIN EXCLUSIVE;"
634
635                 "-- ------------------------------------------------------"
636
637                 "CREATE TABLE ldb_info AS"
638                 "  SELECT 'LDB' AS database_type,"
639                 "         '1.0' AS version;"
640
641                 "-- ------------------------------------------------------"
642                 "-- Schema"
643
644                 "/*"
645                 " * The entry table holds the information about an entry. "
646                 " * This table is used to obtain the EID of the entry and to "
647                 " * support scope=one and scope=base.  The parent and child"
648                 " * table is included in the entry table since all the other"
649                 " * attributes are dependent on EID."
650                 " */"
651                 "CREATE TABLE ldb_entry"
652                 "("
653                 "  -- Unique identifier of this LDB entry"
654                 "  eid                   INTEGER PRIMARY KEY,"
655
656                 "  -- Unique identifier of the parent LDB entry"
657                 "  peid                  INTEGER REFERENCES ldb_entry,"
658
659                 "  -- Distinguished name of this entry"
660                 "  dn                    TEXT,"
661
662                 "  -- Time when the entry was created"
663                 "  create_timestamp      INTEGER,"
664
665                 "  -- Time when the entry was last modified"
666                 "  modify_timestamp      INTEGER,"
667
668                 "  -- Attributes of this entry, in the form"
669                 "  --   attr\1value\0[attr\1value\0]*\0"
670                 "  entry_data            TEXT"
671                 ");"
672
673
674                 "/*"
675                 " * The purpose of the descendant table is to support the"
676                 " * subtree search feature.  For each LDB entry with a unique"
677                 " * ID (AEID), this table contains the unique identifiers"
678                 " * (DEID) of the descendant entries."
679                 " *"
680                 " * For evern entry in the directory, a row exists in this"
681                 " * table for each of its ancestors including itself.  The "
682                 " * size of the table depends on the depth of each entry.  In "
683                 " * the worst case, if all the entries were at the same "
684                 " * depth, the number of rows in the table is O(nm) where "
685                 " * n is the number of nodes in the directory and m is the "
686                 " * depth of the tree. "
687                 " */"
688                 "CREATE TABLE ldb_descendants"
689                 "("
690                 "  -- The unique identifier of the ancestor LDB entry"
691                 "  aeid                  INTEGER REFERENCES ldb_entry,"
692
693                 "  -- The unique identifier of the descendant LDB entry"
694                 "  deid                  INTEGER REFERENCES ldb_entry"
695                 ");"
696
697
698                 "CREATE TABLE ldb_object_classes"
699                 "("
700                 "  -- Object classes are inserted into this table to track"
701                 "  -- their class hierarchy.  'top' is the top-level class"
702                 "  -- of which all other classes are subclasses."
703                 "  class_name            TEXT PRIMARY KEY,"
704
705                 "  -- tree_key tracks the position of the class in"
706                 "  -- the hierarchy"
707                 "  tree_key              TEXT UNIQUE"
708                 ");"
709
710                 "/*"
711                 " * There is one attribute table per searchable attribute."
712                 " */"
713                 "/*"
714                 "CREATE TABLE ldb_attr_ATTRIBUTE_NAME"
715                 "("
716                 "  -- The unique identifier of the LDB entry"
717                 "  eid                   INTEGER REFERENCES ldb_entry,"
718
719                 "  -- Normalized attribute value"
720                 "  attr_value            TEXT"
721                 ");"
722                 "*/"
723
724
725                 "-- ------------------------------------------------------"
726                 "-- Indexes"
727
728
729                 "-- ------------------------------------------------------"
730                 "-- Triggers"
731
732                 "CREATE TRIGGER ldb_entry_insert_tr"
733                 "  AFTER INSERT"
734                 "  ON ldb_entry"
735                 "  FOR EACH ROW"
736                 "    BEGIN"
737                 "      UPDATE ldb_entry"
738                 "        SET create_timestamp = strftime('%s', 'now'),"
739                 "            modify_timestamp = strftime('%s', 'now')"
740                 "        WHERE eid = new.eid;"
741                 "    END;"
742
743                 "CREATE TRIGGER ldb_entry_update_tr"
744                 "  AFTER UPDATE"
745                 "  ON ldb_entry"
746                 "  FOR EACH ROW"
747                 "    BEGIN"
748                 "      UPDATE ldb_entry"
749                 "        SET modify_timestamp = strftime('%s', 'now')"
750                 "        WHERE eid = old.eid;"
751                 "    END;"
752
753                 "-- ------------------------------------------------------"
754                 "-- Table initialization"
755
756                 "/* We need an implicit 'top' level object class */"
757                 "INSERT INTO ldb_attributes (attr_name,"
758                 "                            parent_tree_key)"
759                 "  SELECT 'top', '';"
760
761                 "-- ------------------------------------------------------"
762
763                 "COMMIT;"
764
765                 "-- ------------------------------------------------------"
766                 ;
767         
768         /* Skip protocol indicator of url  */
769         if ((p = strchr(url, ':')) == NULL) {
770                 return SQLITE_MISUSE;
771         } else {
772                 ++p;
773         }
774                 
775         /*
776          * See if we'll be creating a new database, or opening an existing one
777          */
778         if ((stat(p, &statbuf) < 0 && errno == ENOENT) ||
779             statbuf.st_size == 0) {
780
781                 bNewDatabase = True;
782         }
783
784         /* Try to open the (possibly empty/non-existent) database */
785         if ((ret = sqlite3_open(p, &lsqlite3->sqlite)) != SQLITE_OK) {
786                 return ret;
787         }
788
789         if (bNewDatabase) {
790                 /*
791                  * Create the database schema
792                  */
793                 for (pTail = discard_const_p(char, schema); pTail != NULL; ) {
794
795                         if ((ret = sqlite3_prepare(
796                                      lsqlite3->sqlite,
797                                      pTail,
798                                      -1,
799                                      &stmt,
800                                      &pTail)) != SQLITE_OK ||
801                             (ret = sqlite3_step(stmt)) != SQLITE_DONE ||
802                             (ret = sqlite3_finalize(stmt)) != SQLITE_OK) {
803
804                                 (void) sqlite3_close(lsqlite3->sqlite);
805                                 return ret;
806                         }
807                 }
808         } else {
809                 /*
810                  * Ensure that the database we opened is one of ours
811                  */
812                 if ((ret = sqlite3_prepare(
813                              lsqlite3->sqlite,
814                              "SELECT COUNT(*) "
815                              "  FROM sqlite_master "
816                              "  WHERE type = 'table' "
817                              "    AND name IN "
818                              "      ("
819                              "        'ldb_entry', "
820                              "        'ldb_descendants', "
821                              "        'ldb_object_classes' "
822                              "      );",
823                              -1,
824                              &stmt,
825                              &pTail)) != SQLITE_OK ||
826                     (ret = sqlite3_step(stmt)) != SQLITE_ROW ||
827                     sqlite3_column_int(stmt, 0) != 3 ||
828                     (ret = sqlite3_finalize(stmt)) != SQLITE_OK ||
829
830                     (ret = sqlite3_prepare(
831                              lsqlite3->sqlite,
832                              "SELECT 1 "
833                              "  FROM ldb_info "
834                              "  WHERE database_type = 'LDB' "
835                              "    AND version = '1.0';",
836                              -1,
837                              &stmt,
838                              &pTail)) != SQLITE_OK ||
839                     (ret = sqlite3_step(stmt)) != SQLITE_ROW ||
840                     (ret = sqlite3_finalize(stmt)) != SQLITE_OK) {
841                 
842                         /* It's not one that we created.  See ya! */
843                         (void) sqlite3_close(lsqlite3->sqlite);
844                         return SQLITE_MISUSE;
845                 }
846         }
847
848         return SQLITE_OK;
849 }
850
851 /*
852  * connect to the database
853  */
854 struct ldb_context *
855 lsqlite3_connect(const char *url, 
856                  unsigned int flags, 
857                  const char *options[])
858 {
859         int                         i;
860         int                         ret;
861         struct ldb_context *        ldb = NULL;
862         struct lsqlite3_private *   lsqlite3 = NULL;
863
864         ldb = talloc(NULL, struct ldb_context);
865         if (!ldb) {
866                 errno = ENOMEM;
867                 goto failed;
868         }
869
870         lsqlite3 = talloc(ldb, struct lsqlite3_private);
871         if (!lsqlite3) {
872                 errno = ENOMEM;
873                 goto failed;
874         }
875
876         lsqlite3->sqlite = NULL;
877         lsqlite3->options = NULL;
878         lsqlite3->lock_count = 0;
879
880         ret = lsqlite3_initialize(&lsqlite3, url);
881         if (ret != SQLITE_OK) {
882                 goto failed;
883         }
884
885         talloc_set_destructor(lsqlite3, lsqlite3_destructor);
886
887         ldb->modules = talloc(ldb, struct ldb_module);
888         if (!ldb->modules) {
889                 errno = ENOMEM;
890                 goto failed;
891         }
892         ldb->modules->ldb = ldb;
893         ldb->modules->prev = ldb->modules->next = NULL;
894         ldb->modules->private_data = lsqlite3;
895         ldb->modules->ops = &lsqlite3_ops;
896
897         if (options) {
898                 /*
899                  * take a copy of the options array, so we don't have to rely
900                  * on the caller keeping it around (it might be dynamic)
901                  */
902                 for (i=0;options[i];i++) ;
903
904                 lsqlite3->options = talloc_array(lsqlite3, char *, i+1);
905                 if (!lsqlite3->options) {
906                         goto failed;
907                 }
908                 
909                 for (i=0;options[i];i++) {
910
911                         lsqlite3->options[i+1] = NULL;
912                         lsqlite3->options[i] =
913                                 talloc_strdup(lsqlite3->options, options[i]);
914                         if (!lsqlite3->options[i]) {
915                                 goto failed;
916                         }
917                 }
918         }
919
920         return ldb;
921
922 failed:
923         if (lsqlite3->sqlite != NULL) {
924                 (void) sqlite3_close(lsqlite3->sqlite);
925         }
926         talloc_free(ldb);
927         return NULL;
928 }
929