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 <datasource name>
The name of the ODBC datasource to use.
.LP
.B dbhost <hostname>
.br
-.B dbuser <username>
-.br
.B dbpasswd <password>
+.br
+.B dbuser <username>
.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 <SQL expression>
Specifies a where-clause template used to form a subtree search condition
-(dn=".*<dn>").
+(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"<upper_func>(ldap_entries.dn) LIKE CONCAT('%',?)"\fP).
+
.TP
.B children_cond <SQL expression>
Specifies a where-clause template used to form a children search condition
-(dn="\.+,<dn>").
+(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"<upper_func>(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 <SQL expression>
+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 <SQL expression>
+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 <SQL expression>
+.B id_query <SQL expression>
+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 <DN match expr>"\fP,
+where \fB<DN match expr>\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"<upper_func>(dn)=?"\fP
+is used).
+
.TP
-.B delentry_query <SQL expression>
+.B insentry_stmt <SQL expression>
+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 <SQL expression>
+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 <SQL expression>
+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 <SQL expression>
+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 <SQL function name>
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 (<arg> AS VARCHAR(<max DN length>))
is used, where
.B <max DN length>
-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 <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
.BR "CAST(?||? AS VARCHAR(<length>))".
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 <SQL function name>
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
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 }
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 <name> [...]
+Loads the layer \fB<name>\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
.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
.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
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
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)
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
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.
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
}
}
- 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";
}
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",
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;
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;
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" );
*/
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;
/*
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;
}
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;
}
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 ) {
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 ) {
}
} 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",
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(): "
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(): "
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(): "
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 );
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 ];
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 );
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 );
/*
* 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 );
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[],
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"
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
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
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 "?||?"
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 (?,?,?,?)"
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 ) )
{
"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('%',?)";