summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/ldb_sqlite3
diff options
context:
space:
mode:
authorDerrell Lipman <derrell@samba.org>2005-06-25 03:43:33 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:18:47 -0500
commit1603fd94666d3175e9df12652f9ff4e1d14de064 (patch)
tree9a8c26c9e5c1d2cee6a872d4f13426a9d759628a /source4/lib/ldb/ldb_sqlite3
parent1af480a32dcbae582aa617410d248663349e7498 (diff)
downloadsamba-1603fd94666d3175e9df12652f9ff4e1d14de064.tar.gz
samba-1603fd94666d3175e9df12652f9ff4e1d14de064.tar.bz2
samba-1603fd94666d3175e9df12652f9ff4e1d14de064.zip
r7897: work in progress
(This used to be commit 8e1431efcf0df797bc50ef584c38fce6a03429b3)
Diffstat (limited to 'source4/lib/ldb/ldb_sqlite3')
-rw-r--r--source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c312
-rw-r--r--source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h8
2 files changed, 219 insertions, 101 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[]);