r7133: work in progress, including a HIGHLY revised and simplified schema
authorDerrell Lipman <derrell@samba.org>
Tue, 31 May 2005 03:31:54 +0000 (03:31 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:17:20 +0000 (13:17 -0500)
source/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
source/lib/ldb/ldb_sqlite3/schema

index a0ffffca9e70f9cf8bed2c5a4d9a314007cb6c3f..d36ced2667260bd8275f8c9b493d9abcf86d7457 100644 (file)
@@ -1,22 +1,22 @@
 /* 
    ldb database library
 /* 
    ldb database library
-
+   
    Copyright (C) Andrew Tridgell  2004
    Copyright (C) Andrew Tridgell  2004
-
-     ** NOTE! The following LGPL license applies to the ldb
-     ** library. This does NOT imply that all of Samba is released
-     ** under the LGPL
+   
+   ** NOTE! The following LGPL license applies to the ldb
+   ** library. This does NOT imply that all of Samba is released
+   ** under the LGPL
    
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.
    
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.
-
+   
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
-
+   
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
@@ -25,7 +25,7 @@
 /*
  *  Name: ldb
  *
 /*
  *  Name: ldb
  *
- *  Component: ldb sqlite backend
+ *  Component: ldb sqlite3 backend
  *
  *  Description: core files for SQLITE3 backend
  *
  *
  *  Description: core files for SQLITE3 backend
  *
 
 #undef SQL_EXEC                 /* just in case; not expected to be defined */
 #define SQL_EXEC(lsqlite3, query, reset)                        \
 
 #undef SQL_EXEC                 /* just in case; not expected to be defined */
 #define SQL_EXEC(lsqlite3, query, reset)                        \
-    do {                                                        \
-        lsqlite3->last_rc =                                     \
-                sqlite3_step(lsqlite3->queries.query);          \
-        if (lsqlite3->last_rc == SQLITE_BUSY || reset)          \
-                (void) sqlite3_reset(lsqlite3->queries.query);  \
-    } while lsqlite3->last_rc == SQLITE_BUSY;
+        do {                                                    \
+                lsqlite3->last_rc =                             \
+                        sqlite3_step(lsqlite3->queries.query);  \
+                if (lsqlite3->last_rc == SQLITE_BUSY || reset)  \
+                        (void) sqlite3_reset(lsqlite3->queries.query);  \
+        } while lsqlite3->last_rc == SQLITE_BUSY;
 
 
 
 #if 0
 /*
  * we don't need this right now, but will once we add some backend options
 
 
 
 #if 0
 /*
  * we don't need this right now, but will once we add some backend options
+ *
+ * find an option in an option list (a null terminated list of strings)
+ *
+ * this assumes the list is short. If it ever gets long then we really should
+ * do this in some smarter way
  */
  */
-
-/*
-  find an option in an option list (a null terminated list of strings)
-
-  this assumes the list is short. If it ever gets long then we really
-  should do this in some smarter way
- */
-static const char *lsqlite3_option_find(const struct lsqlite3_private *lsqlite3, const char *name)
+static const char *
+lsqlite3_option_find(const struct lsqlite3_private *lsqlite3,
+                     const char *name)
 {
 {
-       int i;
-       size_t len = strlen(name);
+       int                 i;
+       size_t              len = strlen(name);
 
        if (!lsqlite3->options) return NULL;
 
 
        if (!lsqlite3->options) return NULL;
 
@@ -80,10 +80,13 @@ static const char *lsqlite3_option_find(const struct lsqlite3_private *lsqlite3,
 /*
  * rename a record
  */
 /*
  * rename a record
  */
-static int lsqlite3_rename(struct ldb_module *module, const char *olddn, const char *newdn)
+static int
+lsqlite3_rename(struct ldb_module *module,
+                const char *olddn,
+                const char *newdn)
 {
 {
-        int column;
-       struct lsqlite3_private *lsqlite3 = module->private_data;
+        int                         column;
+       struct lsqlite3_private *   lsqlite3 = module->private_data;
 
        /* ignore ltdb specials */
        if (olddn[0] == '@' ||newdn[0] == '@') {
 
        /* ignore ltdb specials */
        if (olddn[0] == '@' ||newdn[0] == '@') {
@@ -117,11 +120,13 @@ static int lsqlite3_rename(struct ldb_module *module, const char *olddn, const c
 /*
  * delete a record
  */
 /*
  * delete a record
  */
-static int lsqlite3_delete(struct ldb_module *module, const char *dn)
+static int
+lsqlite3_delete(struct ldb_module *module,
+                const char *dn)
 {
 {
-       int ret = 0;
-        int column;
-       struct lsqlite3_private *lsqlite3 = module->private_data;
+       int                         ret = 0;
+        int                         column;
+       struct lsqlite3_private *   lsqlite3 = module->private_data;
 
        /* ignore ltdb specials */
        if (dn[0] == '@') {
 
        /* ignore ltdb specials */
        if (dn[0] == '@') {
@@ -146,7 +151,9 @@ static int lsqlite3_delete(struct ldb_module *module, const char *dn)
 /*
  * free a search result
  */
 /*
  * free a search result
  */
-static int lsqlite3_search_free(struct ldb_module *module, struct ldb_message **res)
+static int
+lsqlite3_search_free(struct ldb_module *module,
+                     struct ldb_message **res)
 {
        talloc_free(res);
        return 0;
 {
        talloc_free(res);
        return 0;
@@ -156,12 +163,15 @@ static int lsqlite3_search_free(struct ldb_module *module, struct ldb_message **
 /*
  * add a single set of ldap message values to a ldb_message
  */
 /*
  * add a single set of ldap message values to a ldb_message
  */
-static int lsqlite3_add_msg_attr(struct ldb_context *ldb,
-                            struct ldb_message *msg, 
-                            const char *attr, struct berval **bval)
+static int
+lsqlite3_add_msg_attr(struct ldb_context *ldb,
+                      struct ldb_message *msg, 
+                      const char *attr,
+                      struct berval **bval)
 {
 {
-       int count, i;
-       struct ldb_message_element *el;
+        int                          i;
+       int                          count;
+       struct ldb_message_element * el;
 
        count = ldap_count_values_len(bval);
 
 
        count = ldap_count_values_len(bval);
 
@@ -211,13 +221,18 @@ static int lsqlite3_add_msg_attr(struct ldb_context *ldb,
 /*
  * search for matching records
  */
 /*
  * search for matching records
  */
-static int lsqlite3_search(struct ldb_module *module, const char *base,
-                      enum ldb_scope scope, const char *expression,
-                      const char * const *attrs, struct ldb_message ***res)
+static int
+lsqlite3_search(struct ldb_module *module,
+                const char *base,
+                enum ldb_scope scope,
+                const char *expression,
+                const char * const *attrs,
+                struct ldb_message ***res)
 {
 {
-       struct ldb_context *ldb = module->ldb;
-       struct lsqlite3_private *lsqlite3 = module->private_data;
-       int count, msg_count;
+       int                       count;
+        int                       msg_count;
+       struct ldb_context *      ldb = module->ldb;
+       struct lsqlite3_private * lsqlite3 = module->private_data;
 
        if (base == NULL) {
                base = "";
 
        if (base == NULL) {
                base = "";
@@ -316,16 +331,18 @@ failed:
  * Issue a series of SQL statements to implement the ADD/MODIFY/DELETE
  * requests in the ldb_message
  */
  * Issue a series of SQL statements to implement the ADD/MODIFY/DELETE
  * requests in the ldb_message
  */
-static int lsqlite3_msg_to_sql(struct ldb_context *ldb,
-                               const struct ldb_message *msg,
-                               long long dn_id,
-                               int use_flags)
+static int
+lsqlite3_msg_to_sql(struct ldb_context *ldb,
+                    const struct ldb_message *msg,
+                    long long dn_id,
+                    int use_flags)
 {
 {
-        int flags;
-       unsigned int i, j;
-       struct ldb_context *ldb = module->ldb;
-       struct lsqlite3_private *lsqlite3 = module->private_data;
-        sqlite3_stmt *stmt = NULL;
+        int                         flags;
+       unsigned int                i;
+        unsigned int                j;
+        sqlite3_stmt *              stmt = NULL;
+       struct ldb_context *        ldb = module->ldb;
+       struct lsqlite3_private *   lsqlite3 = module->private_data;
 
        for (i = 0; i < msg->num_elements; i++) {
                const struct ldb_message_element *el = &msg->elements[i];
 
        for (i = 0; i < msg->num_elements; i++) {
                const struct ldb_message_element *el = &msg->elements[i];
@@ -428,11 +445,13 @@ static int lsqlite3_msg_to_sql(struct ldb_context *ldb,
 /*
  * add a record
  */
 /*
  * add a record
  */
-static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg)
+static int
+lsqlite3_add(struct ldb_module *module,
+             const struct ldb_message *msg)
 {
 {
-       struct ldb_context *ldb = module->ldb;
-       struct lsqlite3_private *lsqlite3 = module->private_data;
-       int ret;
+       int                         ret;
+       struct ldb_context *        ldb = module->ldb;
+       struct lsqlite3_private *   lsqlite3 = module->private_data;
 
        /* ignore ltdb specials */
        if (msg->dn[0] == '@') {
 
        /* ignore ltdb specials */
        if (msg->dn[0] == '@') {
@@ -482,12 +501,13 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg
 /*
  * modify a record
  */
 /*
  * modify a record
  */
-static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *msg)
+static int
+lsqlite3_modify(struct ldb_module *module,
+                const struct ldb_message *msg)
 {
 {
-       struct ldb_context *ldb = module->ldb;
-       struct lsqlite3_private *lsqlite3 = module->private_data;
-       LDAPMod **mods;
-       int ret = 0;
+       int                         ret = 0;
+       struct ldb_context *        ldb = module->ldb;
+       struct lsqlite3_private *   lsqlite3 = module->private_data;
 
        /* ignore ltdb specials */
        if (msg->dn[0] == '@') {
 
        /* ignore ltdb specials */
        if (msg->dn[0] == '@') {
@@ -538,11 +558,13 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *
         return lsqlite3->last_rc == SQLITE_DONE && ret == 0 ? 0 : -1;
 }
 
         return lsqlite3->last_rc == SQLITE_DONE && ret == 0 ? 0 : -1;
 }
 
-static int lsqlite3_lock(struct ldb_module *module, const char *lockname)
+static int
+lsqlite3_lock(struct ldb_module *module,
+              const char *lockname)
 {
 {
-       int ret = 0;
-       struct ldb_context *ldb = module->ldb;
-       struct lsqlite3_private *lsqlite3 = module->private_data;
+       int                         ret = 0;
+       struct ldb_context *        ldb = module->ldb;
+       struct lsqlite3_private *   lsqlite3 = module->private_data;
 
        if (lockname == NULL) {
                return -1;
 
        if (lockname == NULL) {
                return -1;
@@ -559,11 +581,13 @@ static int lsqlite3_lock(struct ldb_module *module, const char *lockname)
        return lsqlite3->last_rc == 0 ? 0 : -1;
 }
 
        return lsqlite3->last_rc == 0 ? 0 : -1;
 }
 
-static int lsqlite3_unlock(struct ldb_module *module, const char *lockname)
+static int
+lsqlite3_unlock(struct ldb_module *module,
+                const char *lockname)
 {
 {
-       int ret = 0;
-       struct ldb_context *ldb = module->ldb;
-       struct lsqlite3_private *lsqlite3 = module->private_data;
+       int                         ret = 0;
+       struct ldb_context *        ldb = module->ldb;
+       struct lsqlite3_private *   lsqlite3 = module->private_data;
 
        if (lockname == NULL) {
                return -1;
 
        if (lockname == NULL) {
                return -1;
@@ -587,9 +611,11 @@ static int lsqlite3_unlock(struct ldb_module *module, const char *lockname)
 /*
  * return extended error information
  */
 /*
  * return extended error information
  */
-static const char *lsqlite3_errstring(struct ldb_module *module)
+static const char *
+lsqlite3_errstring(struct ldb_module *module)
 {
 {
-       struct lsqlite3_private *lsqlite3 = module->private_data;
+       struct lsqlite3_private *   lsqlite3 = module->private_data;
+
        return sqlite3_errmsg(lsqlite3->sqlite3);
 }
 
        return sqlite3_errmsg(lsqlite3->sqlite3);
 }
 
@@ -608,22 +634,25 @@ static const struct ldb_module_ops lsqlite3_ops = {
 };
 
 
 };
 
 
-static int lsqlite3_destructor(void *p)
+static int
+lsqlite3_destructor(void *p)
 {
 {
-       struct lsqlite3_private *lsqlite3 = p;
+       struct lsqlite3_private *   lsqlite3 = p;
+
         (void) sqlite3_close(lsqlite3->sqlite3);
        return 0;
 }
 
         (void) sqlite3_close(lsqlite3->sqlite3);
        return 0;
 }
 
-static int lsqlite3_initialize(lsqlite3_private *lsqlite3,
-                               const char *url)
+static int
+lsqlite3_initialize(lsqlite3_private *lsqlite3,
+                    const char *url)
 {
 {
-        int bNewDatabase = False;
-        char *p;
-        char *pTail;
-        struct stat statbuf;
-        sqlite3_stmt *stmt;
-        const char *schema =
+        int             bNewDatabase = False;
+        char *          p;
+        char *          pTail;
+        struct stat     statbuf;
+        sqlite3_stmt *  stmt;
+        const char *    schema =       
                 "
                 -- ------------------------------------------------------
 
                 "
                 -- ------------------------------------------------------
 
@@ -983,13 +1012,14 @@ static int lsqlite3_initialize(lsqlite3_private *lsqlite3,
 /*
  * connect to the database
  */
 /*
  * connect to the database
  */
-struct ldb_context *lsqlite3_connect(const char *url, 
-                                     unsigned int flags, 
-                                     const char *options[])
+struct ldb_context *
+lsqlite3_connect(const char *url, 
+                 unsigned int flags, 
+                 const char *options[])
 {
 {
-       struct ldb_context *ldb = NULL;
-       struct lsqlite3_private *lsqlite3 = NULL;
-       int i;
+       int                         i;
+       struct ldb_context *        ldb = NULL;
+       struct lsqlite3_private *   lsqlite3 = NULL;
 
        ldb = talloc(NULL, struct ldb_context);
        if (!ldb) {
 
        ldb = talloc(NULL, struct ldb_context);
        if (!ldb) {
index d06d7d0c3435b5525ad8eef002854e9c23fa1078..45be5b578f4b0a01a06c5703a37984ae0a1546bc 100644 (file)
                   SELECT 'LDB' AS database_type, 
                          '1.0' AS version;
 
                   SELECT 'LDB' AS database_type, 
                          '1.0' AS version;
 
-                CREATE TABLE ldb_distinguished_names 
+                /*
+                 * Get the next USN value with:
+                 *   BEGIN EXCLUSIVE;
+                 *   UPDATE usn SET value = value + 1;
+                 *   SELECT value FROM usn;
+                 *   COMMIT;
+                 */
+                CREATE TABLE usn
                 (
                 (
-                  dn_id         INTEGER PRIMARY KEY AUTOINCREMENT, 
-                  dn            TEXT UNIQUE
+                  value           INTEGER
                 );
 
                 );
 
-                CREATE TABLE ldb_object_classes 
+                CREATE TABLE ldb_object
                 (
                 (
-                  class_name    TEXT PRIMARY KEY,
-                  tree_key      TEXT,
-                  max_child_num INTEGER
-                );
-
-                CREATE TABLE ldb_dn_object_classes 
-                (
-                  dn_id         INTEGER REFERENCES ldb_distinguished_names, 
-                  class_name    TEXT REFERENCES ldb_object_classes 
+                  /* tree_key is auto-generated by the insert trigger */
+                  tree_key        TEXT PRIMARY KEY,
+
+                  parent_tree_key TEXT,
+                  full_path       TEXT,
+
+                  attr_name       TEXT REFERENCES ldb_attributes,
+                  attr_value      TEXT,
+
+                  /*
+                   * object_type can take on these values (to date):
+                   *   1: object is a node of a DN
+                   *   2: object is an attribute/value pair of its parent DN
+                   */
+                  object_type     INTEGER,
+
+                  /*
+                   * if object_type is 1, the node can have children.
+                   * this tracks the maximum previously assigned child
+                   * number so we can generate a new unique tree key for
+                   * a new child object.  note that this is always incremented,
+                   * so if children are deleted, this will not represent
+                   * the _number_ of children.
+                   */
+                  max_child_num   INTEGER,
+
+                  /*
+                   * Automatically maintained meta-data (a gift for metze)
+                   */
+                  object_guid     TEXT UNIQUE,
+                  timestamp       INTEGER,  -- originating_time
+                  invoke_id       TEXT,     -- GUID: originating_invocation_id
+                  usn             INTEGER,  -- hyper: originating_usn
+
+                  /* do not allow duplicate name/value pairs */
+                  UNIQUE (parent_tree_key, attr_name, attr_value, object_type)
                 );
 
                 CREATE TABLE ldb_attributes
                 (
                   attr_name             TEXT PRIMARY KEY,
                 );
 
                 CREATE TABLE ldb_attributes
                 (
                   attr_name             TEXT PRIMARY KEY,
-                  case_insensitive_p    BOOLEAN DEFAULT FALSE,
-                  wildcard_p            BOOLEAN DEFAULT FALSE,
-                  hidden_p              BOOLEAN DEFAULT FALSE,
-                  integer_p             BOOLEAN DEFAULT FALSE
-                );
+                  parent_tree_key       TEXT,
 
 
-                CREATE TABLE ldb_attr_value_pairs 
-                (
-                  dn_id         INTEGER REFERENCES ldb_distinguished_names, 
-                  attr_name     TEXT, -- optionally REFERENCES ldb_attributes
-                  attr_value    TEXT,
+                  objectclass_p         BOOLEAN DEFAULT 0,
+
+                  case_insensitive_p    BOOLEAN DEFAULT 0,
+                  wildcard_p            BOOLEAN DEFAULT 0,
+                  hidden_p              BOOLEAN DEFAULT 0,
+                  integer_p             BOOLEAN DEFAULT 0,
 
 
-                  UNIQUE (dn_id, attr_name, attr_value)
+                  /* tree_key is auto-generated by the insert trigger */
+                  tree_key              TEXT, -- null if not a object/sub class
+                                              -- level 1 if an objectclass
+                                              -- level 1-n if a subclass
+                  max_child_num         INTEGER
                 );
 
                 -- ------------------------------------------------------
 
                 );
 
                 -- ------------------------------------------------------
 
-                CREATE TRIGGER ldb_distinguished_names_delete_tr
-                  AFTER DELETE
-                  ON ldb_distinguished_names
+                CREATE INDEX ldb_object_full_path_idx
+                  ON ldb_object (full_path);
+
+                CREATE INDEX ldb_attributes_tree_key_ids
+                  ON ldb_attributes (tree_key);
+
+                -- ------------------------------------------------------
+
+                /* Gifts for metze.  Automatically updated meta-data */
+                CREATE TRIGGER ldb_object_insert_tr
+                  AFTER INSERT
+                  ON ldb_object
                   FOR EACH ROW
                     BEGIN
                   FOR EACH ROW
                     BEGIN
-                      DELETE FROM ldb_attr_value_pairs
-                        WHERE dn_id = old.dn_id;
-                      DELETE FROM ldb_dn_object_classes
-                        WHERE dn_id = old.dn_id;
+                      UPDATE ldb_object
+                        SET max_child_num = max_child_num + 1
+                        WHERE tree_key = new.parent_tree_key;
+                      UPDATE usn SET value = value + 1;
+                      UPDATE ldb_object
+                        SET tree_key =
+                              (SELECT
+                                 new.tree_key ||
+                                 base160(SELECT max_child_num
+                                           FROM ldb_object
+                                           WHERE tree_key =
+                                                 new.parent_tree_key));
+                            max_child_num = 0,
+                            object_guid = random_guid(),
+                            timestamp = strftime('%s', 'now'),
+                            usn = (SELECT value FROM usn);
+                        WHERE tree_key = new.tree_key;
                     END;
 
                     END;
 
-                CREATE TRIGGER ldb_attr_value_pairs_insert_tr
-                  BEFORE INSERT
-                  ON ldb_attr_value_pairs
+                CREATE TRIGGER ldb_object_update_tr
+                  AFTER UPDATE
+                  ON ldb_object
                   FOR EACH ROW
                     BEGIN
                   FOR EACH ROW
                     BEGIN
-                      INSERT OR IGNORE INTO ldb_attributes
-                          (attr_name)
-                        VALUES
-                          (new.attr_name);
+                      UPDATE usn SET value = value + 1;
+                      UPDATE ldb_object
+                        SET timestamp = strftime('%s', 'now'),
+                            usn = (SELECT value FROM usn);
+                        WHERE tree_key = new.tree_key;
                     END;
 
                     END;
 
-                CREATE TRIGGER ldb_attr_value_pairs_delete_tr
-                  AFTER DELETE
-                  ON ldb_attr_value_pairs
+                CREATE TRIGGER ldb_attributes_insert_tr
+                  AFTER INSERT
+                  ON ldb_attributes
                   FOR EACH ROW
                     BEGIN
                   FOR EACH ROW
                     BEGIN
-                      DELETE FROM ldb_attributes
-                        WHERE (SELECT COUNT(*)
-                                 FROM ldb_attr_value_pairs
-                                 WHERE attr_name = old.attr_name) = 0
-                          AND attr_name = old.attr_name;
+                      UPDATE ldb_attributes
+                        SET max_child_num = max_child_num + 1
+                        WHERE tree_key = new.parent_tree_key;
+                      UPDATE ldb_attributes
+                        SET tree_key =
+                              (SELECT
+                                 new.tree_key ||
+                                 base160(SELECT max_child_num
+                                           FROM ldb_attributes
+                                           WHERE tree_key =
+                                                 new.parent_tree_key));
+                            max_child_num = 0
+                        WHERE tree_key = new.tree_key;
                     END;
 
                     END;
 
-                -- ------------------------------------------------------
-
-                CREATE INDEX ldb_distinguished_names_dn_idx
-                  ON ldb_distinguished_names (dn);
-
-                CREATE INDEX ldb_object_classes_tree_key_idx
-                  ON ldb_object_classes (tree_key);
-
-
-                CREATE INDEX ldb_dn_object_classes_dn_id_idx
-                  ON ldb_dn_object_classes (dn_id);
-
-                CREATE INDEX ldb_dn_object_classes_class_name_idx
-                  ON ldb_dn_object_classes (class_name);
-
-
-                CREATE INDEX ldb_attr_value_pairs_dn_id_name_case_idx
-                  ON ldb_attr_value_pairs (dn_id, attr_name);
-
-                CREATE INDEX ldb_attr_value_pairs_dn_id_name_nocase_idx
-                  ON ldb_attr_value_pairs (dn_id, attr_name COLLATE NOCASE);
 
                 -- ------------------------------------------------------
 
 
                 -- ------------------------------------------------------
 
-                /* all defaults for dn, initially */
-                INSERT INTO ldb_attributes (attr_name)
-                  VALUES ('dn');
+                /* Initialize usn */
+                INSERT INTO usn (value) VALUES (0);
+
+                /* Create root object */
+                INSERT INTO ldb_object
+                    (tree_key, parent_tree_key,
+                     full_path,
+                     object_type, max_child_num)
+                  VALUES ('', NULL,
+                          '',
+                          1, 0);
 
                 /* We need an implicit "top" level object class */
 
                 /* We need an implicit "top" level object class */
-                INSERT INTO ldb_object_classes (class_name, tree_key)
-                  SELECT 'top', /* next_tree_key(NULL) */ '0001';
+                INSERT INTO ldb_attributes (attr_name,
+                                            parent_tree_key)
+                  SELECT 'top', '';
 
                 -- ------------------------------------------------------
 
 
                 -- ------------------------------------------------------
 
  * objectclass: domainRelatedObject
  */
 -- newDN
  * objectclass: domainRelatedObject
  */
 -- newDN
-INSERT INTO ldb_distinguished_names (dn_id, dn)
-  VALUES (1, 'o=University of Michigan,c=US');
+BEGIN;
+
+INSERT OR IGNORE INTO ldb_object
+    (parent_tree_key
+     full_path,
+     attr_name, attr_value, object_type, max_child_num)
+  VALUES ('',
+          'c=US',
+          'c', 'US', 1, 0);
+
+INSERT INTO ldb_object
+    (parent_tree_key,
+     full_path,
+     attr_name, attr_value, object_type, max_child_num)
+  VALUES ('0001',
+          'o=University of Michigan,c=US',
+          'o', 'University of Michigan', 1, 0);
 
 -- newObjectClass
 
 -- newObjectClass
-INSERT OR IGNORE INTO ldb_object_classes (class_name, tree_key)
-  SELECT 'organization', /* next_tree_key(NULL) */ '0002';
-
-INSERT OR IGNORE INTO ldb_object_classes (class_name, tree_key)
-  SELECT 'domainRelatedObject', /* next_tree_key(NULL) */ '0003';
+INSERT OR IGNORE INTO ldb_attributes
+    (attr_name, parent_tree_key, objectclass_p)
+  VALUES
+    ('objectclass', '', 1);
+
+INSERT INTO ldb_object
+    (parent_tree_key,
+     full_path,
+     attr_name, attr_value, object_type, max_child_num)
+  VALUES ('00010001',
+          NULL,
+          'objectclass', 'organization', 2, 0);
+
+INSERT OR IGNORE INTO ldb_attributes
+    (attr_name, parent_tree_key, objectclass_p)
+  VALUES
+    ('objectclass', '', 1);
+
+INSERT INTO ldb_object
+    (parent_tree_key,
+     full_path,
+     attr_name, attr_value, object_type, max_child_num)
+  VALUES ('00010001',
+          NULL,
+          'objectclass', 'domainRelatedObject', 2, 0);
+
+COMMIT;
 
 
--- assignObjectClass
-INSERT OR IGNORE INTO ldb_dn_object_classes (dn_id, class_name)
-  VALUES (1, 'organization');
-
-INSERT OR IGNORE INTO ldb_dn_object_classes (dn_id, class_name)
-  VALUES (1, 'domainRelatedObject');
 
 /*
 
 /*
+ * dn: o=University of Michigan,c=US
  * l: Ann Arbor, Michigan
  * st: Michigan
  * o: University of Michigan
  * o: UMICH
  * l: Ann Arbor, Michigan
  * st: Michigan
  * o: University of Michigan
  * o: UMICH
- * o: UM
- * o: U-M
- * o: U of M
- * description: The University of Michigan at Ann Arbor
  * seeAlso:
  * seeAlso:
- * postaladdress: University of Michigan $ 535 W. William St. $ Ann Arbor, MI 481
- *  09 $ US
  * telephonenumber: +1 313 764-1817
  * telephonenumber: +1 313 764-1817
- * associateddomain: example.com
  */
 -- addAttrValuePair
  */
 -- addAttrValuePair
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'l', 'Ann Arbor, Michigan');
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'st', 'Michigan');
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'o', 'University of Michigan');
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'o', 'UMICH');
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'o', 'UM');
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'o', 'U-M');
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'o', 'U of M');
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'description', 'The University of Michigan at Ann Arbor');
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'seeAlso', '');
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'postaladdress', 'University of Michigan $ 535 W. William St. $ Ann Arbor, MI 48109 $ US');
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'telephonenumber', '+1 313 764-1817');
-INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
-  VALUES (1, 'associateddomain', 'example.com');
+BEGIN;
+
+INSERT INTO ldb_object
+    (parent_tree_key, full_path,
+     attr_name, attr_value, object_type, max_child_num)
+  VALUES ('00010001', NULL,
+          'l', 'Ann Arbor, Michigan', 2, 0);
+
+INSERT INTO ldb_object
+    (parent_tree_key, full_path,
+     attr_name, attr_value, object_type, max_child_num)
+  VALUES ('00010001', NULL,
+          'st', 'Michigan', 2, 0);
+
+INSERT INTO ldb_object
+    (parent_tree_key, full_path,
+     attr_name, attr_value, object_type, max_child_num)
+  VALUES ('00010001', NULL,
+          'o', 'University of Michigan', 2, 0);
+
+INSERT INTO ldb_object
+    (parent_tree_key, full_path,
+     attr_name, attr_value, object_type, max_child_num)
+  VALUES ('00010001', NULL,
+          'o', 'UMICH', 2, 0);
+
+INSERT INTO ldb_object
+    (parent_tree_key, full_path,
+     attr_name, attr_value, object_type, max_child_num)
+  VALUES ('00010001', NULL,
+          'seeAlso', '', 2, 0);
+
+INSERT INTO ldb_object
+    (parent_tree_key, full_path,
+     attr_name, attr_value, object_type, max_child_num)
+  VALUES ('00010001', NULL,
+          'telephonenumber', '+1 313 764-1817', 2, 0);
+
+COMMIT;
 
 -- ----------------------------------------------------------------------
 
 
 -- ----------------------------------------------------------------------
 
@@ -197,18 +290,41 @@ INSERT INTO ldb_attr_value_pairs (dn_id, attr_name, attr_value)
  * dn: CASE_INSENSITIVE
  */
 -- newAttribute
  * dn: CASE_INSENSITIVE
  */
 -- newAttribute
-INSERT OR REPLACE INTO ldb_attributes
-    (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p)
-  VALUES ('uid', 1, 1, 0, 0);
-INSERT OR REPLACE INTO ldb_attributes
-    (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p)
-  VALUES ('cn', 1, 0, 0, 0);
-INSERT OR REPLACE INTO ldb_attributes
-    (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p)
-  VALUES ('ou', 1, 0, 0, 0);
-INSERT OR REPLACE INTO ldb_attributes
-    (attr_name, case_insensitive_p, wildcard_p, hidden_p, integer_p)
-  VALUES ('dn', 1, 0, 0, 0);
+
+BEGIN;
+
+INSERT OR IGNORE INTO ldb_attributes
+    (attr_name, parent_tree_key, objectclass_p)
+  VALUES
+    ('uid', '', 0);
+
+UPDATE ldb_attributes
+  SET case_insensitive_p = 1,
+      wildcard_p = 1,
+      hidden_p = 0,
+      integer_p = 0
+  WHERE attr_name = 'uid'
+
+UPDATE ldb_attributes
+  SET case_insensitive_p = 1,
+      wildcard_p = 0,
+      hidden_p = 0,
+      integer_p = 0
+  WHERE attr_name = 'cn'
+
+UPDATE ldb_attributes
+  SET case_insensitive_p = 1,
+      wildcard_p = 0,
+      hidden_p = 0,
+      integer_p = 0
+  WHERE attr_name = 'ou'
+
+UPDATE ldb_attributes
+  SET case_insensitive_p = 1,
+      wildcard_p = 0,
+      hidden_p = 0,
+      integer_p = 0
+  WHERE attr_name = 'dn'
 
 -- ----------------------------------------------------------------------
 
 
 -- ----------------------------------------------------------------------
 
@@ -224,6 +340,10 @@ INSERT OR REPLACE INTO ldb_attributes
  * user: computer
  */
 -- insertSubclass
  * user: computer
  */
 -- insertSubclass
+
+/* NOT YET UPDATED!!! *
+
+
 INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
   SELECT 'domain', /* next_tree_key('top') */ '00010001';
 INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
 INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
   SELECT 'domain', /* next_tree_key('top') */ '00010001';
 INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
@@ -240,3 +360,4 @@ INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
   SELECT 'OpenLDAPperson', /* next_tree_key('organizationPerson') */ '0001000200010002';
 INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
   SELECT 'computer', /* next_tree_key('user') */ '0001000200010001';
   SELECT 'OpenLDAPperson', /* next_tree_key('organizationPerson') */ '0001000200010002';
 INSERT OR REPLACE INTO ldb_object_classes (class_name, tree_key)
   SELECT 'computer', /* next_tree_key('user') */ '0001000200010001';