diff options
-rw-r--r-- | source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 312 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h | 8 | ||||
-rw-r--r-- | source4/lib/ldb/tools/cmdline.c | 5 |
3 files changed, 223 insertions, 102 deletions
diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index 019c0eebf1..76ef703ca5 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -84,6 +84,16 @@ } \ } while (0) +#define GET_EID(lsqlite3, result_var, bRollbackOnError, pDN) \ + do { \ + if (getEID(lsqlite3, &result_var, pDN) != 0) { \ + if (bRollbackOnError) { \ + UNLOCK_DB(module, "rollback"); \ + } \ + return -1; \ + } \ + } while (0) + #define SQLITE3_DEBUG_QUERY (1 << 0) #define SQLITE3_DEBUG_INIT (1 << 1) @@ -95,6 +105,7 @@ * Static variables */ static int lsqlite3_debug = FALSE; +sqlite3_stmt * stmtGetEID = NULL; /* * Forward declarations @@ -161,6 +172,11 @@ query_int(const struct lsqlite3_private * lsqlite3, const char * pSql, ...); +static int +getEID(const struct lsqlite3_private * lsqlite3, + long long * pRet, + const char * pNormalizedDN); + static int case_fold_attr_required(void * hUserData, char *attr); @@ -336,10 +352,10 @@ lsqlite3_rename(struct ldb_module * module, } /* Case-fold each of the DNs */ - pOldNormalizedDN = ldb_dn_fold(module->ldb, pOldDN, - module, case_fold_attr_required); - pNewNormalizedDN = ldb_dn_fold(module->ldb, pNewDN, - module, case_fold_attr_required); + pOldNormalizedDN = + ldb_dn_fold(module->ldb, pOldDN, module, case_fold_attr_required); + pNewNormalizedDN = + ldb_dn_fold(module->ldb, pNewDN, module, case_fold_attr_required); /* Begin a transaction */ if (LOCK_DB(module, "transaction") < 0) { @@ -347,13 +363,7 @@ lsqlite3_rename(struct ldb_module * module, } /* Determine the eid of the DN being renamed */ - QUERY_INT(lsqlite3, - eid, - TRUE, - "SELECT eid\n" - " FROM ldb_entry\n" - " WHERE normalized_dn = %Q;", - pOldNormalizedDN); + GET_EID(lsqlite3, eid, TRUE, pOldNormalizedDN); QUERY_NOROWS(lsqlite3, TRUE, @@ -403,17 +413,11 @@ lsqlite3_delete(struct ldb_module * module, } /* Case-fold the DNs */ - pNormalizedDN = ldb_dn_fold(module->ldb, pDN, module, case_fold_attr_required); + pNormalizedDN = + ldb_dn_fold(module->ldb, pDN, module, case_fold_attr_required); /* Determine the eid of the DN being deleted */ - QUERY_INT(lsqlite3, - eid, - TRUE, - "SELECT eid\n" - " FROM ldb_attribute_values\n" - " WHERE attr_name = 'DN'\n" - " AND attr_value_normalized = %Q;", - pNormalizedDN); + GET_EID(lsqlite3, eid, TRUE, pNormalizedDN); /* Delete attribute/value table entries pertaining to this DN */ QUERY_NOROWS(lsqlite3, @@ -470,26 +474,26 @@ lsqlite3_search_bytree(struct ldb_module * module, } /* Case-fold the base DN */ - if ((pNormalizedBaseDN = ldb_dn_fold(hTalloc, pBaseDN?pBaseDN:"", - module, case_fold_attr_required)) == NULL) { + if ((pNormalizedBaseDN = + ldb_dn_fold(hTalloc, + pBaseDN == NULL ? "" : pBaseDN, + module, + case_fold_attr_required)) == NULL) { + talloc_free(hTalloc); return -1; } /* Begin a transaction */ if (LOCK_DB(module, "transaction") < 0) { + talloc_free(hTalloc); return -1; } /* * Obtain the eid of the base DN */ - if ((ret = query_int(lsqlite3, - &eid, - "SELECT eid\n" - " FROM ldb_entry\n" - " WHERE normalized_dn = %Q;", - pNormalizedBaseDN)) == SQLITE_DONE) { + if ((ret = getEID(lsqlite3, &eid, pNormalizedBaseDN)) == SQLITE_DONE) { UNLOCK_DB(module, "rollback"); talloc_free(hTalloc); return 0; @@ -685,9 +689,15 @@ lsqlite3_search_bytree(struct ldb_module * module, -1, &pStmt, NULL)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + if (pppRes != NULL && *pppRes != NULL) { talloc_free(*pppRes); } + continue; } else if (ret != SQLITE_OK) { ret = -1; @@ -730,6 +740,11 @@ lsqlite3_search_bytree(struct ldb_module * module, } if (ret == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + (void) sqlite3_finalize(pStmt); if (pppRes != NULL && *pppRes != NULL) { talloc_free(*pppRes); @@ -743,7 +758,11 @@ lsqlite3_search_bytree(struct ldb_module * module, /* Free the virtual machine */ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } + if (pppRes != NULL && *pppRes != NULL) { talloc_free(*pppRes); } @@ -916,13 +935,7 @@ lsqlite3_modify(struct ldb_module * module, 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 normalized_dn = %Q;", - pNormalizedDN); + GET_EID(lsqlite3, eid, TRUE, pNormalizedDN); /* Apply the message attributes */ if (msg_to_sql(module, msg, eid, TRUE) != 0) { @@ -1068,6 +1081,9 @@ initialize(struct lsqlite3_private *lsqlite3, "CREATE INDEX ldb_attribute_values_eid_idx " " ON ldb_attribute_values (eid);" + "CREATE INDEX ldb_attribute_values_name_value_idx " + " ON ldb_attribute_values (attr_name, attr_value_normalized);" + /* @@ -1351,7 +1367,7 @@ query_norows(const struct lsqlite3_private *lsqlite3, char * p; sqlite3_stmt * pStmt; va_list args; - double t0; + double t0 = 0; double t1; struct timeval tv; struct timezone tz; @@ -1382,6 +1398,10 @@ query_norows(const struct lsqlite3_private *lsqlite3, -1, &pStmt, NULL)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } continue; } else if (ret != SQLITE_OK) { ret = -1; @@ -1390,6 +1410,10 @@ query_norows(const struct lsqlite3_private *lsqlite3, /* No rows expected, so just step through machine code once */ if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } (void) sqlite3_finalize(pStmt); continue; } else if (ret != SQLITE_DONE) { @@ -1400,7 +1424,10 @@ query_norows(const struct lsqlite3_private *lsqlite3, /* Free the virtual machine */ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } continue; } else if (ret != SQLITE_OK) { (void) sqlite3_finalize(pStmt); @@ -1454,7 +1481,7 @@ query_int(const struct lsqlite3_private * lsqlite3, char * p; sqlite3_stmt * pStmt; va_list args; - double t0; + double t0 = 0; double t1; struct timeval tv; struct timezone tz; @@ -1489,6 +1516,10 @@ query_int(const struct lsqlite3_private * lsqlite3, -1, &pStmt, NULL)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } continue; } else if (ret != SQLITE_OK) { break; @@ -1496,6 +1527,10 @@ query_int(const struct lsqlite3_private * lsqlite3, /* One row expected */ if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) { + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } (void) sqlite3_finalize(pStmt); continue; } else if (ret != SQLITE_ROW) { @@ -1508,7 +1543,10 @@ query_int(const struct lsqlite3_private * lsqlite3, /* Free the virtual machine */ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { - (void) sqlite3_finalize(pStmt); + if (stmtGetEID != NULL) { + sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + } continue; } else if (ret != SQLITE_OK) { (void) sqlite3_finalize(pStmt); @@ -1542,6 +1580,92 @@ query_int(const struct lsqlite3_private * lsqlite3, /* + * getEID() + * + * This function is used for the very common case of retrieving an EID value + * given a normalized DN. + * + * NOTE: If more than one value is returned by the query, all but the first + * one will be ignored. + */ +static int +getEID(const struct lsqlite3_private * lsqlite3, + long long * pRet, + const char * pNormalizedDN) +{ + int ret; + int bLoop; + const char * query = + "SELECT eid\n" + " FROM ldb_attribute_values\n" + " WHERE attr_name = 'DN'\n" + " AND attr_value_normalized = :dn;"; + + /* + * 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 */ + ret = SQLITE_OK; + if (stmtGetEID == NULL && + (ret = sqlite3_prepare(lsqlite3->sqlite, + query, + -1, + &stmtGetEID, + NULL)) == SQLITE_SCHEMA) { + continue; + } else if (ret != SQLITE_OK) { + break; + } + + /* Bind our parameter */ + if ((ret = sqlite3_bind_text(stmtGetEID, + 1, + pNormalizedDN, + -1, + SQLITE_STATIC)) != SQLITE_OK) { + break; + } + + /* One row expected */ + if ((ret = sqlite3_step(stmtGetEID)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + continue; + } else if (ret != SQLITE_ROW) { + (void) sqlite3_reset(stmtGetEID); + break; + } + + /* Get the value to be returned */ + *pRet = sqlite3_column_int64(stmtGetEID, 0); + + /* Free the virtual machine */ + if ((ret = sqlite3_reset(stmtGetEID)) == SQLITE_SCHEMA) { + (void) sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + continue; + } else if (ret != SQLITE_OK) { + (void) sqlite3_finalize(stmtGetEID); + stmtGetEID = NULL; + break; + } + + /* + * Normal condition is only one time through loop. Loop is + * rerun in error conditions, via "continue", above. + */ + bLoop = FALSE; + } + + return ret; +} + + +/* callback function used in call to ldb_dn_fold() for determining whether an attribute type requires case folding. */ @@ -2072,8 +2196,9 @@ new_dn(struct ldb_module * module, char * pDN, long long * pEID) { - int nComponent; + int ret; int bFirst; + int nComponent; char * p; char * pPartialDN; char * pPartialNormalizedDN; @@ -2159,7 +2284,10 @@ new_dn(struct ldb_module * module, /* Save the new partial DN */ pPartialDN = p; - pPartialNormalizedDN = ldb_dn_fold(pPartialDN, p, module, case_fold_attr_required); + pPartialNormalizedDN = ldb_dn_fold(pPartialDN, + p, + module, + case_fold_attr_required); if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { gettimeofday(&tv, NULL); @@ -2171,62 +2299,60 @@ new_dn(struct ldb_module * module, /* * Ensure that an entry is in the ldb_entry table for this - * component. Any component other than the last one - * (component 0) may already exist. It is an error if - * component 0 (the full DN requested to be be inserted) - * already exists. + * component. */ - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT %s INTO ldb_entry\n" - " (peid, dn, normalized_dn)\n" - " VALUES\n" - " (%lld, %Q, %Q);", - nComponent == 0 ? "" : "OR IGNORE", - eid, pPartialDN, pPartialNormalizedDN); - - /* Save the parent EID */ - peid = eid; + if ((ret = getEID(lsqlite3, + &eid, + pPartialNormalizedDN)) == SQLITE_DONE) { + + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT INTO ldb_entry\n" + " (peid, dn, normalized_dn)\n" + " VALUES\n" + " (%lld, %Q, %Q);", + eid, pPartialDN, pPartialNormalizedDN); + + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, NULL); + t1 = ((double) tv.tv_sec + + ((double) tv.tv_usec / 1000000.0)); + printf("%1.6lf loc 5\n", t1 - t0); + t0 = t1; + } - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, NULL); - t1 = ((double) tv.tv_sec + - ((double) tv.tv_usec / 1000000.0)); - printf("%1.6lf loc 5\n", t1 - t0); - t0 = t1; - } + /* Get the EID of the just inserted row */ + eid = sqlite3_last_insert_rowid(lsqlite3->sqlite); + + if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { + gettimeofday(&tv, NULL); + t1 = ((double) tv.tv_sec + + ((double) tv.tv_usec / 1000000.0)); + printf("%1.6lf loc 8\n", t1 - t0); + t0 = t1; + } - /* Get the EID of the just inserted row */ - QUERY_INT(lsqlite3, - eid, - FALSE, - "SELECT eid " - " FROM ldb_entry " - " WHERE normalized_dn = %Q;", - pPartialNormalizedDN); + /* Also add DN attribute */ + QUERY_NOROWS(lsqlite3, + FALSE, + "INSERT INTO ldb_attribute_values\n" + " (eid,\n" + " attr_name,\n" + " attr_value,\n" + " attr_value_normalized) " + " VALUES " + " (%lld, 'DN', %Q, %Q);", + eid, + pPartialDN, /* FIX ME */ + pPartialNormalizedDN); - if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { - gettimeofday(&tv, NULL); - t1 = ((double) tv.tv_sec + - ((double) tv.tv_usec / 1000000.0)); - printf("%1.6lf loc 8\n", t1 - t0); - t0 = t1; + } else if (ret != SQLITE_OK) { + UNLOCK_DB(module, "rollback"); + return -1; } - - /* Also add DN attribute */ - QUERY_NOROWS(lsqlite3, - FALSE, - "INSERT %s INTO ldb_attribute_values\n" - " (eid,\n" - " attr_name,\n" - " attr_value,\n" - " attr_value_normalized) " - " VALUES " - " (%lld, 'DN', %Q, %Q);", - nComponent == 0 ? "" : "OR IGNORE", - eid, - pPartialDN, /* FIX ME */ - pPartialNormalizedDN); + + /* Save the parent EID */ + peid = eid; } if (lsqlite3_debug & SQLITE3_DEBUG_NEWDN) { diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h index 3d3c63397b..46ee1e93ba 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h @@ -2,14 +2,6 @@ struct lsqlite3_private { char ** options; - const char * basedn; sqlite3 * sqlite; int lock_count; }; - -void -lsqlite3_base160(unsigned long val, - unsigned char result[5]); - -char * -lsqlite3_base160Next(char base160[]); diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index 31d3f2662a..606c511600 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -38,7 +38,10 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const { struct ldb_cmdline options, *ret=NULL; poptContext pc; - int r, num_options = 0; +#ifdef _SAMBA_BUILD_ + int r; +#endif + int num_options = 0; char opt; struct poptOption popt_options[] = { POPT_AUTOHELP |