summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/ldb_sqlite3
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2006-03-03 22:52:38 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:52:14 -0500
commite07f36a48cbc1b24192bddd3d27b164d52bfe31c (patch)
tree90471b9887a46bb36efc07bb11cbe32493b8c968 /source4/lib/ldb/ldb_sqlite3
parent509814bd037a3c73fea4ab92b531c25964f34dfa (diff)
downloadsamba-e07f36a48cbc1b24192bddd3d27b164d52bfe31c.tar.gz
samba-e07f36a48cbc1b24192bddd3d27b164d52bfe31c.tar.bz2
samba-e07f36a48cbc1b24192bddd3d27b164d52bfe31c.zip
r13826: Try to keep this backend updated
This need more testing and to be built by default when possible (This used to be commit 76cbab0e252620ef6591e2a7354484660bbb6df5)
Diffstat (limited to 'source4/lib/ldb/ldb_sqlite3')
-rw-r--r--source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c638
-rw-r--r--source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h7
2 files changed, 444 insertions, 201 deletions
diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
index aedba4e895..bf6cf0951b 100644
--- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
+++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
@@ -36,7 +36,55 @@
#include "includes.h"
#include "ldb/include/includes.h"
-#include "ldb/ldb_sqlite3/ldb_sqlite3.h"
+#include <sqlite3.h>
+
+struct lsqlite3_private {
+ int trans_count;
+ char **options;
+ sqlite3 *sqlite;
+};
+
+struct lsql_async_context {
+ struct ldb_module *module;
+
+ /* search stuff */
+ long long current_eid;
+ const char * const * attrs;
+ struct ldb_async_result *ares;
+
+ /* async stuff */
+ void *context;
+ int (*callback)(struct ldb_context *, void *, struct ldb_async_result *);
+};
+
+static struct ldb_async_handle *init_lsql_handle(struct lsqlite3_private *lsqlite3, struct ldb_module *module,
+ void *context,
+ int (*callback)(struct ldb_context *, void *, struct ldb_async_result *))
+{
+ struct lsql_async_context *ac;
+ struct ldb_async_handle *h;
+
+ h = talloc_zero(lsqlite3, struct ldb_async_handle);
+ if (h == NULL) {
+ ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
+ return NULL;
+ }
+
+ ac = talloc(h, struct lsql_async_context);
+ if (ac == NULL) {
+ ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
+ talloc_free(h);
+ return NULL;
+ }
+
+ h->private_data = (void *)ac;
+
+ ac->module = module;
+ ac->context = context;
+ ac->callback = callback;
+
+ return h;
+}
/*
* Macros used throughout
@@ -78,7 +126,7 @@ static char *lsqlite3_tprintf(TALLOC_CTX *mem_ctx, const char *fmt, ...)
return ret;
}
-static unsigned char base160tab[161] = {
+static char base160tab[161] = {
48 ,49 ,50 ,51 ,52 ,53 ,54 ,55 ,56 ,57 , /* 0-9 */
58 ,59 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 , /* : ; A-H */
73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 , /* I-R */
@@ -167,10 +215,9 @@ base160next_sql(sqlite3_context * hContext,
{
int i;
int len;
- unsigned char * pTab;
- unsigned char * pBase160 =
- strdup(sqlite3_value_text(argv[0]));
- unsigned char * pStart = pBase160;
+ char * pTab;
+ char * pBase160 = strdup((const char *)sqlite3_value_text(argv[0]));
+ char * pStart = pBase160;
/*
* We need a minimum of four digits, and we will always get a multiple
@@ -289,7 +336,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
* For simple searches, we want to retrieve the list of EIDs that
* match the criteria.
*/
- attr = ldb_attr_casefold(module->ldb, mem_ctx, t->u.equality.attr);
+ attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr);
if (attr == NULL) return NULL;
h = ldb_attrib_handler(module->ldb, attr);
@@ -319,7 +366,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
/* DN query is a special ldb case */
char *cdn = ldb_dn_linearize_casefold(module->ldb,
ldb_dn_explode(module->ldb,
- value.data));
+ (const char *)value.data));
return lsqlite3_tprintf(mem_ctx,
"SELECT eid FROM ldb_entry "
@@ -353,11 +400,11 @@ static char *parsetree_to_sql(struct ldb_module *module,
wild_card_string[strlen(wild_card_string) - 1] = '\0';
}
- attr = ldb_attr_casefold(module->ldb, mem_ctx, t->u.substring.attr);
+ attr = ldb_attr_casefold(mem_ctx, t->u.substring.attr);
if (attr == NULL) return NULL;
h = ldb_attrib_handler(module->ldb, attr);
- subval.data = wild_card_string;
+ subval.data = (void *)wild_card_string;
subval.length = strlen(wild_card_string) + 1;
/* Get a canonicalised copy of the data */
@@ -374,7 +421,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
value.data);
case LDB_OP_GREATER:
- attr = ldb_attr_casefold(module->ldb, mem_ctx, t->u.equality.attr);
+ attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr);
if (attr == NULL) return NULL;
h = ldb_attrib_handler(module->ldb, attr);
@@ -393,7 +440,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
attr);
case LDB_OP_LESS:
- attr = ldb_attr_casefold(module->ldb, mem_ctx, t->u.equality.attr);
+ attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr);
if (attr == NULL) return NULL;
h = ldb_attrib_handler(module->ldb, attr);
@@ -416,7 +463,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
return talloc_strdup(mem_ctx, "SELECT eid FROM ldb_entry");
}
- attr = ldb_attr_casefold(module->ldb, mem_ctx, t->u.present.attr);
+ attr = ldb_attr_casefold(mem_ctx, t->u.present.attr);
if (attr == NULL) return NULL;
return lsqlite3_tprintf(mem_ctx,
@@ -425,7 +472,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
attr);
case LDB_OP_APPROX:
- attr = ldb_attr_casefold(module->ldb, mem_ctx, t->u.equality.attr);
+ attr = ldb_attr_casefold(mem_ctx, t->u.equality.attr);
if (attr == NULL) return NULL;
h = ldb_attrib_handler(module->ldb, attr);
@@ -564,10 +611,10 @@ static void lsqlite3_compare(sqlite3_context *ctx, int argc,
sqlite3_value **argv)
{
struct ldb_context *ldb = (struct ldb_context *)sqlite3_user_data(ctx);
- const unsigned char *val = sqlite3_value_text(argv[0]);
- const unsigned char *func = sqlite3_value_text(argv[1]);
- const unsigned char *cmp = sqlite3_value_text(argv[2]);
- const unsigned char *attr = sqlite3_value_text(argv[3]);
+ const char *val = (const char *)sqlite3_value_text(argv[0]);
+ const char *func = (const char *)sqlite3_value_text(argv[1]);
+ const char *cmp = (const char *)sqlite3_value_text(argv[2]);
+ const char *attr = (const char *)sqlite3_value_text(argv[3]);
const struct ldb_attrib_handler *h;
struct ldb_val valX;
struct ldb_val valY;
@@ -577,9 +624,9 @@ static void lsqlite3_compare(sqlite3_context *ctx, int argc,
/* greater */
case '>': /* >= */
h = ldb_attrib_handler(ldb, attr);
- valX.data = cmp;
+ valX.data = (void *)cmp;
valX.length = strlen(cmp);
- valY.data = val;
+ valY.data = (void *)val;
valY.length = strlen(val);
ret = h->comparison_fn(ldb, ldb, &valY, &valX);
if (ret >= 0)
@@ -591,9 +638,9 @@ static void lsqlite3_compare(sqlite3_context *ctx, int argc,
/* lesser */
case '<': /* <= */
h = ldb_attrib_handler(ldb, attr);
- valX.data = cmp;
+ valX.data = (void *)cmp;
valX.length = strlen(cmp);
- valY.data = val;
+ valY.data = (void *)val;
valY.length = strlen(val);
ret = h->comparison_fn(ldb, ldb, &valY, &valX);
if (ret <= 0)
@@ -654,69 +701,72 @@ static int lsqlite3_eid_callback(void *result, int col_num, char **cols, char **
return SQLITE_OK;
}
-struct lsqlite3_msgs {
- int count;
- struct ldb_message **msgs;
- long long current_eid;
- const char * const * attrs;
- TALLOC_CTX *mem_ctx;
-};
-
/*
* add a single set of ldap message values to a ldb_message
*/
-
static int lsqlite3_search_callback(void *result, int col_num, char **cols, char **names)
{
- struct lsqlite3_msgs *msgs = (struct lsqlite3_msgs *)result;
+ struct ldb_async_handle *handle = talloc_get_type(result, struct ldb_async_handle);
+ struct lsql_async_context *ac = talloc_get_type(handle->private_data, struct lsql_async_context);
struct ldb_message *msg;
long long eid;
int i;
/* eid, dn, attr_name, attr_value */
- if (col_num != 4) return SQLITE_ABORT;
+ if (col_num != 4)
+ return SQLITE_ABORT;
eid = atoll(cols[0]);
- if (eid != msgs->current_eid) {
- msgs->msgs = talloc_realloc(msgs->mem_ctx,
- msgs->msgs,
- struct ldb_message *,
- msgs->count + 2);
- if (msgs->msgs == NULL) return SQLITE_ABORT;
+ if (eid != ac->current_eid) { /* here begin a new entry */
+
+ /* call the async callback for the last entry
+ * except the first time */
+ if (ac->current_eid != 0) {
+ ac->ares->message = ldb_msg_canonicalize(ac->module->ldb, ac->ares->message);
+ if (ac->ares->message == NULL)
+ return SQLITE_ABORT;
+
+ handle->status = ac->callback(ac->module->ldb, ac->context, ac->ares);
+ if (handle->status != LDB_SUCCESS)
+ return SQLITE_ABORT;
+ }
- msgs->msgs[msgs->count] = talloc(msgs->msgs, struct ldb_message);
- if (msgs->msgs[msgs->count] == NULL) return SQLITE_ABORT;
+ /* start over */
+ ac->ares = talloc_zero(ac, struct ldb_async_result);
+ if (!ac->ares)
+ return SQLITE_ABORT;
- msgs->msgs[msgs->count]->dn = NULL;
- msgs->msgs[msgs->count]->num_elements = 0;
- msgs->msgs[msgs->count]->elements = NULL;
- msgs->msgs[msgs->count]->private_data = NULL;
+ ac->ares->message = ldb_msg_new(ac->ares);
+ if (!ac->ares->message)
+ return SQLITE_ABORT;
- msgs->count++;
- msgs->current_eid = eid;
+ ac->ares->type = LDB_REPLY_ENTRY;
+ ac->current_eid = eid;
}
- msg = msgs->msgs[msgs->count -1];
+ msg = ac->ares->message;
if (msg->dn == NULL) {
msg->dn = ldb_dn_explode(msg, cols[1]);
- if (msg->dn == NULL) return SQLITE_ABORT;
+ if (msg->dn == NULL)
+ return SQLITE_ABORT;
}
- if (msgs->attrs) {
+ if (ac->attrs) {
int found = 0;
- for (i = 0; msgs->attrs[i]; i++) {
- if (strcasecmp(cols[2], msgs->attrs[i]) == 0) {
+ for (i = 0; ac->attrs[i]; i++) {
+ if (strcasecmp(cols[2], ac->attrs[i]) == 0) {
found = 1;
break;
}
}
- if (!found) return 0;
+ if (!found) return SQLITE_OK;
}
- if (ldb_msg_add_string(msg, cols[2], cols[3]) != 0)
+ if (ldb_msg_add_string(msg, cols[2], cols[3]) != 0) {
return SQLITE_ABORT;
+ }
return SQLITE_OK;
}
@@ -787,33 +837,81 @@ done:
* Interface functions referenced by lsqlite3_ops
*/
+static int lsql_search_sync_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares)
+{
+ struct ldb_result *res = NULL;
+
+ if (!context) {
+ ldb_set_errstring(ldb, talloc_strdup(ldb, "NULL Context in callback"));
+ goto error;
+ }
+
+ res = *((struct ldb_result **)context);
+
+ if (!res || !ares) {
+ goto error;
+ }
+
+ if (ares->type == LDB_REPLY_ENTRY) {
+ res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, res->count + 2);
+ if (! res->msgs) {
+ goto error;
+ }
+
+ res->msgs[res->count + 1] = NULL;
+
+ res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
+ if (! res->msgs[res->count]) {
+ goto error;
+ }
+
+ res->count++;
+ } else {
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "unrecognized async reply in ltdb_search_sync_callback!\n");
+ goto error;
+ }
+
+ talloc_free(ares);
+ return LDB_SUCCESS;
+
+error:
+ if (ares) talloc_free(ares);
+ if (res) talloc_free(res);
+ if (context) *((struct ldb_result **)context) = NULL;
+ return LDB_ERR_OPERATIONS_ERROR;
+}
+
/* search for matching records, by tree */
-static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_dn* basedn,
- enum ldb_scope scope, struct ldb_parse_tree * tree,
- const char * const * attrs, struct ldb_result ** res)
+int lsql_search_async(struct ldb_module *module, const struct ldb_dn *base,
+ enum ldb_scope scope, struct ldb_parse_tree *tree,
+ const char * const *attrs,
+ void *context,
+ int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
+ struct ldb_async_handle **handle)
{
- TALLOC_CTX *local_ctx;
- struct lsqlite3_private *lsqlite3 = module->private_data;
- struct lsqlite3_msgs msgs;
+ struct lsqlite3_private *lsqlite3 = talloc_get_type(module->private_data, struct lsqlite3_private);
+ struct lsql_async_context *lsql_ac;
char *norm_basedn;
char *sqlfilter;
char *errmsg;
char *query = NULL;
- int ret, i;
+ int ret;
- /* create a local ctx */
- local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_search_bytree local context");
- if (local_ctx == NULL) {
- return -1;
+ *handle = init_lsql_handle(lsqlite3, module, context, callback);
+ if (*handle == NULL) {
+ talloc_free(*handle);
+ return LDB_ERR_OPERATIONS_ERROR;
}
- if (basedn) {
- norm_basedn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, basedn));
+ lsql_ac = talloc_get_type((*handle)->private_data, struct lsql_async_context);
+
+ if (base) {
+ norm_basedn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, base));
if (norm_basedn == NULL) {
ret = LDB_ERR_INVALID_DN_SYNTAX;
goto failed;
}
- } else norm_basedn = talloc_strdup(local_ctx, "");
+ } else norm_basedn = talloc_strdup(lsql_ac, "");
if (*norm_basedn == '\0' &&
(scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) {
@@ -822,13 +920,13 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d
}
/* Convert filter into a series of SQL conditions (constraints) */
- sqlfilter = parsetree_to_sql(module, local_ctx, tree);
+ sqlfilter = parsetree_to_sql(module, lsql_ac, tree);
switch(scope) {
case LDB_SCOPE_DEFAULT:
case LDB_SCOPE_SUBTREE:
if (*norm_basedn != '\0') {
- query = lsqlite3_tprintf(local_ctx,
+ query = lsqlite3_tprintf(lsql_ac,
"SELECT entry.eid,\n"
" entry.dn,\n"
" av.attr_name,\n"
@@ -852,7 +950,7 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d
norm_basedn,
sqlfilter);
} else {
- query = lsqlite3_tprintf(local_ctx,
+ query = lsqlite3_tprintf(lsql_ac,
"SELECT entry.eid,\n"
" entry.dn,\n"
" av.attr_name,\n"
@@ -876,7 +974,7 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d
break;
case LDB_SCOPE_BASE:
- query = lsqlite3_tprintf(local_ctx,
+ query = lsqlite3_tprintf(lsql_ac,
"SELECT entry.eid,\n"
" entry.dn,\n"
" av.attr_name,\n"
@@ -900,7 +998,7 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d
break;
case LDB_SCOPE_ONELEVEL:
- query = lsqlite3_tprintf(local_ctx,
+ query = lsqlite3_tprintf(lsql_ac,
"SELECT entry.eid,\n"
" entry.dn,\n"
" av.attr_name,\n"
@@ -926,7 +1024,6 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d
}
if (query == NULL) {
- ret = LDB_ERR_OTHER;
goto failed;
}
@@ -934,72 +1031,97 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d
printf ("%s\n", query);
/ * */
- msgs.msgs = NULL;
- msgs.count = 0;
- msgs.current_eid = 0;
- msgs.mem_ctx = local_ctx;
- msgs.attrs = attrs;
+ lsql_ac->current_eid = 0;
+ lsql_ac->attrs = attrs;
+ lsql_ac->ares = NULL;
+
+ (*handle)->state = LDB_ASYNC_PENDING;
- ret = sqlite3_exec(lsqlite3->sqlite, query, lsqlite3_search_callback, &msgs, &errmsg);
+ ret = sqlite3_exec(lsqlite3->sqlite, query, lsqlite3_search_callback, *handle, &errmsg);
if (ret != SQLITE_OK) {
if (errmsg) {
ldb_set_errstring(module->ldb, talloc_strdup(module, errmsg));
free(errmsg);
}
- ret = LDB_ERR_OTHER;
goto failed;
}
- for (i = 0; i < msgs.count; i++) {
- msgs.msgs[i] = ldb_msg_canonicalize(module->ldb, msgs.msgs[i]);
- if (msgs.msgs[i] == NULL) {
+ /* complete the last message if any */
+ if (lsql_ac->ares) {
+ lsql_ac->ares->message = ldb_msg_canonicalize(module->ldb, lsql_ac->ares->message);
+ if (lsql_ac->ares->message == NULL)
+ goto failed;
+
+ (*handle)->status = lsql_ac->callback(module->ldb, lsql_ac->context, lsql_ac->ares);
+ if ((*handle)->status != LDB_SUCCESS)
goto failed;
- }
- }
-
- *res = talloc(module, struct ldb_result);
- if (! *res) {
- goto failed;
}
- (*res)->msgs = talloc_steal(*res, msgs.msgs);
- (*res)->count = msgs.count;
- (*res)->refs = NULL;
- (*res)->controls = NULL;
+ (*handle)->state = LDB_ASYNC_DONE;
- talloc_free(local_ctx);
return LDB_SUCCESS;
-/* If error, return error code; otherwise return number of results */
failed:
- talloc_free(local_ctx);
- return LDB_ERR_OTHER;
+ talloc_free(*handle);
+ return LDB_ERR_OPERATIONS_ERROR;
}
+static int lsql_search_bytree(struct ldb_module * module, const struct ldb_dn* base,
+ enum ldb_scope scope, struct ldb_parse_tree * tree,
+ const char * const * attrs, struct ldb_result ** res)
+{
+ struct ldb_async_handle *handle;
+ int ret;
+
+ *res = talloc_zero(module, struct ldb_result);
+ if (! *res) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = lsql_search_async(module, base, scope, tree, attrs,
+ res, &lsql_search_sync_callback,
+ &handle);
+
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
+ talloc_free(handle);
+ }
+
+ if (ret != LDB_SUCCESS) {
+ talloc_free(*res);
+ }
+
+ return ret;
+}
/* add a record */
-static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg)
+static int lsql_add_async(struct ldb_module *module, struct ldb_message *msg,
+ void *context,
+ int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
+ struct ldb_async_handle **handle)
{
- TALLOC_CTX *local_ctx;
- struct lsqlite3_private *lsqlite3 = module->private_data;
+ struct lsqlite3_private *lsqlite3 = talloc_get_type(module->private_data, struct lsqlite3_private);
+ struct lsql_async_context *lsql_ac;
long long eid;
char *dn, *ndn;
char *errmsg;
char *query;
- int ret;
int i;
-
- /* create a local ctx */
- local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_add local context");
- if (local_ctx == NULL) {
- return LDB_ERR_OTHER;
+ int ret = LDB_ERR_OPERATIONS_ERROR;
+
+ *handle = init_lsql_handle(lsqlite3, module, context, callback);
+ if (*handle == NULL) {
+ goto failed;
}
+ lsql_ac = talloc_get_type((*handle)->private_data, struct lsql_async_context);
+ (*handle)->state = LDB_ASYNC_DONE;
+ (*handle)->status = LDB_SUCCESS;
/* See if this is an ltdb special */
if (ldb_dn_is_special(msg->dn)) {
struct ldb_dn *c;
- c = ldb_dn_explode(local_ctx, "@SUBCLASSES");
+ c = ldb_dn_explode(lsql_ac, "@SUBCLASSES");
if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) {
#warning "insert subclasses into object class tree"
ret = LDB_ERR_UNWILLING_TO_PERFORM;
@@ -1018,14 +1140,14 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg
}
/* create linearized and normalized dns */
- dn = ldb_dn_linearize(local_ctx, msg->dn);
- ndn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, msg->dn));
+ dn = ldb_dn_linearize(lsql_ac, msg->dn);
+ ndn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, msg->dn));
if (dn == NULL || ndn == NULL) {
ret = LDB_ERR_OTHER;
goto failed;
}
- query = lsqlite3_tprintf(local_ctx,
+ query = lsqlite3_tprintf(lsql_ac,
/* Add new entry */
"INSERT OR ABORT INTO ldb_entry "
"('dn', 'norm_dn') "
@@ -1046,7 +1168,7 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg
goto failed;
}
- eid = lsqlite3_get_eid_ndn(lsqlite3->sqlite, local_ctx, ndn);
+ eid = lsqlite3_get_eid_ndn(lsqlite3->sqlite, lsql_ac, ndn);
if (eid == -1) {
ret = LDB_ERR_OTHER;
goto failed;
@@ -1059,7 +1181,7 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg
int j;
/* Get a case-folded copy of the attribute name */
- attr = ldb_attr_casefold(module->ldb, local_ctx, el->name);
+ attr = ldb_attr_casefold(lsql_ac, el->name);
if (attr == NULL) {
ret = LDB_ERR_OTHER;
goto failed;
@@ -1073,13 +1195,13 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg
char *insert;
/* Get a canonicalised copy of the data */
- h->canonicalise_fn(module->ldb, local_ctx, &(el->values[j]), &value);
+ h->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
if (value.data == NULL) {
ret = LDB_ERR_OTHER;
goto failed;
}
- insert = lsqlite3_tprintf(local_ctx,
+ insert = lsqlite3_tprintf(lsql_ac,
"INSERT OR ROLLBACK INTO ldb_attribute_values "
"('eid', 'attr_name', 'norm_attr_name',"
" 'attr_value', 'norm_attr_value') "
@@ -1103,36 +1225,59 @@ static int lsqlite3_add(struct ldb_module *module, const struct ldb_message *msg
}
}
- talloc_free(local_ctx);
+ if (lsql_ac->callback)
+ (*handle)->status = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
+
return LDB_SUCCESS;
failed:
- talloc_free(local_ctx);
+ talloc_free(*handle);
+ return ret;
+}
+
+static int lsql_add(struct ldb_module *module, const struct ldb_message *msg)
+{
+ struct ldb_async_handle *handle;
+ int ret;
+
+ ret = lsql_add_async(module, msg, NULL, NULL, &handle);
+
+ if (ret != LDB_SUCCESS)
+ return ret;
+
+ ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
+
+ talloc_free(handle);
return ret;
}
/* modify a record */
-static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *msg)
+static int lsql_modify_async(struct ldb_module *module, const struct ldb_message *msg,
+ void *context,
+ int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
+ struct ldb_async_handle **handle)
{
- TALLOC_CTX *local_ctx;
- struct lsqlite3_private *lsqlite3 = module->private_data;
+ struct lsqlite3_private *lsqlite3 = talloc_get_type(module->private_data, struct lsqlite3_private);
+ struct lsql_async_context *lsql_ac;
long long eid;
char *errmsg;
- int ret;
int i;
-
- /* create a local ctx */
- local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_modify local context");
- if (local_ctx == NULL) {
- return LDB_ERR_OTHER;
+ int ret = LDB_ERR_OPERATIONS_ERROR;
+
+ *handle = init_lsql_handle(lsqlite3, module, context, callback);
+ if (*handle == NULL) {
+ goto failed;
}
+ lsql_ac = talloc_get_type((*handle)->private_data, struct lsql_async_context);
+ (*handle)->state = LDB_ASYNC_DONE;
+ (*handle)->status = LDB_SUCCESS;
/* See if this is an ltdb special */
if (ldb_dn_is_special(msg->dn)) {
struct ldb_dn *c;
- c = ldb_dn_explode(local_ctx, "@SUBCLASSES");
+ c = ldb_dn_explode(lsql_ac, "@SUBCLASSES");
if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) {
#warning "modify subclasses into object class tree"
ret = LDB_ERR_UNWILLING_TO_PERFORM;
@@ -1158,7 +1303,7 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *
int j;
/* Get a case-folded copy of the attribute name */
- attr = ldb_attr_casefold(module->ldb, local_ctx, el->name);
+ attr = ldb_attr_casefold(lsql_ac, el->name);
if (attr == NULL) {
ret = LDB_ERR_OTHER;
goto failed;
@@ -1171,7 +1316,7 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *
case LDB_FLAG_MOD_REPLACE:
/* remove all attributes before adding the replacements */
- mod = lsqlite3_tprintf(local_ctx,
+ mod = lsqlite3_tprintf(lsql_ac,
"DELETE FROM ldb_attribute_values "
"WHERE eid = '%lld' "
"AND norm_attr_name = '%q';",
@@ -1200,13 +1345,13 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *
struct ldb_val value;
/* Get a canonicalised copy of the data */
- h->canonicalise_fn(module->ldb, local_ctx, &(el->values[j]), &value);
+ h->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
if (value.data == NULL) {
ret = LDB_ERR_OTHER;
goto failed;
}
- mod = lsqlite3_tprintf(local_ctx,
+ mod = lsqlite3_tprintf(lsql_ac,
"INSERT OR ROLLBACK INTO ldb_attribute_values "
"('eid', 'attr_name', 'norm_attr_name',"
" 'attr_value', 'norm_attr_value') "
@@ -1235,7 +1380,7 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *
case LDB_FLAG_MOD_DELETE:
#warning "We should throw an error if the attribute we are trying to delete does not exist!"
if (el->num_values == 0) {
- mod = lsqlite3_tprintf(local_ctx,
+ mod = lsqlite3_tprintf(lsql_ac,
"DELETE FROM ldb_attribute_values "
"WHERE eid = '%lld' "
"AND norm_attr_name = '%q';",
@@ -1261,13 +1406,13 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *
struct ldb_val value;
/* Get a canonicalised copy of the data */
- h->canonicalise_fn(module->ldb, local_ctx, &(el->values[j]), &value);
+ h->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
if (value.data == NULL) {
ret = LDB_ERR_OTHER;
goto failed;
}
- mod = lsqlite3_tprintf(local_ctx,
+ mod = lsqlite3_tprintf(lsql_ac,
"DELETE FROM ldb_attribute_values "
"WHERE eid = '%lld' "
"AND norm_attr_name = '%q' "
@@ -1294,42 +1439,60 @@ static int lsqlite3_modify(struct ldb_module *module, const struct ldb_message *
}
}
- talloc_free(local_ctx);
+ if (lsql_ac->callback)
+ (*handle)->status = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
+
return LDB_SUCCESS;
failed:
- talloc_free(local_ctx);
+ talloc_free(*handle);
+ return ret;
+}
+
+static int lsql_modify(struct ldb_module *module, const struct ldb_message *msg)
+{
+ struct ldb_async_handle *handle;
+ int ret;
+
+ ret = lsql_modify_async(module, msg, NULL, NULL, &handle);
+
+ if (ret != LDB_SUCCESS)
+ return ret;
+
+ ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
+
+ talloc_free(handle);
return ret;
}
/* delete a record */
-static int lsqlite3_delete(struct ldb_module *module, const struct ldb_dn *dn)
+static int lsql_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
+ void *context,
+ int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
+ struct ldb_async_handle **handle)
{
- TALLOC_CTX *local_ctx;
- struct lsqlite3_private *lsqlite3 = module->private_data;
+ struct lsqlite3_private *lsqlite3 = talloc_get_type(module->private_data, struct lsqlite3_private);
+ struct lsql_async_context *lsql_ac;
long long eid;
char *errmsg;
char *query;
- int ret;
+ int ret = LDB_ERR_OPERATIONS_ERROR;
- /* ignore ltdb specials */
- if (ldb_dn_is_special(dn)) {
- return LDB_SUCCESS;
- }
- /* create a local ctx */
- local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_delete local context");
- if (local_ctx == NULL) {
- return LDB_ERR_OTHER;
+ *handle = init_lsql_handle(lsqlite3, module, context, callback);
+ if (*handle == NULL) {
+ goto failed;
}
+ lsql_ac = talloc_get_type((*handle)->private_data, struct lsql_async_context);
+ (*handle)->state = LDB_ASYNC_DONE;
+ (*handle)->status = LDB_SUCCESS;
eid = lsqlite3_get_eid(module, dn);
if (eid == -1) {
- ret = LDB_ERR_OTHER;
goto failed;
}
- query = lsqlite3_tprintf(local_ctx,
+ query = lsqlite3_tprintf(lsql_ac,
/* Delete entry */
"DELETE FROM ldb_entry WHERE eid = %lld; "
/* Delete attributes */
@@ -1346,55 +1509,76 @@ static int lsqlite3_delete(struct ldb_module *module, const struct ldb_dn *dn)
ldb_set_errstring(module->ldb, talloc_strdup(module, errmsg));
free(errmsg);
}
- ret = LDB_ERR_OTHER;
+ ret = LDB_ERR_OPERATIONS_ERROR;
goto failed;
}
- talloc_free(local_ctx);
+ if (lsql_ac->callback)
+ (*handle)->status = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
+
return LDB_SUCCESS;
failed:
- talloc_free(local_ctx);
+ talloc_free(*handle);
return ret;
}
-/* rename a record */
-static int lsqlite3_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
+static int lsql_delete(struct ldb_module *module, const struct ldb_dn *dn)
{
- TALLOC_CTX *local_ctx;
- struct lsqlite3_private *lsqlite3 = module->private_data;
- char *new_dn, *new_cdn, *old_cdn;
- char *errmsg;
- char *query;
+ struct ldb_async_handle *handle;
int ret;
/* ignore ltdb specials */
- if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
+ if (ldb_dn_is_special(dn)) {
return LDB_SUCCESS;
}
- /* create a local ctx */
- local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_rename local context");
- if (local_ctx == NULL) {
- return LDB_ERR_OTHER;
+ ret = lsql_delete_async(module, dn, NULL, NULL, &handle);
+
+ if (ret != LDB_SUCCESS)
+ return ret;
+
+ ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
+
+ talloc_free(handle);
+ return ret;
+}
+
+/* rename a record */
+static int lsql_rename_async(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn,
+ void *context,
+ int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
+ struct ldb_async_handle **handle)
+{
+ struct lsqlite3_private *lsqlite3 = talloc_get_type(module->private_data, struct lsqlite3_private);
+ struct lsql_async_context *lsql_ac;
+ char *new_dn, *new_cdn, *old_cdn;
+ char *errmsg;
+ char *query;
+ int ret = LDB_ERR_OPERATIONS_ERROR;
+
+ *handle = init_lsql_handle(lsqlite3, module, context, callback);
+ if (*handle == NULL) {
+ goto failed;
}
+ lsql_ac = talloc_get_type((*handle)->private_data, struct lsql_async_context);
+ (*handle)->state = LDB_ASYNC_DONE;
+ (*handle)->status = LDB_SUCCESS;
/* create linearized and normalized dns */
- old_cdn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, olddn));
- new_cdn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, newdn));
- new_dn = ldb_dn_linearize(local_ctx, newdn);
+ old_cdn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, olddn));
+ new_cdn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, newdn));
+ new_dn = ldb_dn_linearize(lsql_ac, newdn);
if (old_cdn == NULL || new_cdn == NULL || new_dn == NULL) {
- ret = LDB_ERR_OTHER;
goto failed;
}
/* build the SQL query */
- query = lsqlite3_tprintf(local_ctx,
+ query = lsqlite3_tprintf(lsql_ac,
"UPDATE ldb_entry SET dn = '%q', norm_dn = '%q' "
"WHERE norm_dn = '%q';",
new_dn, new_cdn, old_cdn);
if (query == NULL) {
- ret = LDB_ERR_OTHER;
goto failed;
}
@@ -1405,20 +1589,43 @@ static int lsqlite3_rename(struct ldb_module *module, const struct ldb_dn *olddn
ldb_set_errstring(module->ldb, talloc_strdup(module, errmsg));
free(errmsg);
}
- ret = LDB_ERR_OTHER;
+ ret = LDB_ERR_OPERATIONS_ERROR;
goto failed;
}
- /* clean up and exit */
- talloc_free(local_ctx);
+ if (lsql_ac->callback)
+ (*handle)->status = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
+
return LDB_SUCCESS;
failed:
- talloc_free(local_ctx);
+ talloc_free(*handle);
return ret;
}
-static int lsqlite3_start_trans(struct ldb_module * module)
+static int lsql_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
+{
+ struct ldb_async_handle *handle;
+ int ret;
+
+ /* ignore ltdb specials */
+ if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
+ return LDB_SUCCESS;
+ }
+
+
+ ret = lsql_rename_async(module, olddn, newdn, NULL, NULL, &handle);
+
+ if (ret != LDB_SUCCESS)
+ return ret;
+
+ ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
+
+ talloc_free(handle);
+ return ret;
+}
+
+static int lsql_start_trans(struct ldb_module * module)
{
int ret;
char *errmsg;
@@ -1440,7 +1647,7 @@ static int lsqlite3_start_trans(struct ldb_module * module)
return 0;
}
-static int lsqlite3_end_trans(struct ldb_module *module)
+static int lsql_end_trans(struct ldb_module *module)
{
int ret;
char *errmsg;
@@ -1464,7 +1671,7 @@ static int lsqlite3_end_trans(struct ldb_module *module)
return 0;
}
-static int lsqlite3_del_trans(struct ldb_module *module)
+static int lsql_del_trans(struct ldb_module *module)
{
struct lsqlite3_private *lsqlite3 = module->private_data;
@@ -1762,10 +1969,19 @@ destructor(void *p)
return 0;
}
+static int lsql_async_wait(struct ldb_module *module, struct ldb_async_handle *handle, enum ldb_async_wait_type type)
+{
+ return handle->status;
+}
-static int lsqlite3_request(struct ldb_module *module, struct ldb_request *req)
+static int lsql_request(struct ldb_module *module, struct ldb_request *req)
{
/* check for oustanding critical controls and return an error if found */
+
+ if (req->controls != NULL) {
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_sqlite3 backend!\n");
+ }
+
if (check_critical_controls(req->controls)) {
return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
}
@@ -1773,7 +1989,7 @@ static int lsqlite3_request(struct ldb_module *module, struct ldb_request *req)
switch (req->operation) {
case LDB_REQ_SEARCH:
- return lsqlite3_search_bytree(module,
+ return lsql_search_bytree(module,
req->op.search.base,
req->op.search.scope,
req->op.search.tree,
@@ -1781,40 +1997,74 @@ static int lsqlite3_request(struct ldb_module *module, struct ldb_request *req)
&req->op.search.res);
case LDB_REQ_ADD:
- return lsqlite3_add(module, req->op.add.message);
+ return lsql_add(module, req->op.add.message);
case LDB_REQ_MODIFY:
- return lsqlite3_modify(module, req->op.mod.message);
+ return lsql_modify(module, req->op.mod.message);
case LDB_REQ_DELETE:
- return lsqlite3_delete(module, req->op.del.dn);
+ return lsql_delete(module, req->op.del.dn);
case LDB_REQ_RENAME:
- return lsqlite3_rename(module,
+ return lsql_rename(module,
req->op.rename.olddn,
req->op.rename.newdn);
+ case LDB_ASYNC_SEARCH:
+ return lsql_search_async(module,
+ req->op.search.base,
+ req->op.search.scope,
+ req->op.search.tree,
+ req->op.search.attrs,
+ req->async.context,
+ req->async.callback,
+ &req->async.handle);
+/*
+ case LDB_ASYNC_ADD:
+ return lsql_add_async(module,
+ req->op.add.message,
+ req->async.context,
+ req->async.callback,
+ &req->async.handle);
+
+ case LDB_ASYNC_MODIFY:
+ return lsql_modify_async(module,
+ req->op.mod.message,
+ req->async.context,
+ req->async.callback,
+ &req->async.handle);
+*/
+ case LDB_ASYNC_DELETE:
+ return lsql_delete_async(module,
+ req->op.del.dn,
+ req->async.context,
+ req->async.callback,
+ &req->async.handle);
+
+ case LDB_ASYNC_RENAME:
+ return lsql_rename_async(module,
+ req->op.rename.olddn,
+ req->op.rename.newdn,
+ req->async.context,
+ req->async.callback,
+ &req->async.handle);
+
default:
return LDB_ERR_OPERATIONS_ERROR;
}
}
-static int lsqlite3_init_2(struct ldb_module *module)
-{
- return LDB_SUCCESS;
-}
-
/*
* Table of operations for the sqlite3 backend
*/
static const struct ldb_module_ops lsqlite3_ops = {
.name = "sqlite",
- .request = lsqlite3_request,
- .start_transaction = lsqlite3_start_trans,
- .end_transaction = lsqlite3_end_trans,
- .del_transaction = lsqlite3_del_trans,
- .second_stage_init = lsqlite3_init_2
+ .request = lsql_request,
+ .start_transaction = lsql_start_trans,
+ .end_transaction = lsql_end_trans,
+ .del_transaction = lsql_del_trans,
+ .async_wait = lsql_async_wait,
};
/*
diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h
deleted file mode 100644
index d14a1aa0e0..0000000000
--- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <sqlite3.h>
-
-struct lsqlite3_private {
- int trans_count;
- char **options;
- sqlite3 *sqlite;
-};