📄 ldb_sqlite3.c
字号:
if (attr == NULL) return NULL; a = ldb_schema_attribute_by_name(module->ldb, attr); /* Get a canonicalised copy of the data */ a->syntax->canonicalise_fn(module->ldb, mem_ctx, &(t->u.equality.value), &value); if (value.data == NULL) { return NULL; } return lsqlite3_tprintf(mem_ctx, "SELECT eid FROM ldb_attribute_values " "WHERE norm_attr_name = '%q' " "AND ldap_compare(norm_attr_value, '~%', 'q', '%q') ", attr, value.data, attr); case LDB_OP_EXTENDED:#warning "work out how to handle bitops" return NULL; default: break; }; /* should never occur */ abort(); return NULL;}/* * query_int() * * This function is used for the common case of queries that return a single * integer value. * * NOTE: If more than one value is returned by the query, all but the first * one will be ignored. */static intquery_int(const struct lsqlite3_private * lsqlite3, long long * pRet, const char * pSql, ...){ int ret; int bLoop; char * p; sqlite3_stmt * pStmt; va_list args; /* Begin access to variable argument list */ va_start(args, pSql); /* Format the query */ if ((p = sqlite3_vmprintf(pSql, args)) == NULL) { return SQLITE_NOMEM; } /* * 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, p, -1, &pStmt, NULL)) == SQLITE_SCHEMA) { if (stmtGetEID != NULL) { sqlite3_finalize(stmtGetEID); stmtGetEID = NULL; } continue; } else if (ret != SQLITE_OK) { break; } /* 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) { (void) sqlite3_finalize(pStmt); break; } /* Get the value to be returned */ *pRet = sqlite3_column_int64(pStmt, 0); /* Free the virtual machine */ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) { if (stmtGetEID != NULL) { sqlite3_finalize(stmtGetEID); stmtGetEID = NULL; } continue; } else if (ret != SQLITE_OK) { (void) sqlite3_finalize(pStmt); break; } /* * Normal condition is only one time through loop. Loop is * rerun in error conditions, via "continue", above. */ bLoop = FALSE; } /* All done with variable argument list */ va_end(args); /* Free the memory we allocated for our query string */ sqlite3_free(p); return ret;}/* * This is a bad hack to support ldap style comparisons whithin sqlite. * val is the attribute in the row currently under test * func is the desired test "<=" ">=" "~" ":" * cmp is the value to compare against (eg: "test") * attr is the attribute name the value of which we want to test */static void lsqlite3_compare(sqlite3_context *ctx, int argc, sqlite3_value **argv){ struct ldb_context *ldb = (struct ldb_context *)sqlite3_user_data(ctx); 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_schema_attribute *a; struct ldb_val valX; struct ldb_val valY; int ret; switch (func[0]) { /* greater */ case '>': /* >= */ a = ldb_schema_attribute_by_name(ldb, attr); valX.data = (void *)cmp; valX.length = strlen(cmp); valY.data = (void *)val; valY.length = strlen(val); ret = a->syntax->comparison_fn(ldb, ldb, &valY, &valX); if (ret >= 0) sqlite3_result_int(ctx, 1); else sqlite3_result_int(ctx, 0); return; /* lesser */ case '<': /* <= */ a = ldb_schema_attribute_by_name(ldb, attr); valX.data = (void *)cmp; valX.length = strlen(cmp); valY.data = (void *)val; valY.length = strlen(val); ret = a->syntax->comparison_fn(ldb, ldb, &valY, &valX); if (ret <= 0) sqlite3_result_int(ctx, 1); else sqlite3_result_int(ctx, 0); return; /* approx */ case '~': /* TODO */ sqlite3_result_int(ctx, 0); return; /* bitops */ case ':': /* TODO */ sqlite3_result_int(ctx, 0); return; default: break; } sqlite3_result_error(ctx, "Value must start with a special operation char (<>~:)!", -1); return;}/* rename a record */static int lsqlite3_safe_rollback(sqlite3 *sqlite){ char *errmsg; int ret; /* execute */ ret = sqlite3_exec(sqlite, "ROLLBACK;", NULL, NULL, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { printf("lsqlite3_safe_rollback: Error: %s\n", errmsg); free(errmsg); } return -1; } return 0;}/* return an eid as result */static int lsqlite3_eid_callback(void *result, int col_num, char **cols, char **names){ long long *eid = (long long *)result; if (col_num != 1) return SQLITE_ABORT; if (strcasecmp(names[0], "eid") != 0) return SQLITE_ABORT; *eid = atoll(cols[0]); return SQLITE_OK;}/* * 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 ldb_handle *handle = talloc_get_type(result, struct ldb_handle); struct lsql_context *ac = talloc_get_type(handle->private_data, struct lsql_context); struct ldb_message *msg; long long eid; int i; /* eid, dn, attr_name, attr_value */ if (col_num != 4) return SQLITE_ABORT; eid = atoll(cols[0]); 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; } /* start over */ ac->ares = talloc_zero(ac, struct ldb_reply); if (!ac->ares) return SQLITE_ABORT; ac->ares->message = ldb_msg_new(ac->ares); if (!ac->ares->message) return SQLITE_ABORT; ac->ares->type = LDB_REPLY_ENTRY; ac->current_eid = eid; } msg = ac->ares->message; if (msg->dn == NULL) { msg->dn = ldb_dn_new(msg, ac->module->ldb, cols[1]); if (msg->dn == NULL) return SQLITE_ABORT; } if (ac->attrs) { int found = 0; for (i = 0; ac->attrs[i]; i++) { if (strcasecmp(cols[2], ac->attrs[i]) == 0) { found = 1; break; } } if (!found) return SQLITE_OK; } if (ldb_msg_add_string(msg, cols[2], cols[3]) != 0) { return SQLITE_ABORT; } return SQLITE_OK;}/* * lsqlite3_get_eid() * lsqlite3_get_eid_ndn() * * These functions are used for the very common case of retrieving an EID value * given a (normalized) DN. */static long long lsqlite3_get_eid_ndn(sqlite3 *sqlite, void *mem_ctx, const char *norm_dn){ char *errmsg; char *query; long long eid = -1; long long ret; /* get object eid */ query = lsqlite3_tprintf(mem_ctx, "SELECT eid " "FROM ldb_entry " "WHERE norm_dn = '%q';", norm_dn); if (query == NULL) return -1; ret = sqlite3_exec(sqlite, query, lsqlite3_eid_callback, &eid, &errmsg); if (ret != SQLITE_OK) { if (errmsg) { printf("lsqlite3_get_eid: Fatal Error: %s\n", errmsg); free(errmsg); } return -1; } return eid;}static long long lsqlite3_get_eid(struct ldb_module *module, struct ldb_dn *dn){ TALLOC_CTX *local_ctx; struct lsqlite3_private *lsqlite3 = module->private_data; long long eid = -1; char *cdn; /* ignore ltdb specials */ if (ldb_dn_is_special(dn)) { return -1; } /* create a local ctx */ local_ctx = talloc_named(lsqlite3, 0, "lsqlite3_get_eid local context"); if (local_ctx == NULL) { return -1; } cdn = ldb_dn_alloc_casefold(local_ctx, dn); if (!cdn) goto done; eid = lsqlite3_get_eid_ndn(lsqlite3->sqlite, local_ctx, cdn);done: talloc_free(local_ctx); return eid;}/* * Interface functions referenced by lsqlite3_ops *//* search for matching records, by tree */int lsql_search(struct ldb_module *module, struct ldb_request *req){ struct lsqlite3_private *lsqlite3 = talloc_get_type(module->private_data, struct lsqlite3_private); struct lsql_context *lsql_ac; char *norm_basedn; char *sqlfilter; char *errmsg; char *query = NULL; int ret; req->handle = init_handle(lsqlite3, module, req); if (req->handle == NULL) { return LDB_ERR_OPERATIONS_ERROR; } lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context); if ((( ! ldb_dn_is_valid(req->op.search.base)) || ldb_dn_is_null(req->op.search.base)) && (req->op.search.scope == LDB_SCOPE_BASE || req->op.search.scope == LDB_SCOPE_ONELEVEL)) return LDB_ERR_OPERATIONS_ERROR; if (req->op.search.base) { norm_basedn = ldb_dn_alloc_casefold(lsql_ac, req->op.search.base); if (norm_basedn == NULL) { ret = LDB_ERR_INVALID_DN_SYNTAX; goto failed; } } else norm_basedn = talloc_strdup(lsql_ac, ""); /* Convert filter into a series of SQL conditions (constraints) */ sqlfilter = parsetree_to_sql(module, lsql_ac, req->op.search.tree); switch(req->op.search.scope) { case LDB_SCOPE_DEFAULT: case LDB_SCOPE_SUBTREE: if (*norm_basedn != '\0') { query = lsqlite3_tprintf(lsql_ac, "SELECT entry.eid,\n" " entry.dn,\n" " av.attr_name,\n" " av.attr_value\n" " FROM ldb_entry AS entry\n" " LEFT OUTER JOIN ldb_attribute_values AS av\n" " ON av.eid = entry.eid\n" " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" " FROM ldb_entry\n" " WHERE (ldb_entry.norm_dn GLOB('*,%q')\n" " OR ldb_entry.norm_dn = '%q')\n" " AND ldb_entry.eid IN\n" " (%s)\n" " )\n" " ORDER BY entry.eid ASC;", norm_basedn, norm_basedn, sqlfilter); } else { query = lsqlite3_tprintf(lsql_ac, "SELECT entry.eid,\n" " entry.dn,\n" " av.attr_name,\n" " av.attr_value\n" " FROM ldb_entry AS entry\n" " LEFT OUTER JOIN ldb_attribute_values AS av\n" " ON av.eid = entry.eid\n" " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" " FROM ldb_entry\n" " WHERE ldb_entry.eid IN\n" " (%s)\n" " )\n" " ORDER BY entry.eid ASC;", sqlfilter); } break; case LDB_SCOPE_BASE: query = lsqlite3_tprintf(lsql_ac, "SELECT entry.eid,\n" " entry.dn,\n" " av.attr_name,\n" " av.attr_value\n" " FROM ldb_entry AS entry\n" " LEFT OUTER JOIN ldb_attribute_values AS av\n" " ON av.eid = entry.eid\n" " WHERE entry.eid IN\n" " (SELECT DISTINCT ldb_entry.eid\n" " FROM ldb_entry\n" " WHERE ldb_entry.norm_dn = '%q'\n" " AND ldb_entry.eid IN\n" " (%s)\n" " )\n" " ORDER BY entry.eid ASC;", norm_basedn, sqlfilter); break; case LDB_SCOPE_ONELEVEL: query = lsqlite3_tprintf(lsql_ac, "SELECT entry.eid,\n" " entry.dn,\n" " av.attr_name,\n" " av.attr_value\n"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -