From f5936eb7fcc66b9183399e9ea33793cf47f9e4a3 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Wed, 5 Jan 2005 16:23:00 +0000 Subject: [PATCH] minor naming cleanup; improvements to DN mapping layer; major docs update --- doc/man/man5/slapd-sql.5 | 248 ++++++++++++------ servers/slapd/back-sql/add.c | 4 +- servers/slapd/back-sql/api.c | 33 ++- servers/slapd/back-sql/back-sql.h | 15 +- servers/slapd/back-sql/bind.c | 17 +- servers/slapd/back-sql/config.c | 43 +-- servers/slapd/back-sql/delete.c | 6 +- servers/slapd/back-sql/init.c | 40 +-- servers/slapd/back-sql/modrdn.c | 12 +- servers/slapd/back-sql/proto-sql.h | 12 +- .../back-sql/rdbms_depend/ibmdb2/slapd.conf | 2 +- .../back-sql/rdbms_depend/mysql/slapd.conf | 2 +- .../back-sql/rdbms_depend/oracle/slapd.conf | 2 +- .../back-sql/rdbms_depend/pgsql/slapd.conf | 2 +- .../back-sql/rdbms_depend/timesten/slapd.conf | 2 +- servers/slapd/back-sql/search.c | 4 + servers/slapd/back-sql/util.c | 8 +- 17 files changed, 291 insertions(+), 161 deletions(-) diff --git a/doc/man/man5/slapd-sql.5 b/doc/man/man5/slapd-sql.5 index e49b7c75f9..668eb13e88 100644 --- a/doc/man/man5/slapd-sql.5 +++ b/doc/man/man5/slapd-sql.5 @@ -41,90 +41,163 @@ for SQL dialects RDBMSes may use, so it may be used for integration and distribution of data on different RDBMSes, OSes, hosts etc., in other words, in highly heterogeneous environment. .LP -This backend is experimental. +This backend is \fIexperimental\fP. .SH CONFIGURATION These .B slapd.conf -options apply to the SQL backend database. -That is, they must follow a "database sql" line and come before any +options apply to the SQL backend database, which means that +they must follow a "database sql" line and come before any subsequent "backend" or "database" lines. -Other database options are described in the +Other database options not specific to this backend are described +in the .BR slapd.conf (5) manual page. +.SH DATA SOURCE CONFIGURATION + .TP .B dbname The name of the ODBC datasource to use. .LP .B dbhost .br -.B dbuser -.br .B dbpasswd +.br +.B dbuser .RS -These three options are generally unneeded, because this information is already -taken from the datasource. -Use them if you need to override datasource settings. +The three above options are generally unneeded, because this information +is taken from the datasource specified by the +.B dbname +directive. +They allow to override datasource settings. Also, several RDBMS' drivers tend to require explicit passing of user/password, even if those are given in datasource (Note: .B dbhost is currently ignored). .RE +.SH SCOPING CONFIGURATION +These options specify SQL query templates for scoping searches. + .TP .B subtree_cond Specifies a where-clause template used to form a subtree search condition -(dn=".*"). +(dn="(.+,)?$"). It may differ from one SQL dialect to another (see samples). +By default, it is constructed based on the knowledge about +how to normalize DN values (e.g. +\fB"(ldap_entries.dn) LIKE CONCAT('%',?)"\fP). + .TP .B children_cond Specifies a where-clause template used to form a children search condition -(dn="\.+,"). +(dn=".+,$"). It may differ from one SQL dialect to another (see samples). +By default, it is constructed based on the knowledge about +how to normalize DN values (e.g. +\fB"(ldap_entries.dn) LIKE CONCAT('%,',?)"\fP). + +.TP +.B use_subtree_shortcut { NO | yes } +Do not use the subtree condition when the searchBase is the database +suffix, and the scope is subtree; rather collect all entries. +.RE +.SH STAMEMENT CONFIGURATION +These options specify SQL query templates for loading schema mapping +metainformation, adding and deleting entries to ldap_entries, etc. +All these and subtree_cond should have the given default values. +For the current value it is recommended to look at the sources, +or in the log output when slapd starts with "-d 5" or greater. +Note that the parameter number and order must not be changed. + .TP .B oc_query +The query that is used to collect the objectClass mapping data +from table \fIldap_oc_mappings\fP; see "METAINFORMATION USED" for details. The default is -.B "SELECT id, name, keytbl, keycol, create_proc, delete_proc, expect_return FROM ldap_oc_mappings" +\fB"SELECT id, name, keytbl, keycol, create_proc, delete_proc, expect_return +FROM ldap_oc_mappings"\fP. + .TP .B at_query +The query that is used to collect the attributeType mapping data +from table \fIldap_attr_mappings\fP; see "METAINFORMATION USED" for details. The default is -.B "SELECT name, sel_expr, from_tbls, join_where, add_proc, delete_proc, param_order, expect_return FROM ldap_attr_mappings WHERE oc_map_id=?" +\fB"SELECT name, sel_expr, from_tbls, join_where, add_proc, delete_proc, +param_order, expect_return FROM ldap_attr_mappings WHERE oc_map_id=?"\fP. + .TP -.B insentry_query +.B id_query +The query that is used to map a DN to an entry +in table \fIldap_entries\fP; see "METAINFORMATION USED" for details. The default is -.B "INSERT INTO ldap_entries (dn, oc_map_id, parent, keyval) VALUES (?, ?, ?, ?)" +\fB"SELECT id,keyval,oc_map_id,dn FROM ldap_entries WHERE "\fP, +where \fB\fP is constructed based on the knowledge about +how to normalize DN values (e.g. \fB"dn=?"\fP if no means to uppercase +strings are available; typically, \fB"(dn)=?"\fP +is used). + .TP -.B delentry_query +.B insentry_stmt +The statement that is used to insert a new entry +in table \fIldap_entries\fP; see "METAINFORMATION USED" for details. The default is -.B "DELETE FROM ldap_entries WHERE id=?" +\fB"INSERT INTO ldap_entries (dn, oc_map_id, parent, keyval) VALUES +(?, ?, ?, ?)"\fP. + +.TP +.B delentry_stmt +The statement that is used to delete an existing entry +from table \fIldap_entries\fP; see "METAINFORMATION USED" for details. +The default is +\fB"DELETE FROM ldap_entries WHERE id=?"\fP. + +.TP +.B delobjclasses_stmt +The statement that is used to delete an existing entry's ID +from table \fIldap_objclasses\fP; see "METAINFORMATION USED" for details. +The default is +\fB""DELETE FROM ldap_entry_objclasses WHERE entry_id=?"\fP. + +.TP +.B delreferrals_stmt +The statement that is used to delete an existing entry's ID +from table \fIldap_referrals\fP; see "METAINFORMATION USED" for details. +The default is +\fB""DELETE FROM ldap_referrals WHERE entry_id=?"\fP. + +.RE +.SH HELPER CONFIGURATION -These four options specify SQL query templates for loading schema mapping -metainformation, adding and deleting entries to ldap_entries, etc. -All these and subtree_cond should have the given default values. -For the current value it is recommended to look at the sources, -or in the log output when slapd starts with "-d 5" or greater. -Note that the parameter number and order must not be changed. .TP .B upper_func Specifies the name of a function that converts a given value to uppercase. -This is used for CIS matching when the RDBMS is case sensitive. +This is used for case insensitive matching when the RDBMS is case sensitive. +It may differ from one SQL dialect to another (e.g. \fBUCASE\fP, \fBUPPER\fP +or whatever; see samples). By default, none is used, i.e. strings are not +uppercased, so matches may be case sensitive. + .TP -.B upper_needs_cast { NO | yes} +.B upper_needs_cast { NO | yes } Set this directive to .B yes if .B upper_func -needs an explicit cast when applied to literal strings. The form +needs an explicit cast when applied to literal strings. +A cast in the form .B CAST ( AS VARCHAR()) is used, where .B -is builtin. -This is -.B experimental -and may change in future releases. +is builtin in back-sql; see macro +.B BACKSQL_MAX_DN_LEN +(currently 255; note that slapd's builtin limit, in macro +.BR SLAP_LDAPDN_MAXLEN , +is set to 8192). +This is \fIexperimental\fP and may change in future releases. + .TP .B concat_pattern This statement defines the .B pattern -to be used to concatenate strings. The +that is used to concatenate strings. The .B pattern MUST contain two question marks, '?', that will be replaced by the two strings that must be concatenated. The default value is @@ -135,40 +208,34 @@ but an explicit cast may be required when operating on literal strings: .BR "CAST(?||? AS VARCHAR())". On some RDBMSes (IBM db2, MSSQL) the form .B "?+?" -is known to work. +is known to work as well. Carefully check the documentation of your RDBMS or stay with the examples for supported ones. -This is -.B experimental -and may change in future releases. +This is \fIexperimental\fP and may change in future releases. + .TP .B strcast_func Specifies the name of a function that converts a given value to a string for appropriate ordering. This is used in "SELECT DISTINCT" statements for strongly typed RDBMSes with little implicit casting (like PostgreSQL), when a literal string is specified. -This is -.B experimental -and may change in future releases. +This is \fIexperimental\fP and may change in future releases. + .TP .B has_ldapinfo_dn_ru { NO | yes } -Explicitly inform the backend whether the SQL schema has dn_ru column -(dn in reverse uppercased form) or not. -Overrides automatic check (required by PostgreSQL/unixODBC). -This is -.B experimental -and may change in future releases. +Explicitly inform the backend whether the dn_ru column +(DN in reverse uppercased form) is present in table \fIldap_entries\fP. +Overrides automatic check (this is required, ofr instance, +by PostgreSQL/unixODBC). +This is \fIexperimental\fP and may change in future releases. .TP .B fail_if_no_mapping { NO | yes } When set to .B yes -it forces -.I attribute -write operations to fail if no appropriate mapping between LDAP attributes -and SQL data is available. -The default behavior is to ignore those changes that cannot be mapped -correctly. +it forces \fIattribute\fP write operations to fail if no appropriate +mapping between LDAP attributes and SQL data is available. +The default behavior is to ignore those changes that cannot be mapped. It has no impact on objectClass mapping, i.e. if the .I structuralObjectClass of an entry cannot be mapped to SQL by looking up its name @@ -177,9 +244,7 @@ in ldap_oc_mappings, an operation will fail regardless of the .B fail_if_no_mapping switch; see section "METAINFORMATION USED" for details. -This is -.B experimental -and may change in future releases. +This is \fIexperimental\fP and may change in future releases. .TP .B allow_orphans { NO | yes } @@ -196,21 +261,31 @@ Instructs the database to create and manage an in-memory baseObject entry instead of looking for one in the RDBMS. If the (optional) .B filename -argument is given, the entry is read from file -.B filename -in +argument is given, the entry is read from that file in .BR LDIF (5) -form. -This is particularly useful when -.B ldap_entries +form; otherwise, an entry with objectClass \fBextensibleObject\fP +is created based on the contents of the RDN of the \fIbaseObject\fP. +This is particularly useful when \fIldap_entries\fP information is stored in a view rather than in a table, and .B union is not supported for views, so that the view can only specify one rule to compute the entry structure for one objectClass. This topic is discussed further in section "METAINFORMATION USED". -This is -.B experimental -and may change in future releases. +This is \fIexperimental\fP and may change in future releases. + +.TP +.B create_needs_select { NO | yes } +Instructs the database whether entry creation in table \fIldap_entries\fP +needs a subsequent select to collect the automatically assigned ID, +instead of being returned by a stored procedure. + +.TP +.B sqllayer [...] +Loads the layer \fB\fP onto a stack of helpers that are used +to map DNs from LDAP to SQL representation and vice-versa. +Subsequent args are passed to the layer configuration routine. +This is \fIhighly experimental\fP and should be used with extreme care. +The API of the layers is not frozen yet, so it is unpublished. .SH METAINFORMATION USED .LP @@ -280,7 +355,7 @@ for telephoneNumber we can use: .LP .nf SELECT phones.phone AS telephoneNumber FROM persons,phones - WHERE persons.id=phones.pers_id AND persons.id=? + WHERE persons.id=phones.pers_id AND persons.id=? .fi .LP If we wanted to service LDAP requests with filters like @@ -288,11 +363,15 @@ If we wanted to service LDAP requests with filters like .LP .nf SELECT ... FROM persons,phones - WHERE persons.id=phones.pers_id - AND persons.id=? - AND phones.phone like '123%' + WHERE persons.id=phones.pers_id + AND persons.id=? + AND phones.phone like '%1%2%3%' .fi .LP +(note how the telephoneNumber match is expanded in multiple wildcards +to account for interspersed ininfluential chars like spaces, dashes +and so; this occurs by design because telephoneNumber is defined after +a specially recognized syntax). So, if we had information about what tables contain values for each attribute, how to join these tables and arrange these values, we could try to automatically generate such statements, and translate search @@ -402,13 +481,15 @@ like this (by Robin Elfrink): CREATE VIEW ldap_entries (id, dn, oc_map_id, parent, keyval) AS SELECT 0, UPPER('o=MyCompany,c=NL'), - 3, 0, 'baseObject' FROM unixusers WHERE userid='root' UNION + 3, 0, 'baseObject' FROM unixusers WHERE userid='root' + UNION SELECT (1000000000+userid), - UPPER(CONCAT(CONCAT('cn=',gecos),',o=MyCompany,c=NL')), - 1, 0, userid FROM unixusers UNION + UPPER(CONCAT(CONCAT('cn=',gecos),',o=MyCompany,c=NL')), + 1, 0, userid FROM unixusers + UNION SELECT (2000000000+groupnummer), - UPPER(CONCAT(CONCAT('cn=',groupnaam),',o=MyCompany,c=NL')), - 2, 0, groupnummer FROM groups; + UPPER(CONCAT(CONCAT('cn=',groupnaam),',o=MyCompany,c=NL')), + 2, 0, groupnummer FROM groups; .fi .LP @@ -439,7 +520,7 @@ query generated (which loads candidate IDs) AND ldap_entries.objclass=? AND ldap_entries.parent=? AND phones.pers_id=persons.id - AND (phones.phone LIKE '123%') + AND (phones.phone LIKE '%1%2%3%') .fi .LP (for ONELEVEL search) @@ -465,15 +546,15 @@ ADD, DELETE, MODIFY and MODRDN operations are also performed on per-attribute metainformation (add_proc etc.). In those fields one can specify an SQL statement or stored procedure call which can add, or delete given values of a given attribute, using -the given entry keyval (see examples -- mostly ORACLE and MSSQL - since -there're no stored procs in mySQL). +the given entry keyval (see examples -- mostly PostgreSQL, ORACLE and MSSQL +- since as of this writing there are no stored procs in MySQL). .LP -We just add more columns to oc_mappings and attr_mappings, holding +We just add more columns to ldap_oc_mappings and ldap_attr_mappings, holding statements to execute (like create_proc, add_proc, del_proc etc.), and flags governing the order of parameters passed to those statements. Please see samples to find out what are the parameters passed, and other information on this matter - they are self-explanatory for those familiar -with concept expressed above. +with the concepts expressed above. .LP .SH Common techniques (referrals, multiclassing etc.) First of all, let's remember that among other major differences to the @@ -505,16 +586,24 @@ As previously stated, this backend should not be considered a replacement of other data storage backends, but rather a gateway to existing RDBMS storages that need to be published in LDAP form. .LP -The hasSubordintes operational attribute is honored by back-sql +The \fBhasSubordintes\fP operational attribute is honored by back-sql in search results and in compare operations; it is partially honored -also in filtering. Owing to design limitations, a (braindead) filter +also in filtering. Owing to design limitations, a (braindead?) filter of the form \fB(!(hasSubordinates=TRUE))\fP -will give no results instead of returning all the leaf entries. +will give no results instead of returning all the leaf entries, because +it actually expands into \fB... AND NOT (1=1)\fP. If you need to find all the leaf entries, please use \fB(hasSubordinates=FALSE)\fP instead. .LP +A directoryString value of the form "__First___Last_" +(where underscores should be replaced by spaces) corresponds +to its prettified counterpart "First_Last"; this is not currently +honored by back-sql if non-prettified data is written via RDBMS; +when non-prettified data is written thru back-sql, the prettified +values are actually used instead. +.LP .SH PROXY CACHE OVERLAY The proxy cache overlay allows caching of LDAP search requests (queries) in a local database. @@ -525,6 +614,7 @@ for details. There are example SQL modules in the slapd/back-sql/rdbms_depend/ directory in the OpenLDAP source tree. .SH FILES + .TP ETCDIR/slapd.conf default slapd configuration file diff --git a/servers/slapd/back-sql/add.c b/servers/slapd/back-sql/add.c index 55903e4047..c46dbba0a1 100644 --- a/servers/slapd/back-sql/add.c +++ b/servers/slapd/back-sql/add.c @@ -1348,7 +1348,7 @@ backsql_add( Operation *op, SlapReply *rs ) } } - rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_query, 0 ); + rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_stmt, 0 ); if ( rc != SQL_SUCCESS ) { rs->sr_err = LDAP_OTHER; rs->sr_text = "SQL-backend error"; @@ -1416,7 +1416,7 @@ backsql_add( Operation *op, SlapReply *rs ) } Debug( LDAP_DEBUG_TRACE, " backsql_add(): executing \"%s\" for dn \"%s\"\n", - bi->sql_insentry_query, op->oq_add.rs_e->e_name.bv_val, 0 ); + bi->sql_insentry_stmt, op->oq_add.rs_e->e_name.bv_val, 0 ); #ifdef BACKSQL_ARBITRARY_KEY Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, " "parent_id=%s, keyval=%ld\n", diff --git a/servers/slapd/back-sql/api.c b/servers/slapd/back-sql/api.c index 763956b049..e4584c3ebf 100644 --- a/servers/slapd/back-sql/api.c +++ b/servers/slapd/back-sql/api.c @@ -31,7 +31,7 @@ static backsql_api *backsqlapi; int -backsql_api_config( backsql_info *bi, const char *name ) +backsql_api_config( backsql_info *bi, const char *name, int argc, char *argv[] ) { backsql_api *ba; @@ -44,6 +44,14 @@ backsql_api_config( backsql_info *bi, const char *name ) ba2 = ch_malloc( sizeof( backsql_api ) ); *ba2 = *ba; + + if ( ba2->ba_config ) { + if ( ( *ba2->ba_config )( ba2, argc, argv ) ) { + ch_free( ba2 ); + return 1; + } + } + ba2->ba_next = bi->sql_api; bi->sql_api = ba2; return 0; @@ -53,12 +61,35 @@ backsql_api_config( backsql_info *bi, const char *name ) return 1; } +int +backsql_api_destroy( backsql_info *bi ) +{ + backsql_api *ba; + + assert( bi ); + + ba = bi->sql_api; + + if ( ba == NULL ) { + return 0; + } + + for ( ; ba; ba = ba->ba_next ) { + if ( ba->ba_destroy ) { + (void)( *ba->ba_destroy )( ba ); + } + } + + return 0; +} + int backsql_api_register( backsql_api *ba ) { backsql_api *ba2; assert( ba ); + assert( ba->ba_private == NULL ); if ( ba->ba_name == NULL ) { fprintf( stderr, "API module has no name\n" ); diff --git a/servers/slapd/back-sql/back-sql.h b/servers/slapd/back-sql/back-sql.h index a949b8c0a2..dd3a35edce 100644 --- a/servers/slapd/back-sql/back-sql.h +++ b/servers/slapd/back-sql/back-sql.h @@ -238,9 +238,14 @@ typedef struct { */ typedef struct backsql_api { char *ba_name; + int (*ba_config)( struct backsql_api *self, int argc, char *argv[] ); + int (*ba_destroy)( struct backsql_api *self ); + int (*ba_dn2odbc)( Operation *op, SlapReply *rs, struct berval *dn ); int (*ba_odbc2dn)( Operation *op, SlapReply *rs, struct berval *dn ); - struct backsql_api *ba_next; + + void *ba_private; + struct backsql_api *ba_next; } backsql_api; /* @@ -437,10 +442,10 @@ typedef struct { struct berval sql_children_cond; char *sql_oc_query, *sql_at_query; - char *sql_insentry_query, - *sql_delentry_query, - *sql_delobjclasses_query, - *sql_delreferrals_query; + char *sql_insentry_stmt, + *sql_delentry_stmt, + *sql_delobjclasses_stmt, + *sql_delreferrals_stmt; char *sql_id_query; char *sql_has_children_query; diff --git a/servers/slapd/back-sql/bind.c b/servers/slapd/back-sql/bind.c index ce4edaf83c..45b60659f0 100644 --- a/servers/slapd/back-sql/bind.c +++ b/servers/slapd/back-sql/bind.c @@ -100,26 +100,15 @@ backsql_bind( Operation *op, SlapReply *rs ) } e = &user_entry; - if ( ! access_allowed( op, e, password, NULL, ACL_AUTH, NULL ) ) { -#if 1 - rs->sr_err = LDAP_INVALID_CREDENTIALS; -#else - rs->sr_err = LDAP_INSUFFICIENT_ACCESS; -#endif - goto error_return; - } - a = attr_find( e->e_attrs, password ); if ( a == NULL ) { -#if 1 rs->sr_err = LDAP_INVALID_CREDENTIALS; -#else - rs->sr_err = LDAP_INAPPROPRIATE_AUTH; -#endif goto error_return; } - if ( slap_passwd_check( op->o_conn, a, &op->oq_bind.rb_cred, &rs->sr_text ) != 0 ) { + if ( slap_passwd_check( op, e, a, &op->oq_bind.rb_cred, + &rs->sr_text ) != 0 ) + { rs->sr_err = LDAP_INVALID_CREDENTIALS; goto error_return; } diff --git a/servers/slapd/back-sql/config.c b/servers/slapd/back-sql/config.c index 965ba89180..413bdf5f9f 100644 --- a/servers/slapd/back-sql/config.c +++ b/servers/slapd/back-sql/config.c @@ -176,18 +176,20 @@ backsql_db_config( Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): " "at_query=%s\n", bi->sql_at_query, 0, 0 ); - } else if ( !strcasecmp( argv[ 0 ], "insentry_query" ) ) { + } else if ( !strcasecmp( argv[ 0 ], "insentry_stmt" ) || + !strcasecmp( argv[ 0 ], "insentry_query" ) ) + { if ( argc < 2 ) { Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): " "missing SQL statement " - "in \"insentry_query\" directive\n", + "in \"insentry_stmt\" directive\n", fname, lineno, 0 ); return 1; } - bi->sql_insentry_query = ch_strdup( argv[ 1 ] ); + bi->sql_insentry_stmt = ch_strdup( argv[ 1 ] ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): " - "insentry_query=%s\n", bi->sql_insentry_query, 0, 0 ); + "insentry_stmt=%s\n", bi->sql_insentry_stmt, 0, 0 ); } else if ( !strcasecmp( argv[ 0 ], "create_needs_select" ) ) { if ( argc < 2 ) { @@ -274,44 +276,50 @@ backsql_db_config( Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): " "strcast_func=%s\n", bi->sql_strcast_func.bv_val, 0, 0 ); - } else if ( !strcasecmp( argv[ 0 ], "delentry_query" ) ) { + } else if ( !strcasecmp( argv[ 0 ], "delentry_stmt" ) || + !strcasecmp( argv[ 0 ], "delentry_query" ) ) + { if ( argc < 2 ) { Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): " "missing SQL statement " - "in \"delentry_query\" directive\n", + "in \"delentry_stmt\" directive\n", fname, lineno, 0 ); return 1; } - bi->sql_delentry_query = ch_strdup( argv[ 1 ] ); + bi->sql_delentry_stmt = ch_strdup( argv[ 1 ] ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): " - "delentry_query=%s\n", bi->sql_delentry_query, 0, 0 ); + "delentry_stmt=%s\n", bi->sql_delentry_stmt, 0, 0 ); - } else if ( !strcasecmp( argv[ 0 ], "delobjclasses_query" ) ) { + } else if ( !strcasecmp( argv[ 0 ], "delobjclasses_stmt" ) || + !strcasecmp( argv[ 0 ], "delobjclasses_query" ) ) + { if ( argc < 2 ) { Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): " "missing SQL statement " - "in \"delobjclasses_query\" directive\n", + "in \"delobjclasses_stmt\" directive\n", fname, lineno, 0 ); return 1; } - bi->sql_delobjclasses_query = ch_strdup( argv[ 1 ] ); + bi->sql_delobjclasses_stmt = ch_strdup( argv[ 1 ] ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): " - "delobjclasses_query=%s\n", bi->sql_delobjclasses_query, 0, 0 ); + "delobjclasses_stmt=%s\n", bi->sql_delobjclasses_stmt, 0, 0 ); - } else if ( !strcasecmp( argv[ 0 ], "delreferrals_query" ) ) { + } else if ( !strcasecmp( argv[ 0 ], "delreferrals_stmt" ) || + !strcasecmp( argv[ 0 ], "delreferrals_query" ) ) + { if ( argc < 2 ) { Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): " "missing SQL statement " - "in \"delreferrals_query\" directive\n", + "in \"delreferrals_stmt\" directive\n", fname, lineno, 0 ); return 1; } - bi->sql_delreferrals_query = ch_strdup( argv[ 1 ] ); + bi->sql_delreferrals_stmt = ch_strdup( argv[ 1 ] ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): " - "delreferrals_query=%s\n", bi->sql_delreferrals_query, 0, 0 ); + "delreferrals_stmt=%s\n", bi->sql_delreferrals_stmt, 0, 0 ); } else if ( !strcasecmp( argv[ 0 ], "has_ldapinfo_dn_ru") ) { if ( argc < 2 ) { @@ -436,7 +444,8 @@ backsql_db_config( } } else if ( !strcasecmp( argv[ 0 ], "sqllayer") ) { - if ( backsql_api_config( bi, argv[ 1 ] ) ) { + if ( backsql_api_config( bi, argv[ 1 ], argc - 2, &argv[ 2 ] ) ) + { Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): " "unable to load sqllayer \"%s\"\n", diff --git a/servers/slapd/back-sql/delete.c b/servers/slapd/back-sql/delete.c index fb0538b09d..366297c791 100644 --- a/servers/slapd/back-sql/delete.c +++ b/servers/slapd/back-sql/delete.c @@ -246,7 +246,7 @@ backsql_delete( Operation *op, SlapReply *rs ) SQLFreeStmt( sth, SQL_DROP ); /* delete "auxiliary" objectClasses, if any... */ - rc = backsql_Prepare( dbh, &sth, bi->sql_delobjclasses_query, 0 ); + rc = backsql_Prepare( dbh, &sth, bi->sql_delobjclasses_stmt, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " @@ -296,7 +296,7 @@ backsql_delete( Operation *op, SlapReply *rs ) SQLFreeStmt( sth, SQL_DROP ); /* delete referrals, if any... */ - rc = backsql_Prepare( dbh, &sth, bi->sql_delreferrals_query, 0 ); + rc = backsql_Prepare( dbh, &sth, bi->sql_delreferrals_stmt, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " @@ -346,7 +346,7 @@ backsql_delete( Operation *op, SlapReply *rs ) SQLFreeStmt( sth, SQL_DROP ); /* delete entry... */ - rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_query, 0 ); + rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_stmt, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " diff --git a/servers/slapd/back-sql/init.c b/servers/slapd/back-sql/init.c index 28d56e76d9..11c4518970 100644 --- a/servers/slapd/back-sql/init.c +++ b/servers/slapd/back-sql/init.c @@ -135,10 +135,10 @@ backsql_db_destroy( free( bi->sql_subtree_cond.bv_val ); free( bi->sql_oc_query ); free( bi->sql_at_query ); - free( bi->sql_insentry_query ); - free( bi->sql_delentry_query ); - free( bi->sql_delobjclasses_query ); - free( bi->sql_delreferrals_query ); + free( bi->sql_insentry_stmt ); + free( bi->sql_delentry_stmt ); + free( bi->sql_delobjclasses_stmt ); + free( bi->sql_delreferrals_stmt ); if ( bi->sql_baseObject ) { entry_free( bi->sql_baseObject ); @@ -343,48 +343,48 @@ backsql_db_open( bi->sql_at_query = ch_strdup( backsql_def_at_query ); } - if ( bi->sql_insentry_query == NULL ) { + if ( bi->sql_insentry_stmt == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "entry insertion SQL statement not specified " - "(use \"insentry_query\" directive in slapd.conf)\n", + "(use \"insentry_stmt\" directive in slapd.conf)\n", 0, 0, 0 ); Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" by default\n", - backsql_def_insentry_query, 0, 0 ); - bi->sql_insentry_query = ch_strdup( backsql_def_insentry_query ); + backsql_def_insentry_stmt, 0, 0 ); + bi->sql_insentry_stmt = ch_strdup( backsql_def_insentry_stmt ); } - if ( bi->sql_delentry_query == NULL ) { + if ( bi->sql_delentry_stmt == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "entry deletion SQL statement not specified " - "(use \"delentry_query\" directive in slapd.conf)\n", + "(use \"delentry_stmt\" directive in slapd.conf)\n", 0, 0, 0 ); Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" by default\n", - backsql_def_delentry_query, 0, 0 ); - bi->sql_delentry_query = ch_strdup( backsql_def_delentry_query ); + backsql_def_delentry_stmt, 0, 0 ); + bi->sql_delentry_stmt = ch_strdup( backsql_def_delentry_stmt ); } - if ( bi->sql_delobjclasses_query == NULL ) { + if ( bi->sql_delobjclasses_stmt == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "objclasses deletion SQL statement not specified " - "(use \"delobjclasses_query\" directive in slapd.conf)\n", + "(use \"delobjclasses_stmt\" directive in slapd.conf)\n", 0, 0, 0 ); Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" by default\n", - backsql_def_delobjclasses_query, 0, 0 ); - bi->sql_delobjclasses_query = ch_strdup( backsql_def_delobjclasses_query ); + backsql_def_delobjclasses_stmt, 0, 0 ); + bi->sql_delobjclasses_stmt = ch_strdup( backsql_def_delobjclasses_stmt ); } - if ( bi->sql_delreferrals_query == NULL ) { + if ( bi->sql_delreferrals_stmt == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "referrals deletion SQL statement not specified " - "(use \"delreferrals_query\" directive in slapd.conf)\n", + "(use \"delreferrals_stmt\" directive in slapd.conf)\n", 0, 0, 0 ); Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" by default\n", - backsql_def_delreferrals_query, 0, 0 ); - bi->sql_delreferrals_query = ch_strdup( backsql_def_delreferrals_query ); + backsql_def_delreferrals_stmt, 0, 0 ); + bi->sql_delreferrals_stmt = ch_strdup( backsql_def_delreferrals_stmt ); } op->o_hdr = (Opheader *)&op[ 1 ]; diff --git a/servers/slapd/back-sql/modrdn.c b/servers/slapd/back-sql/modrdn.c index 847ae82d84..c54d8833c9 100644 --- a/servers/slapd/back-sql/modrdn.c +++ b/servers/slapd/back-sql/modrdn.c @@ -232,13 +232,13 @@ backsql_modrdn( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " - "executing delentry_query\n", 0, 0, 0 ); + "executing delentry_stmt\n", 0, 0, 0 ); - rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_query, 0 ); + rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_stmt, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " - "error preparing delentry_query\n", 0, 0, 0 ); + "error preparing delentry_stmt\n", 0, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); @@ -279,13 +279,13 @@ backsql_modrdn( Operation *op, SlapReply *rs ) SQLFreeStmt( sth, SQL_DROP ); Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " - "executing insentry_query\n", 0, 0, 0 ); + "executing insentry_stmt\n", 0, 0, 0 ); - rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_query, 0 ); + rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_stmt, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " - "error preparing insentry_query\n", 0, 0, 0 ); + "error preparing insentry_stmt\n", 0, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); diff --git a/servers/slapd/back-sql/proto-sql.h b/servers/slapd/back-sql/proto-sql.h index b03f3ecbf5..1e019b587a 100644 --- a/servers/slapd/back-sql/proto-sql.h +++ b/servers/slapd/back-sql/proto-sql.h @@ -96,7 +96,9 @@ int backsql_modify_internal( /* * api.c */ -int backsql_api_config( backsql_info *si, const char *name ); +int backsql_api_config( backsql_info *bi, const char *name, + int argc, char *argv[] ); +int backsql_api_destroy( backsql_info *bi ); int backsql_api_register( backsql_api *ba ); int backsql_api_dn2odbc( Operation *op, SlapReply *rs, struct berval *dn ); int backsql_api_odbc2dn( Operation *op, SlapReply *rs, struct berval *dn ); @@ -221,10 +223,10 @@ extern char backsql_def_oc_query[], backsql_def_needs_select_oc_query[], backsql_def_at_query[], - backsql_def_delentry_query[], - backsql_def_insentry_query[], - backsql_def_delobjclasses_query[], - backsql_def_delreferrals_query[], + backsql_def_delentry_stmt[], + backsql_def_insentry_stmt[], + backsql_def_delobjclasses_stmt[], + backsql_def_delreferrals_stmt[], backsql_def_subtree_cond[], backsql_def_upper_subtree_cond[], backsql_id_query[], diff --git a/servers/slapd/back-sql/rdbms_depend/ibmdb2/slapd.conf b/servers/slapd/back-sql/rdbms_depend/ibmdb2/slapd.conf index 556470cb53..f6c1613009 100644 --- a/servers/slapd/back-sql/rdbms_depend/ibmdb2/slapd.conf +++ b/servers/slapd/back-sql/rdbms_depend/ibmdb2/slapd.conf @@ -28,7 +28,7 @@ dbname ldap_db2 dbuser db2inst1 dbpasswd ibmdb2 subtree_cond "upper(ldap_entries.dn) LIKE CONCAT('%',?)" -insentry_query "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select max(id)+1 from ldap_entries),?,?,?,?)" +insentry_stmt "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select max(id)+1 from ldap_entries),?,?,?,?)" upper_func "upper" upper_needs_cast "yes" create_needs_select "yes" diff --git a/servers/slapd/back-sql/rdbms_depend/mysql/slapd.conf b/servers/slapd/back-sql/rdbms_depend/mysql/slapd.conf index a780c83954..8f6e4e12f1 100644 --- a/servers/slapd/back-sql/rdbms_depend/mysql/slapd.conf +++ b/servers/slapd/back-sql/rdbms_depend/mysql/slapd.conf @@ -28,5 +28,5 @@ dbname ldap_mysql dbuser root dbpasswd subtree_cond "ldap_entries.dn LIKE CONCAT('%',?)" -insentry_query "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)" +insentry_stmt "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)" has_ldapinfo_dn_ru no diff --git a/servers/slapd/back-sql/rdbms_depend/oracle/slapd.conf b/servers/slapd/back-sql/rdbms_depend/oracle/slapd.conf index e94368237a..cc195d91e8 100644 --- a/servers/slapd/back-sql/rdbms_depend/oracle/slapd.conf +++ b/servers/slapd/back-sql/rdbms_depend/oracle/slapd.conf @@ -28,5 +28,5 @@ dbname ldap_ora8 dbuser ldap dbpasswd ldap subtree_cond "UPPER(ldap_entries.dn) LIKE CONCAT('%',UPPER(?))" -insentry_query "INSERT INTO ldap_entries (id,dn,oc_map_id,parent,keyval) VALUES (ldap_entry_ids.nextval,?,?,?,?)" +insentry_stmt "INSERT INTO ldap_entries (id,dn,oc_map_id,parent,keyval) VALUES (ldap_entry_ids.nextval,?,?,?,?)" upper_func UPPER diff --git a/servers/slapd/back-sql/rdbms_depend/pgsql/slapd.conf b/servers/slapd/back-sql/rdbms_depend/pgsql/slapd.conf index aecc890597..70a8dee054 100644 --- a/servers/slapd/back-sql/rdbms_depend/pgsql/slapd.conf +++ b/servers/slapd/back-sql/rdbms_depend/pgsql/slapd.conf @@ -27,7 +27,7 @@ rootpw secret dbname PostgreSQL dbuser postgres dbpasswd postgres -insentry_query "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select max(id)+1 from ldap_entries),?,?,?,?)" +insentry_stmt "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select max(id)+1 from ldap_entries),?,?,?,?)" upper_func "upper" strcast_func "text" concat_pattern "?||?" diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/slapd.conf b/servers/slapd/back-sql/rdbms_depend/timesten/slapd.conf index b0b15a386f..f93de8b402 100644 --- a/servers/slapd/back-sql/rdbms_depend/timesten/slapd.conf +++ b/servers/slapd/back-sql/rdbms_depend/timesten/slapd.conf @@ -28,4 +28,4 @@ dbname ldap_tt dbuser root dbpasswd subtree_cond "ldap_entries.dn LIKE ?" -insentry_query "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)" +insentry_stmt "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)" diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c index 3097e18fea..cb4089b192 100644 --- a/servers/slapd/back-sql/search.c +++ b/servers/slapd/back-sql/search.c @@ -958,6 +958,10 @@ equality_match:; casefold = 1; } + /* FIXME: directoryString filtering should use a similar + * approach to deal with non-prettified values like + * " A non prettified value ", by using a LIKE + * filter with all whitespaces collapsed to a single '%' */ if ( SLAP_MR_ASSOCIATED( matching_rule, bi->sql_telephoneNumberMatch ) ) { diff --git a/servers/slapd/back-sql/util.c b/servers/slapd/back-sql/util.c index dcc30bf20e..d85058488b 100644 --- a/servers/slapd/back-sql/util.c +++ b/servers/slapd/back-sql/util.c @@ -47,13 +47,13 @@ char backsql_def_at_query[] = "SELECT name,sel_expr,from_tbls,join_where,add_proc,delete_proc," "param_order,expect_return,sel_expr_u FROM ldap_attr_mappings " "WHERE oc_map_id=?"; -char backsql_def_delentry_query[] = "DELETE FROM ldap_entries WHERE id=?"; -char backsql_def_insentry_query[] = +char backsql_def_delentry_stmt[] = "DELETE FROM ldap_entries WHERE id=?"; +char backsql_def_insentry_stmt[] = "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) " "VALUES (?,?,?,?)"; -char backsql_def_delobjclasses_query[] = "DELETE FROM ldap_entry_objclasses " +char backsql_def_delobjclasses_stmt[] = "DELETE FROM ldap_entry_objclasses " "WHERE entry_id=?"; -char backsql_def_delreferrals_query[] = "DELETE FROM ldap_referrals " +char backsql_def_delreferrals_stmt[] = "DELETE FROM ldap_referrals " "WHERE entry_id=?"; char backsql_def_subtree_cond[] = "ldap_entries.dn LIKE CONCAT('%',?)"; char backsql_def_upper_subtree_cond[] = "(ldap_entries.dn) LIKE CONCAT('%',?)"; -- 2.39.5