1
0
mirror of https://github.com/samba-team/samba.git synced 2025-09-16 01:44:21 +03:00

r7349: work in progress

(This used to be commit 0e4d9729d9)
This commit is contained in:
Derrell Lipman
2005-06-07 03:01:46 +00:00
committed by Gerald (Jerry) Carter
parent 22ae788666
commit f08fafc492

View File

@@ -1,7 +1,6 @@
/* /*
ldb database library ldb database library
Copyright (C) Andrew Tridgell 2004
Copyright (C) Derrell Lipman 2005 Copyright (C) Derrell Lipman 2005
** NOTE! The following LGPL license applies to the ldb ** NOTE! The following LGPL license applies to the ldb
@@ -37,6 +36,7 @@
#include "includes.h" #include "includes.h"
#include "ldb/include/ldb.h" #include "ldb/include/ldb.h"
#include "ldb/include/ldb_private.h" #include "ldb/include/ldb_private.h"
#include "ldb/include/ldb_parse.h"
#include "ldb/ldb_sqlite3/ldb_sqlite3.h" #include "ldb/ldb_sqlite3/ldb_sqlite3.h"
#ifndef FALSE #ifndef FALSE
@@ -294,124 +294,314 @@ lsqlite3_add_msg_attr(struct ldb_context *ldb,
} }
#endif #endif
static char *
lsqlite3_parsetree_to_sql(struct ldb_module *module,
char * hTalloc,
const struct ldb_parse_tree *t)
{
int i;
char * child;
char * p;
char * ret = NULL;
char * pAttrName;
switch(t->operation) {
case LDB_OP_SIMPLE:
break;
case LDB_OP_AND:
ret = lsqlite3_parsetree_to_sql(module,
hTalloc,
t->u.list.elements[0]);
for (i = 1; i < t->u.list.num_elements; i++) {
child =
lsqlite3_parsetree_to_sql(
module,
hTalloc,
t->u.list.elements[i]);
ret = talloc_asprintf_append(ret,
"INTERSECT\n"
"%s\n",
child);
talloc_free(child);
}
child = ret;
ret = talloc_asprintf("(\n"
"%s\n"
")\n",
child);
talloc_free(child);
return ret;
case LDB_OP_OR:
child =
lsqlite3_parsetree_to_sql(
module,
hTalloc,
t->u.list.elements[0]);
for (i = 1; i < t->u.list.num_elements; i++) {
child =
lsqlite3_parsetree_to_sql(
module,
hTalloc,
t->u.list.elements[i]);
ret = talloc_asprintf_append(ret,
"UNION\n"
"%s\n",
child);
talloc_free(child);
}
child = ret;
ret = talloc_asprintf("(\n"
"%s\n"
")\n",
child);
talloc_free(child);
return ret;
case LDB_OP_NOT:
child =
lsqlite3_parsetree_to_sql(
module,
hTalloc,
t->u.not.child);
ret = talloc_asprintf(hTalloc,
"(\n"
" SELECT eid\n"
" FROM ldb_entry\n"
" WHERE eid NOT IN %s\n"
")\n",
child);
talloc_free(child);
return ret;
default:
/* should never occur */
abort();
};
/* Get a case-folded copy of the attribute name */
pAttrName = ldb_casefold((struct ldb_context *) module,
t->u.simple.attr);
/*
* For simple searches, we want to retrieve the list of EIDs that
* match the criteria. We accomplish this by searching the
* appropriate table, ldb_attr_<attributeName>, for the eid
* corresponding to all matching values.
*/
if (t->u.simple.value.length == 1 &&
(*(const char *) t->u.simple.value.data) == '*') {
/*
* Special case for "attr_name=*". In this case, we want the
* eid corresponding to all values in the specified attribute
* table.
*/
if ((p = sqlite3_mprintf("(\n"
" SELECT eid\n"
" FROM ldb_attr_%q\n"
")\n",
pAttrName)) == NULL) {
return NULL;
}
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
* that are subclasses as well.
*/
if ((p = sqlite3_mprintf(
"(\n"
" SELECT eid\n"
" FROM ldb_attr_objectclass\n"
" WHERE attr_name IN\n"
" (SELECT class_name\n"
" FROM ldb_objectclasses\n"
" WHERE tree_key GLOB\n"
" (SELECT tree_key\n"
" FROM ldb_objectclasses\n"
" WHERE class_name = %Q) || '*')\n"
")\n",
t->u.simple.value.data)) == NULL) {
return NULL;
}
ret = talloc_strdup(hTalloc, p);
sqlite3_free(p);
} else {
/* A normal query. */
if ((p = sqlite3_mprintf("(\n"
" SELECT eid\n"
" FROM ldb_attr_%q\n"
" WHERE attr_value = %Q\n"
")\n",
pAttrName,
t->u.simple.value.data)) == NULL) {
return NULL;
}
ret = talloc_strdup(hTalloc, p);
sqlite3_free(p);
}
return ret;
}
static char *
lsqlite3_parsetree_to_tablelist(struct ldb_module *module,
char * hTalloc,
const struct ldb_parse_tree *t)
{
#warning "obtain talloc'ed array of attribute names for table list"
return NULL;
}
/* /*
* search for matching records * search for matching records
*/ */
static int static int
lsqlite3_search(struct ldb_module *module, lsqlite3_search(struct ldb_module * module,
const char *base, const char * pBaseDN,
enum ldb_scope scope, enum ldb_scope scope,
const char *expression, const char * pExpression,
const char * const attrs[], const char * const attrs[],
struct ldb_message ***res) struct ldb_message *** res)
{ {
#warning "lsqlite3_search() not yet implemented" int ret;
#if 0 int bLoop;
int count; long long eid;
int msg_count; char * sql;
struct ldb_context * ldb = module->ldb; char * sql_constraints;
struct lsqlite3_private * lsqlite3 = module->private_data; char * table_list;
char * hTalloc;
if (base == NULL) { const char * pTail;
base = ""; sqlite3_stmt * pStmt;
struct ldb_parse_tree * pTree;
struct lsqlite3_private * lsqlite3 = module->private_data;
if (pBaseDN == NULL) {
pBaseDN = "";
} }
lsqlite3->last_rc = ldap_search_s(lsqlite3->ldap, base, (int)scope, /*
expression, * Obtain the eid of the base DN
discard_const_p(char *, attrs), */
0, &ldapres); if ((pTail = sqlite3_mprintf("SELECT eid "
if (lsqlite3->last_rc != LDAP_SUCCESS) { " FROM ldb_attr_dn "
" WHERE attr_value = %Q;",
pBaseDN)) == NULL) {
return -1;
}
for (bLoop = TRUE; bLoop; ) {
/* Compile the SQL statement into sqlite virtual machine */
if ((ret = sqlite3_prepare(lsqlite3->sqlite,
pTail,
-1,
&pStmt,
&pTail)) != SQLITE_OK) {
ret = -1;
break;
}
/* One row expected */
if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) {
(void) sqlite3_finalize(pStmt);
continue;
} else if (ret != SQLITE_ROW) {
(void) sqlite3_finalize(pStmt);
ret = -1;
break;
}
/* Retrieve the EID */
eid = sqlite3_column_int64(pStmt, 0);
/* 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;
}
/* Parse the filter expression into a tree we can work with */
if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) {
return -1; return -1;
} }
/* Allocate a temporary talloc context */
hTalloc = talloc_new(module);
count = ldap_count_entries(lsqlite3->ldap, ldapres); /* Move the parse tree to our temporary context */
if (count == -1 || count == 0) { talloc_steal(hTalloc, pTree);
ldap_msgfree(ldapres);
return count; /* Convert filter into a series of SQL statements (constraints) */
} sql_constraints = lsqlite3_parsetree_to_sql(module, hTalloc, pTree);
/* Get the list of attribute names to use as our extra table list */
table_list = lsqlite3_parsetree_to_tablelist(module, hTalloc, pTree);
(*res) = talloc_array(lsqlite3, struct ldb_message *, count+1); switch(scope) {
if (! *res) { case LDB_SCOPE_DEFAULT:
ldap_msgfree(ldapres); case LDB_SCOPE_SUBTREE:
errno = ENOMEM; sql = sqlite3_mprintf(
return -1; "SELECT entry.entry_data\n"
} " FROM ldb_entry AS entry\n"
" WHERE entry.eid IN\n"
" (SELECT ldb_entry.eid\n"
" FROM ldb_entry,\n"
" ldb_descendants,\n"
" %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,
sql_constraints);
break;
(*res)[0] = NULL; #warning "scope BASE and ONLEVEL not yet implemented"
case LDB_SCOPE_BASE:
break;
msg_count = 0; case LDB_SCOPE_ONELEVEL:
break;
}
/* loop over all messages */ return ret;
for (msg=ldap_first_entry(lsqlite3->ldap, ldapres);
msg;
msg=ldap_next_entry(lsqlite3->ldap, msg)) {
BerElement *berptr = NULL;
char *attr, *dn;
if (msg_count == count) {
/* hmm, got too many? */
ldb_debug(ldb, LDB_DEBUG_FATAL, "Fatal: ldap message count inconsistent\n");
break;
}
(*res)[msg_count] = talloc(*res, struct ldb_message);
if (!(*res)[msg_count]) {
goto failed;
}
(*res)[msg_count+1] = NULL;
dn = ldap_get_dn(lsqlite3->ldap, msg);
if (!dn) {
goto failed;
}
(*res)[msg_count]->dn = talloc_strdup((*res)[msg_count], dn);
ldap_memfree(dn);
if (!(*res)[msg_count]->dn) {
goto failed;
}
(*res)[msg_count]->num_elements = 0;
(*res)[msg_count]->elements = NULL;
(*res)[msg_count]->private_data = NULL;
/* loop over all attributes */
for (attr=ldap_first_attribute(lsqlite3->ldap, msg, &berptr);
attr;
attr=ldap_next_attribute(lsqlite3->ldap, msg, berptr)) {
struct berval **bval;
bval = ldap_get_values_len(lsqlite3->ldap, msg, attr);
if (bval) {
lsqlite3_add_msg_attr(ldb, (*res)[msg_count], attr, bval);
ldap_value_free_len(bval);
}
ldap_memfree(attr);
}
if (berptr) ber_free(berptr, 0);
msg_count++;
}
ldap_msgfree(ldapres);
return msg_count;
failed:
if (*res) lsqlite3_search_free(module, *res);
return -1;
#else
return -1;
#endif
} }
static int static int
lsqlite3_new_attr(struct lsqlite3_private * lsqlite3, lsqlite3_new_attr(struct ldb_module * module,
char * pAttrName) char * pAttrName)
{ {
struct lsqlite3_private * lsqlite3 = module->private_data;
/* Get a case-folded copy of the attribute name */
pAttrName = ldb_casefold((struct ldb_context *) module, pAttrName);
QUERY_NOROWS(lsqlite3, QUERY_NOROWS(lsqlite3,
FALSE, FALSE,
"CREATE TABLE ldb_attr_%q " "CREATE TABLE ldb_attr_%q "
@@ -429,12 +619,13 @@ lsqlite3_new_attr(struct lsqlite3_private * lsqlite3,
* requests in the ldb_message * requests in the ldb_message
*/ */
static int static int
lsqlite3_msg_to_sql(struct ldb_module *module, lsqlite3_msg_to_sql(struct ldb_module * module,
const struct ldb_message *msg, const struct ldb_message * msg,
long long eid, long long eid,
int use_flags) int use_flags)
{ {
int flags; int flags;
char * pAttrName;
unsigned int i; unsigned int i;
unsigned int j; unsigned int j;
struct lsqlite3_private * lsqlite3 = module->private_data; struct lsqlite3_private * lsqlite3 = module->private_data;
@@ -450,7 +641,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module,
if (flags == LDB_FLAG_MOD_ADD) { if (flags == LDB_FLAG_MOD_ADD) {
/* Create the attribute table if it doesn't exist */ /* Create the attribute table if it doesn't exist */
if (lsqlite3_new_attr(lsqlite3, el->name) != 0) { if (lsqlite3_new_attr(module, el->name) != 0) {
return -1; return -1;
} }
} }
@@ -458,6 +649,10 @@ lsqlite3_msg_to_sql(struct ldb_module *module,
/* For each value of the specified attribute name... */ /* For each value of the specified attribute name... */
for (j = 0; j < el->num_values; j++) { for (j = 0; j < el->num_values; j++) {
/* Get a case-folded copy of the attribute name */
pAttrName = ldb_casefold((struct ldb_context *) module,
el->name);
/* ... bind the attribute value, if necessary */ /* ... bind the attribute value, if necessary */
switch (flags) { switch (flags) {
case LDB_FLAG_MOD_ADD: case LDB_FLAG_MOD_ADD:
@@ -467,6 +662,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module,
" (eid, attr_value) " " (eid, attr_value) "
" VALUES " " VALUES "
" (%lld, %Q);", " (%lld, %Q);",
pAttrName,
eid, el->values[j].data); eid, el->values[j].data);
QUERY_NOROWS(lsqlite3, QUERY_NOROWS(lsqlite3,
FALSE, FALSE,
@@ -486,6 +682,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module,
"UPDATE ldb_attr_%q " "UPDATE ldb_attr_%q "
" SET attr_value = %Q " " SET attr_value = %Q "
" WHERE eid = %lld;", " WHERE eid = %lld;",
pAttrName,
el->values[j].data, el->values[j].data,
eid); eid);
QUERY_NOROWS(lsqlite3, QUERY_NOROWS(lsqlite3,
@@ -506,6 +703,7 @@ lsqlite3_msg_to_sql(struct ldb_module *module,
"DELETE FROM ldb_attr_%q " "DELETE FROM ldb_attr_%q "
" WHERE eid = %lld " " WHERE eid = %lld "
" AND attr_value = %Q;", " AND attr_value = %Q;",
pAttrName,
eid, eid,
el->values[j].data); el->values[j].data);
QUERY_NOROWS(lsqlite3, QUERY_NOROWS(lsqlite3,
@@ -903,16 +1101,11 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3,
; ;
/* Skip protocol indicator of url */ /* Skip protocol indicator of url */
if (strchr(url, ':')) { if ((p = strchr(url, ':')) == NULL) {
if (strncmp(url, "sqlite://", 9) != 0) { return SQLITE_MISUSE;
errno = EINVAL; } else {
return SQLITE_MISUSE; ++p;
} }
p = url + 9;
} else {
p = url;
}
/* /*
* See if we'll be creating a new database, or opening an existing one * See if we'll be creating a new database, or opening an existing one