diff options
Diffstat (limited to 'source4/lib/ldb/ldb_sqlite3')
-rw-r--r-- | source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 178 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_sqlite3/schema | 19 |
2 files changed, 153 insertions, 44 deletions
diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 556702a21d..d9e72c8089 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -290,6 +290,7 @@ lsqlite3_delete(struct ldb_module *module, return 0; } +#warning "lsqlite3_delete() is not yet supported" return -1; } @@ -302,11 +303,18 @@ lsqlite3_search(struct ldb_module * module, const char * const attrs[], struct ldb_message *** res) { + int ret; + int bLoop; long long eid = 0; - char * sql; - char * sql_constraints; - char * table_list; + long long prevEID; + char * pSql = NULL; + char * pSqlConstraints; + char * pTableList; char * hTalloc; + const char * pDN; + const char * pAttrName; + const char * pAttrValue; + sqlite3_stmt * pStmt; struct ldb_parse_tree * pTree; struct lsqlite3_private * lsqlite3 = module->private_data; @@ -340,17 +348,21 @@ lsqlite3_search(struct ldb_module * module, talloc_steal(hTalloc, pTree); /* Convert filter into a series of SQL statements (constraints) */ - sql_constraints = parsetree_to_sql(module, hTalloc, pTree); + pSqlConstraints = parsetree_to_sql(module, hTalloc, pTree); /* Get the list of attribute names to use as our extra table list */ - table_list = parsetree_to_tablelist(module, hTalloc, pTree); + pTableList = parsetree_to_tablelist(module, hTalloc, pTree); switch(scope) { case LDB_SCOPE_DEFAULT: case LDB_SCOPE_SUBTREE: - sql = sqlite3_mprintf( - "SELECT entry.entry_data\n" - " FROM ldb_entry AS entry\n" + pSql = sqlite3_mprintf( + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry,\n" + " ldb_attribute_values AS av\n" " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" " FROM ldb_entry,\n" @@ -358,55 +370,133 @@ lsqlite3_search(struct ldb_module * module, " %q\n" " WHERE ldb_descendants.aeid = %lld\n" " AND ldb_entry.eid = ldb_descendants.deid\n" - " AND ldap_entry.eid IN\n" - "%s" - ");", - table_list, + " AND ldap_entry.eid IN\n%s\n" + " ) " + " AND av.eid = entry.eid " + " ORDER BY av.eid, av.attr_name;", + pTableList, eid, - sql_constraints); + pSqlConstraints); break; case LDB_SCOPE_BASE: - sql = sqlite3_mprintf( - "SELECT entry.entry_data\n" - " FROM ldb_entry AS entry\n" + pSql = sqlite3_mprintf( + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry,\n" + " ldb_attribute_values AS av\n" " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" " FROM %q\n" " WHERE ldb_entry.eid = %lld\n" - " AND ldb_entry.eid IN\n" - "%s" - ");", - table_list, + " AND ldb_entry.eid IN\n%s\n" + " ) " + " AND av.eid = entry.eid " + " ORDER BY av.eid, av.attr_name;", + pTableList, eid, - sql_constraints); + pSqlConstraints); break; case LDB_SCOPE_ONELEVEL: - sql = sqlite3_mprintf( - "SELECT entry.entry_data\n" - " FROM ldb_entry AS entry\n" + pSql = sqlite3_mprintf( + "SELECT entry.eid,\n" + " entry.dn,\n" + " av.attr_name,\n" + " av.attr_value\n" + " FROM ldb_entry AS entry,\n" + " ldb_attribute_values AS av\n" " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" " FROM ldb_entry AS pchild, " " %q\n" " WHERE ldb_entry.eid = pchild.eid " " AND pchild.peid = %lld " - " AND ldb_entry.eid IN\n" - "%s" - ");", - table_list, + " AND ldb_entry.eid IN\n%s\n" + " ) " + " AND av.eid = entry.eid " + " ORDER BY av.eid, av.attr_name;", + pTableList, eid, - sql_constraints); + pSqlConstraints); break; } -#warning "retrieve and return the result set of the search here" + /* Initially, we have no old eid */ + prevEID = -1; + + /* + * Prepare and execute the SQL statement. Loop allows retrying on + * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes, + * requiring retrying the operation. + */ + for (bLoop = TRUE; bLoop; ) { + + /* Compile the SQL statement into sqlite virtual machine */ + if ((ret = sqlite3_prepare(lsqlite3->sqlite, + pSql, + -1, + &pStmt, + NULL)) == SQLITE_SCHEMA) { + continue; + } else if (ret != SQLITE_OK) { + ret = -1; + break; + } + + /* Loop through the returned rows */ + do { + /* Get the next row */ + if ((ret = sqlite3_step(pStmt)) == SQLITE_ROW) { + + /* Get the values from this row */ + eid = sqlite3_column_int64(pStmt, 0); + pDN = sqlite3_column_text(pStmt, 1); + pAttrName = sqlite3_column_text(pStmt, 2); + pAttrValue = sqlite3_column_text(pStmt, 3); + + /* Add this row data to the return results */ +#warning "finish returning the result set of the search here" + } + } while (ret == SQLITE_ROW); + + if (ret == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_DONE) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* Free the virtual machine */ + if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(pStmt); + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(pStmt); + ret = -1; + break; + } + + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + ret = 0; + bLoop = FALSE; + } + /* End the transaction */ QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;"); - return 0; + /* We're alll done with this query */ + sqlite3_free(pSql); + + return ret; } @@ -559,11 +649,7 @@ initialize(struct lsqlite3_private *lsqlite3, " create_timestamp INTEGER," " -- Time when the entry was last modified" - " modify_timestamp INTEGER," - - " -- Attributes of this entry, in the form" - " -- attr\1value\0[attr\1value\0]*\0" - " entry_data TEXT" + " modify_timestamp INTEGER" ");" @@ -604,6 +690,16 @@ initialize(struct lsqlite3_private *lsqlite3, ");" "/*" + " * We keep a full listing of attribute/value pairs here" + " */" + "CREATE TABLE ldb_attribute_values" + "(" + " eid INTEGER REFERENCES ldb_entry," + " attr_name TEXT, -- see ldb_attr_ATTRIBUTE_NAME" + " attr_value TEXT" + ");" + + "/*" " * There is one attribute table per searchable attribute." " */" "/*" @@ -793,7 +889,9 @@ query_norows(const struct lsqlite3_private *lsqlite3, pTail, -1, &pStmt, - &pTail)) != SQLITE_OK) { + &pTail)) == SQLITE_SCHEMA) { + continue; + } else if (ret != SQLITE_OK) { ret = -1; break; } @@ -878,12 +976,14 @@ query_int(const struct lsqlite3_private * lsqlite3, pTail, -1, &pStmt, - &pTail)) != SQLITE_OK) { + &pTail)) == SQLITE_SCHEMA) { + continue; + } else if (ret != SQLITE_OK) { ret = -1; break; } - /* No rows expected, so just step through machine code once */ + /* One row expected */ if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { (void) sqlite3_finalize(pStmt); continue; diff --git a/source4/lib/ldb/ldb_sqlite3/schema b/source4/lib/ldb/ldb_sqlite3/schema index dddca8d48f..b02b806150 100644 --- a/source4/lib/ldb/ldb_sqlite3/schema +++ b/source4/lib/ldb/ldb_sqlite3/schema @@ -37,11 +37,7 @@ create_timestamp INTEGER, -- Time when the entry was last modified - modify_timestamp INTEGER, - - -- Attributes of this entry, in the form - -- attr\1value\0[attr\1value\0]*\0 - entry_data TEXT + modify_timestamp INTEGER ); @@ -81,6 +77,19 @@ ); /* + * We keep a full listing of attribute/value pairs here + */ + CREATE TABLE ldb_attribute_values + ( + eid INTEGER REFERENCES ldb_entry, + + attr_name TEXT, -- see ldb_attr_ATTRIBUTE_NAME + + attr_value TEXT + ); + + + /* * There is one attribute table per searchable attribute. */ /* |