summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c')
-rw-r--r--source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c243
1 files changed, 208 insertions, 35 deletions
diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
index 09ba24022f..51830db94c 100644
--- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
+++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
@@ -167,9 +167,11 @@ static int
parsetree_to_attrlist(struct lsqlite3_private * lsqlite3,
const struct ldb_parse_tree * t);
+#ifdef NEED_TABLE_LIST
static char *
build_attr_table_list(void * hTalloc,
struct lsqlite3_private * lsqlite3);
+#endif
static int
msg_to_sql(struct ldb_module * module,
@@ -295,36 +297,140 @@ failed:
/* rename a record */
static int
lsqlite3_rename(struct ldb_module * module,
- const char * olddn,
- const char * newdn)
+ const char * pOldDN,
+ const char * pNewDN)
{
- /* ignore ltdb specials */
- if (olddn[0] == '@' ||newdn[0] == '@') {
- return 0;
- }
-
-#warning "lsqlite3_rename() is not yet supported"
+ struct lsqlite3_private * lsqlite3 = module->private_data;
+
+ /* Case-fold each of the DNs */
+ pOldDN = ldb_dn_fold(module->ldb, pOldDN,
+ module, case_fold_attr_required);
+ pNewDN = ldb_dn_fold(module->ldb, pNewDN,
+ module, case_fold_attr_required);
- return -1;
+ QUERY_NOROWS(lsqlite3,
+ FALSE,
+ "UPDATE ldb_entry "
+ " SET dn = %Q "
+ " WHERE dn = %Q;",
+ pNewDN, pOldDN);
+
+ return 0;
}
/* delete a record */
static int
-lsqlite3_delete(struct ldb_module *module,
- const char *dn)
+lsqlite3_delete(struct ldb_module * module,
+ const char * pDN)
{
+ int ret;
+ int bLoop;
+ long long eid;
+ char * pSql;
+ const char * pAttrName;
+ sqlite3_stmt * pStmt;
struct lsqlite3_private * lsqlite3 = module->private_data;
- /* ignore ltdb specials */
- if (dn[0] == '@') {
- return 0;
- }
-
/* Begin a transaction */
QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;");
+ /* Determine the eid of the DN being deleted */
+ QUERY_INT(lsqlite3,
+ eid,
+ TRUE,
+ "SELECT eid\n"
+ " FROM ldb_entry\n"
+ " WHERE dn = %Q;",
+ pDN);
+
+ /* Obtain the list of attribute names in use by this DN */
+ if ((pSql = talloc_asprintf(module->ldb,
+ "SELECT attr_name "
+ " FROM ldb_attribute_values "
+ " WHERE eid = %lld;",
+ eid)) == NULL) {
+ return -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 */
+ for (ret = SQLITE_ROW; ret == SQLITE_ROW; ) {
+
+ /* Get the next row */
+ if ((ret = sqlite3_step(pStmt)) == SQLITE_ROW) {
+
+ /* Get the values from this row */
+ pAttrName = sqlite3_column_text(pStmt, 0);
+
+ /*
+ * Delete any entries from the specified
+ * attribute table that pertain to this eid.
+ */
+ QUERY_NOROWS(lsqlite3,
+ TRUE,
+ "DELETE FROM ldb_attr_%q "
+ " WHERE eid = %lld;",
+ pAttrName, eid);
+ }
+ }
+
+ 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;
+ }
+
+ /* Delete the descendants records */
+ QUERY_NOROWS(lsqlite3,
+ TRUE,
+ "DELETE FROM ldb_descendants "
+ " WHERE deid = %lld;",
+ eid);
-#warning "lsqlite3_delete() is not yet supported"
+ /* Delete attribute/value table entries pertaining to this DN */
+ QUERY_NOROWS(lsqlite3,
+ TRUE,
+ "DELETE FROM ldb_attribute_value "
+ " WHERE eid = %lld;",
+ eid);
/* Commit the transaction */
QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;");
@@ -348,7 +454,9 @@ lsqlite3_search_bytree(struct ldb_module * module,
long long prevEID;
char * pSql = NULL;
char * pSqlConstraints;
+#ifdef NEED_TABLE_LIST
char * pTableList;
+#endif
char * hTalloc = NULL;
const char * pDN;
const char * pAttrName;
@@ -362,6 +470,18 @@ lsqlite3_search_bytree(struct ldb_module * module,
pBaseDN = "";
}
+ /* Allocate a temporary talloc context */
+ if ((hTalloc = talloc_new(module->ldb)) == NULL) {
+ return -1;
+ }
+
+ /* Case-fold the base DN */
+ if ((pBaseDN = ldb_dn_fold(hTalloc, pBaseDN,
+ module, case_fold_attr_required)) == NULL) {
+ talloc_free(hTalloc);
+ return -1;
+ }
+
/* Begin a transaction */
QUERY_NOROWS(lsqlite3, FALSE, "BEGIN IMMEDIATE;");
@@ -375,19 +495,14 @@ lsqlite3_search_bytree(struct ldb_module * module,
" WHERE attr_value = %Q;",
pBaseDN)) == SQLITE_DONE) {
QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;");
+ talloc_free(hTalloc);
return 0;
} else if (ret != SQLITE_OK) {
QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;");
+ talloc_free(hTalloc);
return -1;
}
- /* Allocate a temporary talloc context */
- if ((hTalloc = talloc_new(module->ldb)) == NULL) {
- ret = -1;
- talloc_free(pTree);
- goto cleanup;
- }
-
/* Convert filter into a series of SQL conditions (constraints) */
pSqlConstraints = parsetree_to_sql(module, hTalloc, pTree);
@@ -453,14 +568,15 @@ lsqlite3_search_bytree(struct ldb_module * module,
goto cleanup;
}
+#ifdef NEED_TABLE_LIST
/*
* Build the attribute table list from the list of unique names.
*/
-
if ((pTableList = build_attr_table_list(hTalloc, lsqlite3)) == NULL) {
ret = -1;
goto cleanup;
}
+#endif
switch(scope) {
case LDB_SCOPE_DEFAULT:
@@ -534,6 +650,11 @@ lsqlite3_search_bytree(struct ldb_module * module,
break;
}
+ if (pSql == NULL) {
+ ret = -1;
+ goto cleanup;
+ }
+
if (lsqlite3_debug) {
printf("%s\n", pSql);
}
@@ -630,12 +751,12 @@ lsqlite3_search_bytree(struct ldb_module * module,
bLoop = FALSE;
}
- /* End the transaction */
- QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;");
-
/* We're alll done with this query */
sqlite3_free(pSql);
+ /* End the transaction */
+ QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;");
+
/* Were there any results? */
if (ret != 0 || allocated == 0) {
/* Nope. We can free the results. */
@@ -733,9 +854,11 @@ lsqlite3_add(struct ldb_module *module,
/* modify a record */
static int
-lsqlite3_modify(struct ldb_module *module,
- const struct ldb_message *msg)
+lsqlite3_modify(struct ldb_module * module,
+ const struct ldb_message * msg)
{
+ char * pDN;
+ long long eid;
struct lsqlite3_private * lsqlite3 = module->private_data;
/* ignore ltdb specials */
@@ -746,7 +869,25 @@ lsqlite3_modify(struct ldb_module *module,
/* Begin a transaction */
QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;");
-#warning "modify() not yet implemented"
+ /* Case-fold the DN so we can compare it to what's in the database */
+ pDN = ldb_dn_fold(module->ldb, msg->dn,
+ module, case_fold_attr_required);
+
+ /* Determine the eid of the DN being deleted */
+ QUERY_INT(lsqlite3,
+ eid,
+ TRUE,
+ "SELECT eid\n"
+ " FROM ldb_entry\n"
+ " WHERE dn = %Q;",
+ pDN);
+
+ /* Apply the message attributes */
+ if (msg_to_sql(module, msg, eid, TRUE) != 0) {
+ QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;");
+ return -1;
+ }
+
/* Everything worked. Commit it! */
QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;");
@@ -1409,7 +1550,8 @@ parsetree_to_sql(struct ldb_module *module,
}
child = ret;
- ret = talloc_asprintf("(\n"
+ ret = talloc_asprintf(hTalloc,
+ "(\n"
"%s\n"
")\n",
child);
@@ -1436,7 +1578,8 @@ parsetree_to_sql(struct ldb_module *module,
talloc_free(child);
}
child = ret;
- ret = talloc_asprintf("(\n"
+ ret = talloc_asprintf(hTalloc,
+ "(\n"
"%s\n"
")\n",
child);
@@ -1495,7 +1638,7 @@ parsetree_to_sql(struct ldb_module *module,
ret = talloc_strdup(hTalloc, p);
sqlite3_free(p);
-
+
} else if (strcasecmp(t->u.simple.attr, "objectclass") == 0) {
/*
* For object classes, we want to search for all objectclasses
@@ -1543,6 +1686,7 @@ parsetree_to_sql(struct ldb_module *module,
ret = talloc_strdup(hTalloc, p);
sqlite3_free(p);
}
+
return ret;
}
@@ -1619,6 +1763,7 @@ parsetree_to_attrlist(struct lsqlite3_private * lsqlite3,
}
+#ifdef NEED_TABLE_LIST
/*
* Use the already-generated FILTER_ATTR_TABLE to create a list of attribute
* table names that will be used in search queries.
@@ -1724,6 +1869,7 @@ build_attr_table_list(void * hTalloc,
return pTableList;
}
+#endif
/*
@@ -1847,6 +1993,7 @@ new_dn(struct ldb_module * module,
char * p;
char * pPartialDN;
long long eid;
+ long long peid;
struct ldb_dn * pExplodedDN;
struct ldb_dn_component * pComponent;
struct ldb_context * ldb = module->ldb;
@@ -1906,9 +2053,35 @@ new_dn(struct ldb_module * module,
nComponent == 0 ? "" : "OR IGNORE",
eid, pPartialDN);
- /* Get the EID of the just inserted row (the next parent) */
+ /* Save the parent EID */
+ peid = eid;
+
+ /* Get the EID of the just inserted row */
eid = sqlite3_last_insert_rowid(lsqlite3->sqlite);
+ /*
+ * Popoulate the descendant table
+ */
+
+ /* This table has an entry for itself as well as descendants */
+ QUERY_NOROWS(lsqlite3,
+ FALSE,
+ "INSERT INTO ldb_descendants "
+ " (aeid, deid) "
+ " VALUES "
+ " (%lld, %lld);",
+ eid, eid);
+
+ /* Now insert rows for all of our ancestors */
+ QUERY_NOROWS(lsqlite3,
+ FALSE,
+ "INSERT INTO ldb_descendants "
+ " (aeid, deid) "
+ " SELECT aeid, %lld "
+ " FROM ldb_descendants "
+ " WHERE aeid = %lld;",
+ eid, peid);
+
/* If this is the final component, also add DN attribute */
if (nComponent == 0) {
QUERY_NOROWS(lsqlite3,