2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2017 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
6 * Portions Copyright 2002 Pierangelo Masarati.
7 * Portions Copyright 2004 Mark Adamson.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
19 * This work was initially developed by Dmitry Kovalev for inclusion
20 * by OpenLDAP Software. Additional significant contributors include
21 * Pierangelo Masarati.
27 #include "ac/string.h"
28 #include <sys/types.h>
34 #include "proto-sql.h"
47 static ConfigDriver sql_cf_gen;
51 BSQL_CREATE_NEEDS_SEL,
52 BSQL_UPPER_NEEDS_CAST,
53 BSQL_HAS_LDAPINFO_DN_RU,
54 BSQL_FAIL_IF_NO_MAPPING,
58 BSQL_SUBTREE_SHORTCUT,
62 BSQL_ALIASING_KEYWORD,
66 static ConfigTable sqlcfg[] = {
67 { "dbhost", "hostname", 2, 2, 0, ARG_STRING|ARG_OFFSET,
68 (void *)offsetof(struct backsql_info, sql_dbhost),
69 "( OLcfgDbAt:6.1 NAME 'olcDbHost' "
70 "DESC 'Hostname of SQL server' "
71 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
72 { "dbname", "name", 2, 2, 0, ARG_STRING|ARG_OFFSET,
73 (void *)offsetof(struct backsql_info, sql_dbname),
74 "( OLcfgDbAt:6.2 NAME 'olcDbName' "
75 "DESC 'Name of SQL database' "
76 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
77 { "dbuser", "username", 2, 2, 0, ARG_STRING|ARG_OFFSET,
78 (void *)offsetof(struct backsql_info, sql_dbuser),
79 "( OLcfgDbAt:6.3 NAME 'olcDbUser' "
80 "DESC 'Username for SQL session' "
81 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
82 { "dbpasswd", "password", 2, 2, 0, ARG_STRING|ARG_OFFSET,
83 (void *)offsetof(struct backsql_info, sql_dbpasswd),
84 "( OLcfgDbAt:6.4 NAME 'olcDbPass' "
85 "DESC 'Password for SQL session' "
86 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
87 { "concat_pattern", "pattern", 2, 2, 0,
88 ARG_STRING|ARG_MAGIC|BSQL_CONCAT_PATT, (void *)sql_cf_gen,
89 "( OLcfgDbAt:6.20 NAME 'olcSqlConcatPattern' "
90 "DESC 'Pattern used to concatenate strings' "
91 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
92 { "subtree_cond", "SQL expression", 2, 0, 0, ARG_BERVAL|ARG_QUOTE|ARG_OFFSET,
93 (void *)offsetof(struct backsql_info, sql_subtree_cond),
94 "( OLcfgDbAt:6.21 NAME 'olcSqlSubtreeCond' "
95 "DESC 'Where-clause template for a subtree search condition' "
96 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
97 { "children_cond", "SQL expression", 2, 0, 0, ARG_BERVAL|ARG_QUOTE|ARG_OFFSET,
98 (void *)offsetof(struct backsql_info, sql_children_cond),
99 "( OLcfgDbAt:6.22 NAME 'olcSqlChildrenCond' "
100 "DESC 'Where-clause template for a children search condition' "
101 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
102 { "dn_match_cond", "SQL expression", 2, 0, 0, ARG_BERVAL|ARG_QUOTE|ARG_OFFSET,
103 (void *)offsetof(struct backsql_info, sql_dn_match_cond),
104 "( OLcfgDbAt:6.23 NAME 'olcSqlDnMatchCond' "
105 "DESC 'Where-clause template for a DN match search condition' "
106 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
107 { "oc_query", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
108 (void *)offsetof(struct backsql_info, sql_oc_query),
109 "( OLcfgDbAt:6.24 NAME 'olcSqlOcQuery' "
110 "DESC 'Query used to collect objectClass mapping data' "
111 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
112 { "at_query", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
113 (void *)offsetof(struct backsql_info, sql_at_query),
114 "( OLcfgDbAt:6.25 NAME 'olcSqlAtQuery' "
115 "DESC 'Query used to collect attributeType mapping data' "
116 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
117 { "insentry_stmt", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
118 (void *)offsetof(struct backsql_info, sql_insentry_stmt),
119 "( OLcfgDbAt:6.26 NAME 'olcSqlInsEntryStmt' "
120 "DESC 'Statement used to insert a new entry' "
121 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
122 { "create_needs_select", "yes|no", 2, 2, 0,
123 ARG_ON_OFF|ARG_MAGIC|BSQL_CREATE_NEEDS_SEL, (void *)sql_cf_gen,
124 "( OLcfgDbAt:6.27 NAME 'olcSqlCreateNeedsSelect' "
125 "DESC 'Whether entry creation needs a subsequent select' "
126 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
127 { "upper_func", "SQL function name", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,
128 (void *)offsetof(struct backsql_info, sql_upper_func),
129 "( OLcfgDbAt:6.28 NAME 'olcSqlUpperFunc' "
130 "DESC 'Function that converts a value to uppercase' "
131 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
132 { "upper_needs_cast", "yes|no", 2, 2, 0,
133 ARG_ON_OFF|ARG_MAGIC|BSQL_UPPER_NEEDS_CAST, (void *)sql_cf_gen,
134 "( OLcfgDbAt:6.29 NAME 'olcSqlUpperNeedsCast' "
135 "DESC 'Whether olcSqlUpperFunc needs an explicit cast' "
136 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
137 { "strcast_func", "SQL function name", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,
138 (void *)offsetof(struct backsql_info, sql_strcast_func),
139 "( OLcfgDbAt:6.30 NAME 'olcSqlStrcastFunc' "
140 "DESC 'Function that converts a value to a string' "
141 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
142 { "delentry_stmt", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
143 (void *)offsetof(struct backsql_info, sql_delentry_stmt),
144 "( OLcfgDbAt:6.31 NAME 'olcSqlDelEntryStmt' "
145 "DESC 'Statement used to delete an existing entry' "
146 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
147 { "renentry_stmt", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
148 (void *)offsetof(struct backsql_info, sql_renentry_stmt),
149 "( OLcfgDbAt:6.32 NAME 'olcSqlRenEntryStmt' "
150 "DESC 'Statement used to rename an entry' "
151 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
152 { "delobjclasses_stmt", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
153 (void *)offsetof(struct backsql_info, sql_delobjclasses_stmt),
154 "( OLcfgDbAt:6.33 NAME 'olcSqlDelObjclassesStmt' "
155 "DESC 'Statement used to delete the ID of an entry' "
156 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
157 { "has_ldapinfo_dn_ru", "yes|no", 2, 2, 0,
158 ARG_ON_OFF|ARG_MAGIC|BSQL_HAS_LDAPINFO_DN_RU, (void *)sql_cf_gen,
159 "( OLcfgDbAt:6.34 NAME 'olcSqlHasLDAPinfoDnRu' "
160 "DESC 'Whether the dn_ru column is present' "
161 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
162 { "fail_if_no_mapping", "yes|no", 2, 2, 0,
163 ARG_ON_OFF|ARG_MAGIC|BSQL_FAIL_IF_NO_MAPPING, (void *)sql_cf_gen,
164 "( OLcfgDbAt:6.35 NAME 'olcSqlFailIfNoMapping' "
165 "DESC 'Whether to fail on unknown attribute mappings' "
166 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
167 { "allow_orphans", "yes|no", 2, 2, 0,
168 ARG_ON_OFF|ARG_MAGIC|BSQL_ALLOW_ORPHANS, (void *)sql_cf_gen,
169 "( OLcfgDbAt:6.36 NAME 'olcSqlAllowOrphans' "
170 "DESC 'Whether to allow adding entries with no parent' "
171 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
172 { "baseobject", "[file]", 1, 2, 0,
173 ARG_STRING|ARG_MAGIC|BSQL_BASE_OBJECT, (void *)sql_cf_gen,
174 "( OLcfgDbAt:6.37 NAME 'olcSqlBaseObject' "
175 "DESC 'Manage an in-memory baseObject entry' "
176 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
177 { "sqllayer", "name", 2, 0, 0,
178 ARG_MAGIC|BSQL_LAYER, (void *)sql_cf_gen,
179 "( OLcfgDbAt:6.38 NAME 'olcSqlLayer' "
180 "DESC 'Helper used to map DNs between LDAP and SQL' "
181 "SYNTAX OMsDirectoryString )", NULL, NULL },
182 { "use_subtree_shortcut", "yes|no", 2, 2, 0,
183 ARG_ON_OFF|ARG_MAGIC|BSQL_SUBTREE_SHORTCUT, (void *)sql_cf_gen,
184 "( OLcfgDbAt:6.39 NAME 'olcSqlUseSubtreeShortcut' "
185 "DESC 'Collect all entries when searchBase is DB suffix' "
186 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
187 { "fetch_all_attrs", "yes|no", 2, 2, 0,
188 ARG_ON_OFF|ARG_MAGIC|BSQL_FETCH_ALL_ATTRS, (void *)sql_cf_gen,
189 "( OLcfgDbAt:6.40 NAME 'olcSqlFetchAllAttrs' "
190 "DESC 'Require all attributes to always be loaded' "
191 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
192 { "fetch_attrs", "attrlist", 2, 0, 0,
193 ARG_MAGIC|BSQL_FETCH_ATTRS, (void *)sql_cf_gen,
194 "( OLcfgDbAt:6.41 NAME 'olcSqlFetchAttrs' "
195 "DESC 'Set of attributes to always fetch' "
196 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
197 { "check_schema", "yes|no", 2, 2, 0,
198 ARG_ON_OFF|ARG_MAGIC|BSQL_CHECK_SCHEMA, (void *)sql_cf_gen,
199 "( OLcfgDbAt:6.42 NAME 'olcSqlCheckSchema' "
200 "DESC 'Check schema after modifications' "
201 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
202 { "aliasing_keyword", "string", 2, 2, 0,
203 ARG_STRING|ARG_MAGIC|BSQL_ALIASING_KEYWORD, (void *)sql_cf_gen,
204 "( OLcfgDbAt:6.43 NAME 'olcSqlAliasingKeyword' "
205 "DESC 'The aliasing keyword' "
206 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
207 { "aliasing_quote", "string", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,
208 (void *)offsetof(struct backsql_info, sql_aliasing_quote),
209 "( OLcfgDbAt:6.44 NAME 'olcSqlAliasingQuote' "
210 "DESC 'Quoting char of the aliasing keyword' "
211 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
212 { "autocommit", "yes|no", 2, 2, 0,
213 ARG_ON_OFF|ARG_MAGIC|BSQL_AUTOCOMMIT, (void *)sql_cf_gen,
214 "( OLcfgDbAt:6.45 NAME 'olcSqlAutocommit' "
215 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
216 { "id_query", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
217 (void *)offsetof(struct backsql_info, sql_id_query),
218 "( OLcfgDbAt:6.46 NAME 'olcSqlIdQuery' "
219 "DESC 'Query used to collect entryID mapping data' "
220 "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
221 { NULL, NULL, 0, 0, 0, ARG_IGNORED,
222 NULL, NULL, NULL, NULL }
225 static ConfigOCs sqlocs[] = {
228 "NAME 'olcSqlConfig' "
229 "DESC 'SQL backend configuration' "
230 "SUP olcDatabaseConfig "
232 "MAY ( olcDbHost $ olcDbUser $ olcDbPass $ olcSqlConcatPattern $ "
233 "olcSqlSubtreeCond $ olcsqlChildrenCond $ olcSqlDnMatchCond $ "
234 "olcSqlOcQuery $ olcSqlAtQuery $ olcSqlInsEntryStmt $ "
235 "olcSqlCreateNeedsSelect $ olcSqlUpperFunc $ olcSqlUpperNeedsCast $ "
236 "olcSqlStrCastFunc $ olcSqlDelEntryStmt $ olcSqlRenEntryStmt $ "
237 "olcSqlDelObjClassesStmt $ olcSqlHasLDAPInfoDnRu $ "
238 "olcSqlFailIfNoMapping $ olcSqlAllowOrphans $ olcSqlBaseObject $ "
239 "olcSqlLayer $ olcSqlUseSubtreeShortcut $ olcSqlFetchAllAttrs $ "
240 "olcSqlFetchAttrs $ olcSqlCheckSchema $ olcSqlAliasingKeyword $ "
241 "olcSqlAliasingQuote $ olcSqlAutocommit $ olcSqlIdQuery ) )",
242 Cft_Database, sqlcfg },
243 { NULL, Cft_Abstract, NULL }
247 sql_cf_gen( ConfigArgs *c )
249 backsql_info *bi = (backsql_info *)c->be->be_private;
252 if ( c->op == SLAP_CONFIG_EMIT ) {
254 case BSQL_CONCAT_PATT:
255 if ( bi->sql_concat_patt ) {
256 c->value_string = ch_strdup( bi->sql_concat_patt );
261 case BSQL_CREATE_NEEDS_SEL:
262 if ( bi->sql_flags & BSQLF_CREATE_NEEDS_SELECT )
265 case BSQL_UPPER_NEEDS_CAST:
266 if ( bi->sql_flags & BSQLF_UPPER_NEEDS_CAST )
269 case BSQL_HAS_LDAPINFO_DN_RU:
270 if ( !(bi->sql_flags & BSQLF_DONTCHECK_LDAPINFO_DN_RU) )
272 if ( bi->sql_flags & BSQLF_HAS_LDAPINFO_DN_RU )
275 case BSQL_FAIL_IF_NO_MAPPING:
276 if ( bi->sql_flags & BSQLF_FAIL_IF_NO_MAPPING )
279 case BSQL_ALLOW_ORPHANS:
280 if ( bi->sql_flags & BSQLF_ALLOW_ORPHANS )
283 case BSQL_SUBTREE_SHORTCUT:
284 if ( bi->sql_flags & BSQLF_USE_SUBTREE_SHORTCUT )
287 case BSQL_FETCH_ALL_ATTRS:
288 if ( bi->sql_flags & BSQLF_FETCH_ALL_ATTRS )
291 case BSQL_CHECK_SCHEMA:
292 if ( bi->sql_flags & BSQLF_CHECK_SCHEMA )
295 case BSQL_AUTOCOMMIT:
296 if ( bi->sql_flags & BSQLF_AUTOCOMMIT_ON )
299 case BSQL_BASE_OBJECT:
300 if ( bi->sql_base_ob_file ) {
301 c->value_string = ch_strdup( bi->sql_base_ob_file );
302 } else if ( bi->sql_baseObject ) {
303 c->value_string = ch_strdup( "TRUE" );
314 for ( ba = bi->sql_api; ba; ba = ba->ba_next ) {
315 bv.bv_len = strlen( ba->ba_name );
317 for ( i = 0; i<ba->ba_argc; i++ )
318 bv.bv_len += strlen( ba->ba_argv[i] ) + 3;
320 bv.bv_val = ch_malloc( bv.bv_len + 1 );
321 ptr = lutil_strcopy( bv.bv_val, ba->ba_name );
323 for ( i = 0; i<ba->ba_argc; i++ ) {
326 ptr = lutil_strcopy( ptr, ba->ba_argv[i] );
330 ber_bvarray_add( &c->rvalue_vals, &bv );
336 case BSQL_ALIASING_KEYWORD:
337 if ( !BER_BVISNULL( &bi->sql_aliasing )) {
339 bv = bi->sql_aliasing;
341 value_add_one( &c->rvalue_vals, &bv );
346 case BSQL_FETCH_ATTRS:
347 if ( bi->sql_anlist ||
348 ( bi->sql_flags & (BSQLF_FETCH_ALL_USERATTRS|
349 BSQLF_FETCH_ALL_OPATTRS)))
351 char buf[BUFSIZ*2], *ptr;
353 # define WHATSLEFT ((ber_len_t) (&buf[sizeof( buf )] - ptr))
355 if ( bi->sql_anlist ) {
356 ptr = anlist_unparse( bi->sql_anlist, ptr, WHATSLEFT );
360 if ( bi->sql_flags & BSQLF_FETCH_ALL_USERATTRS ) {
361 if ( WHATSLEFT <= STRLENOF( ",*" )) return 1;
362 if ( ptr != buf ) *ptr++ = ',';
365 if ( bi->sql_flags & BSQLF_FETCH_ALL_OPATTRS ) {
366 if ( WHATSLEFT <= STRLENOF( ",+" )) return 1;
367 if ( ptr != buf ) *ptr++ = ',';
371 bv.bv_len = ptr - buf;
372 value_add_one( &c->rvalue_vals, &bv );
377 } else if ( c->op == LDAP_MOD_DELETE ) { /* FIXME */
382 case BSQL_CONCAT_PATT:
383 if ( backsql_split_pattern( c->argv[ 1 ], &bi->sql_concat_func, 2 ) ) {
384 snprintf( c->cr_msg, sizeof( c->cr_msg ),
385 "%s: unable to parse pattern \"%s\"",
386 c->log, c->argv[ 1 ] );
387 Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
390 bi->sql_concat_patt = c->value_string;
392 case BSQL_CREATE_NEEDS_SEL:
394 bi->sql_flags |= BSQLF_CREATE_NEEDS_SELECT;
396 bi->sql_flags &= ~BSQLF_CREATE_NEEDS_SELECT;
398 case BSQL_UPPER_NEEDS_CAST:
400 bi->sql_flags |= BSQLF_UPPER_NEEDS_CAST;
402 bi->sql_flags &= ~BSQLF_UPPER_NEEDS_CAST;
404 case BSQL_HAS_LDAPINFO_DN_RU:
405 bi->sql_flags |= BSQLF_DONTCHECK_LDAPINFO_DN_RU;
407 bi->sql_flags |= BSQLF_HAS_LDAPINFO_DN_RU;
409 bi->sql_flags &= ~BSQLF_HAS_LDAPINFO_DN_RU;
411 case BSQL_FAIL_IF_NO_MAPPING:
413 bi->sql_flags |= BSQLF_FAIL_IF_NO_MAPPING;
415 bi->sql_flags &= ~BSQLF_FAIL_IF_NO_MAPPING;
417 case BSQL_ALLOW_ORPHANS:
419 bi->sql_flags |= BSQLF_ALLOW_ORPHANS;
421 bi->sql_flags &= ~BSQLF_ALLOW_ORPHANS;
423 case BSQL_SUBTREE_SHORTCUT:
425 bi->sql_flags |= BSQLF_USE_SUBTREE_SHORTCUT;
427 bi->sql_flags &= ~BSQLF_USE_SUBTREE_SHORTCUT;
429 case BSQL_FETCH_ALL_ATTRS:
431 bi->sql_flags |= BSQLF_FETCH_ALL_ATTRS;
433 bi->sql_flags &= ~BSQLF_FETCH_ALL_ATTRS;
435 case BSQL_CHECK_SCHEMA:
437 bi->sql_flags |= BSQLF_CHECK_SCHEMA;
439 bi->sql_flags &= ~BSQLF_CHECK_SCHEMA;
441 case BSQL_AUTOCOMMIT:
443 bi->sql_flags |= BSQLF_AUTOCOMMIT_ON;
445 bi->sql_flags &= ~BSQLF_AUTOCOMMIT_ON;
447 case BSQL_BASE_OBJECT:
448 if ( c->be->be_nsuffix == NULL ) {
449 snprintf( c->cr_msg, sizeof( c->cr_msg ),
450 "%s: suffix must be set", c->log );
451 Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
455 if ( bi->sql_baseObject ) {
456 Debug( LDAP_DEBUG_CONFIG,
458 "\"baseObject\" already provided (will be overwritten)\n",
460 entry_free( bi->sql_baseObject );
462 if ( c->argc == 2 && !strcmp( c->argv[1], "TRUE" ))
466 return create_baseObject( c->be, c->fname, c->lineno );
469 rc = read_baseObject( c->be, c->argv[ 1 ] );
471 ch_free( bi->sql_base_ob_file );
472 bi->sql_base_ob_file = c->value_string;
477 snprintf( c->cr_msg, sizeof( c->cr_msg ),
478 "%s: trailing values in directive", c->log );
479 Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
484 if ( backsql_api_config( bi, c->argv[ 1 ], c->argc - 2, &c->argv[ 2 ] ) )
486 snprintf( c->cr_msg, sizeof( c->cr_msg ),
487 "%s: unable to load sql layer", c->log );
488 Debug( LDAP_DEBUG_ANY, "%s \"%s\"\n",
489 c->cr_msg, c->argv[1], 0 );
493 case BSQL_ALIASING_KEYWORD:
494 if ( ! BER_BVISNULL( &bi->sql_aliasing ) ) {
495 ch_free( bi->sql_aliasing.bv_val );
498 ber_str2bv( c->argv[ 1 ], strlen( c->argv[ 1 ] ) + 1, 1,
500 /* add a trailing space... */
501 bi->sql_aliasing.bv_val[ bi->sql_aliasing.bv_len - 1] = ' ';
503 case BSQL_FETCH_ATTRS: {
504 char *str, *s, *next;
505 const char *delimstr = ",";
507 str = ch_strdup( c->argv[ 1 ] );
508 for ( s = ldap_pvt_strtok( str, delimstr, &next );
510 s = ldap_pvt_strtok( NULL, delimstr, &next ) )
512 if ( strlen( s ) == 1 ) {
514 bi->sql_flags |= BSQLF_FETCH_ALL_USERATTRS;
515 c->argv[ 1 ][ s - str ] = ',';
517 } else if ( *s == '+' ) {
518 bi->sql_flags |= BSQLF_FETCH_ALL_OPATTRS;
519 c->argv[ 1 ][ s - str ] = ',';
524 bi->sql_anlist = str2anlist( bi->sql_anlist, c->argv[ 1 ], delimstr );
525 if ( bi->sql_anlist == NULL ) {
535 * Read the entries specified in fname and merge the attributes
536 * to the user defined baseObject entry. Note that if we find any errors
537 * what so ever, we will discard the entire entries, print an
538 * error message and return.
545 backsql_info *bi = (backsql_info *)be->be_private;
547 int rc = 0, lmax = 0, ldifrc;
548 unsigned long lineno = 0;
551 assert( fname != NULL );
553 fp = ldif_open( fname, "r" );
555 Debug( LDAP_DEBUG_ANY,
556 "could not open back-sql baseObject "
557 "attr file \"%s\" - absolute path?\n",
563 bi->sql_baseObject = entry_alloc();
564 if ( bi->sql_baseObject == NULL ) {
565 Debug( LDAP_DEBUG_ANY,
566 "read_baseObject_file: entry_alloc failed", 0, 0, 0 );
568 return LDAP_NO_MEMORY;
570 bi->sql_baseObject->e_name = be->be_suffix[0];
571 bi->sql_baseObject->e_nname = be->be_nsuffix[0];
572 bi->sql_baseObject->e_attrs = NULL;
574 while (( ldifrc = ldif_read_record( fp, &lineno, &buf, &lmax )) > 0 ) {
575 Entry *e = str2entry( buf );
579 fprintf( stderr, "back-sql baseObject: "
580 "could not parse entry (line=%lu)\n",
586 /* make sure the DN is the database's suffix */
587 if ( !be_issuffix( be, &e->e_nname ) ) {
589 "back-sql: invalid baseObject - "
590 "dn=\"%s\" (line=%lu)\n",
591 e->e_name.bv_val, lineno );
598 * we found a valid entry, so walk thru all the attributes in the
599 * entry, and add each attribute type and description to baseObject
601 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
602 if ( attr_merge( bi->sql_baseObject, a->a_desc,
604 ( a->a_nvals == a->a_vals ) ?
605 NULL : a->a_nvals ) )
622 entry_free( bi->sql_baseObject );
623 bi->sql_baseObject = NULL;
630 Debug( LDAP_DEBUG_CONFIG, "back-sql baseObject file \"%s\" read.\n",
642 backsql_info *bi = (backsql_info *)be->be_private;
648 snprintf( buf, sizeof(buf),
650 "objectClass: extensibleObject\n"
651 "description: builtin baseObject for back-sql\n"
652 "description: all entries mapped "
653 "in table \"ldap_entries\" "
655 "\"" BACKSQL_BASEOBJECT_IDSTR "\" "
656 "in the \"parent\" column",
657 be->be_suffix[0].bv_val );
659 bi->sql_baseObject = str2entry( buf );
660 if ( bi->sql_baseObject == NULL ) {
661 Debug( LDAP_DEBUG_TRACE,
662 "<==backsql_db_config (%s line %d): "
663 "unable to parse baseObject entry\n",
668 if ( BER_BVISEMPTY( &be->be_suffix[ 0 ] ) ) {
672 rc = ldap_bv2rdn( &be->be_suffix[ 0 ], &rdn, (char **)&p,
673 LDAP_DN_FORMAT_LDAP );
674 if ( rc != LDAP_SUCCESS ) {
675 snprintf( buf, sizeof(buf),
676 "unable to extract RDN "
677 "from baseObject DN \"%s\" (%d: %s)",
678 be->be_suffix[ 0 ].bv_val,
679 rc, ldap_err2string( rc ) );
680 Debug( LDAP_DEBUG_TRACE,
681 "<==backsql_db_config (%s line %d): %s\n",
682 fname, lineno, buf );
686 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
687 LDAPAVA *ava = rdn[ iAVA ];
688 AttributeDescription *ad = NULL;
689 slap_syntax_transform_func *transf = NULL;
690 struct berval bv = BER_BVNULL;
691 const char *text = NULL;
693 assert( ava != NULL );
695 rc = slap_bv2ad( &ava->la_attr, &ad, &text );
696 if ( rc != LDAP_SUCCESS ) {
697 snprintf( buf, sizeof(buf),
698 "AttributeDescription of naming "
699 "attribute #%d from baseObject "
701 iAVA, be->be_suffix[ 0 ].bv_val,
702 rc, ldap_err2string( rc ) );
703 Debug( LDAP_DEBUG_TRACE,
704 "<==backsql_db_config (%s line %d): %s\n",
705 fname, lineno, buf );
709 transf = ad->ad_type->sat_syntax->ssyn_pretty;
712 * transform value by pretty function
713 * if value is empty, use empty_bv
715 rc = ( *transf )( ad->ad_type->sat_syntax,
718 : (struct berval *) &slap_empty_bv,
721 if ( rc != LDAP_SUCCESS ) {
722 snprintf( buf, sizeof(buf),
723 "prettying of attribute #%d "
725 "DN \"%s\" failed: %d: %s",
726 iAVA, be->be_suffix[ 0 ].bv_val,
727 rc, ldap_err2string( rc ) );
728 Debug( LDAP_DEBUG_TRACE,
729 "<==backsql_db_config (%s line %d): "
731 fname, lineno, buf );
736 if ( !BER_BVISNULL( &bv ) ) {
737 if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) {
738 ber_memfree( ava->la_value.bv_val );
741 ava->la_flags |= LDAP_AVA_FREE_VALUE;
744 attr_merge_normalize_one( bi->sql_baseObject,
745 ad, &ava->la_value, NULL );
753 int backsql_init_cf( BackendInfo *bi )
757 bi->bi_cf_ocs = sqlocs;
758 rc = config_register_schema( sqlcfg, sqlocs );