2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2013 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|SQL_AUTOCOMMIT, (void *)sql_cf_gen,
214 "( OLcfgDbAt:6.45 NAME 'olcSqlAutocommit' "
215 "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
216 { NULL, NULL, 0, 0, 0, ARG_IGNORED,
217 NULL, NULL, NULL, NULL }
220 static ConfigOCs sqlocs[] = {
223 "NAME 'olcSqlConfig' "
224 "DESC 'SQL backend configuration' "
225 "SUP olcDatabaseConfig "
227 "MAY ( olcDbHost $ olcDbUser $ olcDbPass $ olcSqlConcatPattern $ "
228 "olcSqlSubtreeCond $ olcsqlChildrenCond $ olcSqlDnMatchCond $ "
229 "olcSqlOcQuery $ olcSqlAtQuery $ olcSqlInsEntryStmt $ "
230 "olcSqlCreateNeedsSelect $ olcSqlUpperFunc $ olcSqlUpperNeedsCast $ "
231 "olcSqlStrCastFunc $ olcSqlDelEntryStmt $ olcSqlRenEntryStmt $ "
232 "olcSqlDelObjClassesStmt $ olcSqlHasLDAPInfoDnRu $ "
233 "olcSqlFailIfNoMapping $ olcSqlAllowOrphans $ olcSqlBaseObject $ "
234 "olcSqlLayer $ olcSqlUseSubtreeShortcut $ olcSqlFetchAllAttrs $ "
235 "olcSqlFetchAttrs $ olcSqlCheckSchema $ olcSqlAliasingKeyword $ "
236 "olcSqlAliasingQuote $ olcSqlAutocommit ) )",
237 Cft_Database, sqlcfg },
238 { NULL, Cft_Abstract, NULL }
242 sql_cf_gen( ConfigArgs *c )
244 backsql_info *bi = (backsql_info *)c->be->be_private;
247 if ( c->op == SLAP_CONFIG_EMIT ) {
249 case BSQL_CONCAT_PATT:
250 if ( bi->sql_concat_patt ) {
251 c->value_string = ch_strdup( bi->sql_concat_patt );
256 case BSQL_CREATE_NEEDS_SEL:
257 if ( bi->sql_flags & BSQLF_CREATE_NEEDS_SELECT )
260 case BSQL_UPPER_NEEDS_CAST:
261 if ( bi->sql_flags & BSQLF_UPPER_NEEDS_CAST )
264 case BSQL_HAS_LDAPINFO_DN_RU:
265 if ( !(bi->sql_flags & BSQLF_DONTCHECK_LDAPINFO_DN_RU) )
267 if ( bi->sql_flags & BSQLF_HAS_LDAPINFO_DN_RU )
270 case BSQL_FAIL_IF_NO_MAPPING:
271 if ( bi->sql_flags & BSQLF_FAIL_IF_NO_MAPPING )
274 case BSQL_ALLOW_ORPHANS:
275 if ( bi->sql_flags & BSQLF_ALLOW_ORPHANS )
278 case BSQL_SUBTREE_SHORTCUT:
279 if ( bi->sql_flags & BSQLF_USE_SUBTREE_SHORTCUT )
282 case BSQL_FETCH_ALL_ATTRS:
283 if ( bi->sql_flags & BSQLF_FETCH_ALL_ATTRS )
286 case BSQL_CHECK_SCHEMA:
287 if ( bi->sql_flags & BSQLF_CHECK_SCHEMA )
290 case BSQL_AUTOCOMMIT:
291 if ( bi->sql_flags & BSQLF_AUTOCOMMIT_ON )
294 case BSQL_BASE_OBJECT:
295 if ( bi->sql_base_ob_file ) {
296 c->value_string = ch_strdup( bi->sql_base_ob_file );
297 } else if ( bi->sql_baseObject ) {
298 c->value_string = ch_strdup( "TRUE" );
309 for ( ba = bi->sql_api; ba; ba = ba->ba_next ) {
310 bv.bv_len = strlen( ba->ba_name );
312 for ( i = 0; i<ba->ba_argc; i++ )
313 bv.bv_len += strlen( ba->ba_argv[i] ) + 3;
315 bv.bv_val = ch_malloc( bv.bv_len + 1 );
316 ptr = lutil_strcopy( bv.bv_val, ba->ba_name );
318 for ( i = 0; i<ba->ba_argc; i++ ) {
321 ptr = lutil_strcopy( ptr, ba->ba_argv[i] );
325 ber_bvarray_add( &c->rvalue_vals, &bv );
331 case BSQL_ALIASING_KEYWORD:
332 if ( !BER_BVISNULL( &bi->sql_aliasing )) {
334 bv = bi->sql_aliasing;
336 value_add_one( &c->rvalue_vals, &bv );
341 case BSQL_FETCH_ATTRS:
342 if ( bi->sql_anlist ||
343 ( bi->sql_flags & (BSQLF_FETCH_ALL_USERATTRS|
344 BSQLF_FETCH_ALL_OPATTRS)))
346 char buf[BUFSIZ*2], *ptr;
348 # define WHATSLEFT ((ber_len_t) (&buf[sizeof( buf )] - ptr))
350 if ( bi->sql_anlist ) {
351 ptr = anlist_unparse( bi->sql_anlist, ptr, WHATSLEFT );
355 if ( bi->sql_flags & BSQLF_FETCH_ALL_USERATTRS ) {
356 if ( WHATSLEFT <= STRLENOF( ",*" )) return 1;
357 if ( ptr != buf ) *ptr++ = ',';
360 if ( bi->sql_flags & BSQLF_FETCH_ALL_OPATTRS ) {
361 if ( WHATSLEFT <= STRLENOF( ",+" )) return 1;
362 if ( ptr != buf ) *ptr++ = ',';
366 bv.bv_len = ptr - buf;
367 value_add_one( &c->rvalue_vals, &bv );
372 } else if ( c->op == LDAP_MOD_DELETE ) { /* FIXME */
377 case BSQL_CONCAT_PATT:
378 if ( backsql_split_pattern( c->argv[ 1 ], &bi->sql_concat_func, 2 ) ) {
379 snprintf( c->cr_msg, sizeof( c->cr_msg ),
380 "%s: unable to parse pattern \"%s\"",
381 c->log, c->argv[ 1 ] );
382 Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
385 bi->sql_concat_patt = c->value_string;
387 case BSQL_CREATE_NEEDS_SEL:
389 bi->sql_flags |= BSQLF_CREATE_NEEDS_SELECT;
391 bi->sql_flags &= ~BSQLF_CREATE_NEEDS_SELECT;
393 case BSQL_UPPER_NEEDS_CAST:
395 bi->sql_flags |= BSQLF_UPPER_NEEDS_CAST;
397 bi->sql_flags &= ~BSQLF_UPPER_NEEDS_CAST;
399 case BSQL_HAS_LDAPINFO_DN_RU:
400 bi->sql_flags |= BSQLF_DONTCHECK_LDAPINFO_DN_RU;
402 bi->sql_flags |= BSQLF_HAS_LDAPINFO_DN_RU;
404 bi->sql_flags &= ~BSQLF_HAS_LDAPINFO_DN_RU;
406 case BSQL_FAIL_IF_NO_MAPPING:
408 bi->sql_flags |= BSQLF_FAIL_IF_NO_MAPPING;
410 bi->sql_flags &= ~BSQLF_FAIL_IF_NO_MAPPING;
412 case BSQL_ALLOW_ORPHANS:
414 bi->sql_flags |= BSQLF_ALLOW_ORPHANS;
416 bi->sql_flags &= ~BSQLF_ALLOW_ORPHANS;
418 case BSQL_SUBTREE_SHORTCUT:
420 bi->sql_flags |= BSQLF_USE_SUBTREE_SHORTCUT;
422 bi->sql_flags &= ~BSQLF_USE_SUBTREE_SHORTCUT;
424 case BSQL_FETCH_ALL_ATTRS:
426 bi->sql_flags |= BSQLF_FETCH_ALL_ATTRS;
428 bi->sql_flags &= ~BSQLF_FETCH_ALL_ATTRS;
430 case BSQL_CHECK_SCHEMA:
432 bi->sql_flags |= BSQLF_CHECK_SCHEMA;
434 bi->sql_flags &= ~BSQLF_CHECK_SCHEMA;
436 case BSQL_AUTOCOMMIT:
438 bi->sql_flags |= BSQLF_AUTOCOMMIT_ON;
440 bi->sql_flags &= ~BSQLF_AUTOCOMMIT_ON;
442 case BSQL_BASE_OBJECT:
443 if ( c->be->be_nsuffix == NULL ) {
444 snprintf( c->cr_msg, sizeof( c->cr_msg ),
445 "%s: suffix must be set", c->log );
446 Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
450 if ( bi->sql_baseObject ) {
451 Debug( LDAP_DEBUG_CONFIG,
453 "\"baseObject\" already provided (will be overwritten)\n",
455 entry_free( bi->sql_baseObject );
457 if ( c->argc == 2 && !strcmp( c->argv[1], "TRUE" ))
461 return create_baseObject( c->be, c->fname, c->lineno );
464 rc = read_baseObject( c->be, c->argv[ 1 ] );
466 ch_free( bi->sql_base_ob_file );
467 bi->sql_base_ob_file = c->value_string;
472 snprintf( c->cr_msg, sizeof( c->cr_msg ),
473 "%s: trailing values in directive", c->log );
474 Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg, 0, 0 );
479 if ( backsql_api_config( bi, c->argv[ 1 ], c->argc - 2, &c->argv[ 2 ] ) )
481 snprintf( c->cr_msg, sizeof( c->cr_msg ),
482 "%s: unable to load sql layer", c->log );
483 Debug( LDAP_DEBUG_ANY, "%s \"%s\"\n",
484 c->cr_msg, c->argv[1], 0 );
488 case BSQL_ALIASING_KEYWORD:
489 if ( ! BER_BVISNULL( &bi->sql_aliasing ) ) {
490 ch_free( bi->sql_aliasing.bv_val );
493 ber_str2bv( c->argv[ 1 ], strlen( c->argv[ 1 ] ) + 1, 1,
495 /* add a trailing space... */
496 bi->sql_aliasing.bv_val[ bi->sql_aliasing.bv_len - 1] = ' ';
498 case BSQL_FETCH_ATTRS: {
499 char *str, *s, *next;
500 const char *delimstr = ",";
502 str = ch_strdup( c->argv[ 1 ] );
503 for ( s = ldap_pvt_strtok( str, delimstr, &next );
505 s = ldap_pvt_strtok( NULL, delimstr, &next ) )
507 if ( strlen( s ) == 1 ) {
509 bi->sql_flags |= BSQLF_FETCH_ALL_USERATTRS;
510 c->argv[ 1 ][ s - str ] = ',';
512 } else if ( *s == '+' ) {
513 bi->sql_flags |= BSQLF_FETCH_ALL_OPATTRS;
514 c->argv[ 1 ][ s - str ] = ',';
519 bi->sql_anlist = str2anlist( bi->sql_anlist, c->argv[ 1 ], delimstr );
520 if ( bi->sql_anlist == NULL ) {
530 * Read the entries specified in fname and merge the attributes
531 * to the user defined baseObject entry. Note that if we find any errors
532 * what so ever, we will discard the entire entries, print an
533 * error message and return.
540 backsql_info *bi = (backsql_info *)be->be_private;
542 int rc = 0, lmax = 0, ldifrc;
543 unsigned long lineno = 0;
546 assert( fname != NULL );
548 fp = ldif_open( fname, "r" );
550 Debug( LDAP_DEBUG_ANY,
551 "could not open back-sql baseObject "
552 "attr file \"%s\" - absolute path?\n",
558 bi->sql_baseObject = entry_alloc();
559 if ( bi->sql_baseObject == NULL ) {
560 Debug( LDAP_DEBUG_ANY,
561 "read_baseObject_file: entry_alloc failed", 0, 0, 0 );
563 return LDAP_NO_MEMORY;
565 bi->sql_baseObject->e_name = be->be_suffix[0];
566 bi->sql_baseObject->e_nname = be->be_nsuffix[0];
567 bi->sql_baseObject->e_attrs = NULL;
569 while (( ldifrc = ldif_read_record( fp, &lineno, &buf, &lmax )) > 0 ) {
570 Entry *e = str2entry( buf );
574 fprintf( stderr, "back-sql baseObject: "
575 "could not parse entry (line=%lu)\n",
581 /* make sure the DN is the database's suffix */
582 if ( !be_issuffix( be, &e->e_nname ) ) {
584 "back-sql: invalid baseObject - "
585 "dn=\"%s\" (line=%lu)\n",
586 e->e_name.bv_val, lineno );
593 * we found a valid entry, so walk thru all the attributes in the
594 * entry, and add each attribute type and description to baseObject
596 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
597 if ( attr_merge( bi->sql_baseObject, a->a_desc,
599 ( a->a_nvals == a->a_vals ) ?
600 NULL : a->a_nvals ) )
617 entry_free( bi->sql_baseObject );
618 bi->sql_baseObject = NULL;
625 Debug( LDAP_DEBUG_CONFIG, "back-sql baseObject file \"%s\" read.\n",
637 backsql_info *bi = (backsql_info *)be->be_private;
643 snprintf( buf, sizeof(buf),
645 "objectClass: extensibleObject\n"
646 "description: builtin baseObject for back-sql\n"
647 "description: all entries mapped "
648 "in table \"ldap_entries\" "
650 "\"" BACKSQL_BASEOBJECT_IDSTR "\" "
651 "in the \"parent\" column",
652 be->be_suffix[0].bv_val );
654 bi->sql_baseObject = str2entry( buf );
655 if ( bi->sql_baseObject == NULL ) {
656 Debug( LDAP_DEBUG_TRACE,
657 "<==backsql_db_config (%s line %d): "
658 "unable to parse baseObject entry\n",
663 if ( BER_BVISEMPTY( &be->be_suffix[ 0 ] ) ) {
667 rc = ldap_bv2rdn( &be->be_suffix[ 0 ], &rdn, (char **)&p,
668 LDAP_DN_FORMAT_LDAP );
669 if ( rc != LDAP_SUCCESS ) {
670 snprintf( buf, sizeof(buf),
671 "unable to extract RDN "
672 "from baseObject DN \"%s\" (%d: %s)",
673 be->be_suffix[ 0 ].bv_val,
674 rc, ldap_err2string( rc ) );
675 Debug( LDAP_DEBUG_TRACE,
676 "<==backsql_db_config (%s line %d): %s\n",
677 fname, lineno, buf );
681 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
682 LDAPAVA *ava = rdn[ iAVA ];
683 AttributeDescription *ad = NULL;
684 slap_syntax_transform_func *transf = NULL;
685 struct berval bv = BER_BVNULL;
686 const char *text = NULL;
688 assert( ava != NULL );
690 rc = slap_bv2ad( &ava->la_attr, &ad, &text );
691 if ( rc != LDAP_SUCCESS ) {
692 snprintf( buf, sizeof(buf),
693 "AttributeDescription of naming "
694 "attribute #%d from baseObject "
696 iAVA, be->be_suffix[ 0 ].bv_val,
697 rc, ldap_err2string( rc ) );
698 Debug( LDAP_DEBUG_TRACE,
699 "<==backsql_db_config (%s line %d): %s\n",
700 fname, lineno, buf );
704 transf = ad->ad_type->sat_syntax->ssyn_pretty;
707 * transform value by pretty function
708 * if value is empty, use empty_bv
710 rc = ( *transf )( ad->ad_type->sat_syntax,
713 : (struct berval *) &slap_empty_bv,
716 if ( rc != LDAP_SUCCESS ) {
717 snprintf( buf, sizeof(buf),
718 "prettying of attribute #%d "
720 "DN \"%s\" failed: %d: %s",
721 iAVA, be->be_suffix[ 0 ].bv_val,
722 rc, ldap_err2string( rc ) );
723 Debug( LDAP_DEBUG_TRACE,
724 "<==backsql_db_config (%s line %d): "
726 fname, lineno, buf );
731 if ( !BER_BVISNULL( &bv ) ) {
732 if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) {
733 ber_memfree( ava->la_value.bv_val );
736 ava->la_flags |= LDAP_AVA_FREE_VALUE;
739 attr_merge_normalize_one( bi->sql_baseObject,
740 ad, &ava->la_value, NULL );
748 int backsql_init_cf( BackendInfo *bi )
752 bi->bi_cf_ocs = sqlocs;
753 rc = config_register_schema( sqlcfg, sqlocs );