1 /*        $NetBSD: init.c,v 1.3 2021/08/14 16:15:01 christos Exp $    */
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1999-2021 The OpenLDAP Foundation.
7  * Portions Copyright 1999 Dmitry Kovalev.
8  * Portions Copyright 2002 Pierangelo Masarati.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in the file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 /* ACKNOWLEDGEMENTS:
20  * This work was initially developed by Dmitry Kovalev for inclusion
21  * by OpenLDAP Software.  Additional significant contributors include
22  * Pierangelo Masarati.
23  */
24 
25 #include <sys/cdefs.h>
26 __RCSID("$NetBSD: init.c,v 1.3 2021/08/14 16:15:01 christos Exp $");
27 
28 #include "portable.h"
29 
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include "ac/string.h"
33 
34 #include "slap.h"
35 #include "slap-config.h"
36 #include "proto-sql.h"
37 
38 int
sql_back_initialize(BackendInfo * bi)39 sql_back_initialize(
40           BackendInfo         *bi )
41 {
42           static char *controls[] = {
43                     LDAP_CONTROL_ASSERT,
44                     LDAP_CONTROL_MANAGEDSAIT,
45                     LDAP_CONTROL_NOOP,
46 #ifdef SLAP_CONTROL_X_TREE_DELETE
47                     SLAP_CONTROL_X_TREE_DELETE,
48 #endif /* SLAP_CONTROL_X_TREE_DELETE */
49 #ifndef BACKSQL_ARBITRARY_KEY
50                     LDAP_CONTROL_PAGEDRESULTS,
51 #endif /* ! BACKSQL_ARBITRARY_KEY */
52                     NULL
53           };
54           int rc;
55 
56           bi->bi_controls = controls;
57 
58           bi->bi_flags |=
59 #if 0
60                     SLAP_BFLAG_INCREMENT |
61 #endif
62                     SLAP_BFLAG_REFERRALS;
63 
64           Debug( LDAP_DEBUG_TRACE,"==>sql_back_initialize()\n" );
65 
66           bi->bi_db_init = backsql_db_init;
67           bi->bi_db_config = config_generic_wrapper;
68           bi->bi_db_open = backsql_db_open;
69           bi->bi_db_close = backsql_db_close;
70           bi->bi_db_destroy = backsql_db_destroy;
71 
72           bi->bi_op_abandon = 0;
73           bi->bi_op_compare = backsql_compare;
74           bi->bi_op_bind = backsql_bind;
75           bi->bi_op_unbind = 0;
76           bi->bi_op_search = backsql_search;
77           bi->bi_op_modify = backsql_modify;
78           bi->bi_op_modrdn = backsql_modrdn;
79           bi->bi_op_add = backsql_add;
80           bi->bi_op_delete = backsql_delete;
81 
82           bi->bi_chk_referrals = 0;
83           bi->bi_operational = backsql_operational;
84           bi->bi_entry_get_rw = backsql_entry_get;
85           bi->bi_entry_release_rw = backsql_entry_release;
86 
87           bi->bi_connection_init = 0;
88 
89           rc = backsql_init_cf( bi );
90           Debug( LDAP_DEBUG_TRACE,"<==sql_back_initialize()\n" );
91           return rc;
92 }
93 
94 int
backsql_destroy(BackendInfo * bi)95 backsql_destroy(
96           BackendInfo         *bi )
97 {
98           Debug( LDAP_DEBUG_TRACE, "==>backsql_destroy()\n" );
99           Debug( LDAP_DEBUG_TRACE, "<==backsql_destroy()\n" );
100           return 0;
101 }
102 
103 int
backsql_db_init(BackendDB * bd,ConfigReply * cr)104 backsql_db_init(
105           BackendDB           *bd,
106           ConfigReply         *cr )
107 {
108           backsql_info        *bi;
109           int                 rc = 0;
110 
111           Debug( LDAP_DEBUG_TRACE, "==>backsql_db_init()\n" );
112 
113           bi = (backsql_info *)ch_calloc( 1, sizeof( backsql_info ) );
114           ldap_pvt_thread_mutex_init( &bi->sql_dbconn_mutex );
115           ldap_pvt_thread_mutex_init( &bi->sql_schema_mutex );
116 
117           if ( backsql_init_db_env( bi ) != SQL_SUCCESS ) {
118                     rc = -1;
119           }
120 
121           bd->be_private = bi;
122           bd->be_cf_ocs = bd->bd_info->bi_cf_ocs;
123 
124           Debug( LDAP_DEBUG_TRACE, "<==backsql_db_init()\n" );
125 
126           return rc;
127 }
128 
129 int
backsql_db_destroy(BackendDB * bd,ConfigReply * cr)130 backsql_db_destroy(
131           BackendDB           *bd,
132           ConfigReply         *cr )
133 {
134           backsql_info        *bi = (backsql_info*)bd->be_private;
135 
136           Debug( LDAP_DEBUG_TRACE, "==>backsql_db_destroy()\n" );
137 
138           backsql_free_db_env( bi );
139           ldap_pvt_thread_mutex_destroy( &bi->sql_dbconn_mutex );
140           backsql_destroy_schema_map( bi );
141           ldap_pvt_thread_mutex_destroy( &bi->sql_schema_mutex );
142 
143           if ( bi->sql_dbname ) {
144                     ch_free( bi->sql_dbname );
145           }
146           if ( bi->sql_dbuser ) {
147                     ch_free( bi->sql_dbuser );
148           }
149           if ( bi->sql_dbpasswd ) {
150                     ch_free( bi->sql_dbpasswd );
151           }
152           if ( bi->sql_dbhost ) {
153                     ch_free( bi->sql_dbhost );
154           }
155           if ( bi->sql_upper_func.bv_val ) {
156                     ch_free( bi->sql_upper_func.bv_val );
157                     ch_free( bi->sql_upper_func_open.bv_val );
158                     ch_free( bi->sql_upper_func_close.bv_val );
159           }
160           if ( bi->sql_concat_func ) {
161                     ber_bvarray_free( bi->sql_concat_func );
162           }
163           if ( !BER_BVISNULL( &bi->sql_strcast_func ) ) {
164                     ch_free( bi->sql_strcast_func.bv_val );
165           }
166           if ( !BER_BVISNULL( &bi->sql_children_cond ) ) {
167                     ch_free( bi->sql_children_cond.bv_val );
168           }
169           if ( !BER_BVISNULL( &bi->sql_dn_match_cond ) ) {
170                     ch_free( bi->sql_dn_match_cond.bv_val );
171           }
172           if ( !BER_BVISNULL( &bi->sql_subtree_cond ) ) {
173                     ch_free( bi->sql_subtree_cond.bv_val );
174           }
175           if ( !BER_BVISNULL( &bi->sql_dn_oc_aliasing ) ) {
176                     ch_free( bi->sql_dn_oc_aliasing.bv_val );
177           }
178           if ( bi->sql_oc_query ) {
179                     ch_free( bi->sql_oc_query );
180           }
181           if ( bi->sql_at_query ) {
182                     ch_free( bi->sql_at_query );
183           }
184           if ( bi->sql_id_query ) {
185                     ch_free( bi->sql_id_query );
186           }
187           if ( bi->sql_has_children_query ) {
188                     ch_free( bi->sql_has_children_query );
189           }
190           if ( bi->sql_insentry_stmt ) {
191                     ch_free( bi->sql_insentry_stmt );
192           }
193           if ( bi->sql_delentry_stmt ) {
194                     ch_free( bi->sql_delentry_stmt );
195           }
196           if ( bi->sql_renentry_stmt ) {
197                     ch_free( bi->sql_renentry_stmt );
198           }
199           if ( bi->sql_delobjclasses_stmt ) {
200                     ch_free( bi->sql_delobjclasses_stmt );
201           }
202           if ( !BER_BVISNULL( &bi->sql_aliasing ) ) {
203                     ch_free( bi->sql_aliasing.bv_val );
204           }
205           if ( !BER_BVISNULL( &bi->sql_aliasing_quote ) ) {
206                     ch_free( bi->sql_aliasing_quote.bv_val );
207           }
208 
209           if ( bi->sql_anlist ) {
210                     int       i;
211 
212                     for ( i = 0; !BER_BVISNULL( &bi->sql_anlist[ i ].an_name ); i++ )
213                     {
214                               ch_free( bi->sql_anlist[ i ].an_name.bv_val );
215                     }
216                     ch_free( bi->sql_anlist );
217           }
218 
219           if ( bi->sql_baseObject ) {
220                     entry_free( bi->sql_baseObject );
221           }
222 
223           ch_free( bi );
224 
225           Debug( LDAP_DEBUG_TRACE, "<==backsql_db_destroy()\n" );
226           return 0;
227 }
228 
229 int
backsql_db_open(BackendDB * bd,ConfigReply * cr)230 backsql_db_open(
231           BackendDB           *bd,
232           ConfigReply         *cr )
233 {
234           backsql_info        *bi = (backsql_info*)bd->be_private;
235           struct berbuf       bb = BB_NULL;
236 
237           Connection          conn = { 0 };
238           OperationBuffer opbuf;
239           Operation*          op;
240           SQLHDBC             dbh = SQL_NULL_HDBC;
241           void                *thrctx = ldap_pvt_thread_pool_context();
242 
243           Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): "
244                     "testing RDBMS connection\n" );
245           if ( bi->sql_dbname == NULL ) {
246                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
247                               "datasource name not specified "
248                               "(use \"dbname\" directive in slapd.conf)\n" );
249                     return 1;
250           }
251 
252           if ( bi->sql_concat_func == NULL ) {
253                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
254                               "concat func not specified (use \"concat_pattern\" "
255                               "directive in slapd.conf)\n" );
256 
257                     if ( backsql_split_pattern( backsql_def_concat_func,
258                                         &bi->sql_concat_func, 2 ) ) {
259                               Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
260                                         "unable to parse pattern \"%s\"",
261                                         backsql_def_concat_func );
262                               return 1;
263                     }
264           }
265 
266           /*
267            * see back-sql.h for default values
268            */
269           if ( BER_BVISNULL( &bi->sql_aliasing ) ) {
270                     ber_str2bv( BACKSQL_ALIASING,
271                               STRLENOF( BACKSQL_ALIASING ),
272                               1, &bi->sql_aliasing );
273           }
274 
275           if ( BER_BVISNULL( &bi->sql_aliasing_quote ) ) {
276                     ber_str2bv( BACKSQL_ALIASING_QUOTE,
277                               STRLENOF( BACKSQL_ALIASING_QUOTE ),
278                               1, &bi->sql_aliasing_quote );
279           }
280 
281           /*
282            * Prepare cast string as required
283            */
284           if ( bi->sql_upper_func.bv_val ) {
285                     char buf[1024];
286 
287                     if ( BACKSQL_UPPER_NEEDS_CAST( bi ) ) {
288                               snprintf( buf, sizeof( buf ),
289                                         "%s(cast (" /* ? as varchar(%d))) */ ,
290                                         bi->sql_upper_func.bv_val );
291                               ber_str2bv( buf, 0, 1, &bi->sql_upper_func_open );
292 
293                               snprintf( buf, sizeof( buf ),
294                                         /* (cast(? */ " as varchar(%d)))",
295                                         BACKSQL_MAX_DN_LEN );
296                               ber_str2bv( buf, 0, 1, &bi->sql_upper_func_close );
297 
298                     } else {
299                               snprintf( buf, sizeof( buf ), "%s(" /* ?) */ ,
300                                                   bi->sql_upper_func.bv_val );
301                               ber_str2bv( buf, 0, 1, &bi->sql_upper_func_open );
302 
303                               ber_str2bv( /* (? */ ")", 0, 1, &bi->sql_upper_func_close );
304                     }
305           }
306 
307           /* normalize filter values only if necessary */
308           bi->sql_caseIgnoreMatch = mr_find( "caseIgnoreMatch" );
309           assert( bi->sql_caseIgnoreMatch != NULL );
310 
311           bi->sql_telephoneNumberMatch = mr_find( "telephoneNumberMatch" );
312           assert( bi->sql_telephoneNumberMatch != NULL );
313 
314           if ( bi->sql_dbuser == NULL ) {
315                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
316                               "user name not specified "
317                               "(use \"dbuser\" directive in slapd.conf)\n" );
318                     return 1;
319           }
320 
321           if ( BER_BVISNULL( &bi->sql_subtree_cond ) ) {
322                     /*
323                      * Prepare concat function for subtree search condition
324                      */
325                     struct berval       concat;
326                     struct berval       values[] = {
327                               BER_BVC( "'%'" ),
328                               BER_BVC( "?" ),
329                               BER_BVNULL
330                     };
331                     struct berbuf       bb = BB_NULL;
332 
333                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
334                               "subtree search SQL condition not specified "
335                               "(use \"subtree_cond\" directive in slapd.conf); "
336                               "preparing default\n" );
337 
338                     if ( backsql_prepare_pattern( bi->sql_concat_func, values,
339                                         &concat ) ) {
340                               Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
341                                         "unable to prepare CONCAT pattern for subtree search" );
342                               return 1;
343                     }
344 
345                     if ( bi->sql_upper_func.bv_val ) {
346 
347                               /*
348                                * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%',?))
349                                */
350 
351                               backsql_strfcat_x( &bb, NULL, "blbbb",
352                                                   &bi->sql_upper_func,
353                                                   (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ),
354                                                             "(ldap_entries.dn) LIKE ",
355                                                   &bi->sql_upper_func_open,
356                                                   &concat,
357                                                   &bi->sql_upper_func_close );
358 
359                     } else {
360 
361                               /*
362                                * ldap_entries.dn LIKE CONCAT('%',?)
363                                */
364 
365                               backsql_strfcat_x( &bb, NULL, "lb",
366                                                   (ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ),
367                                                             "ldap_entries.dn LIKE ",
368                                                   &concat );
369                     }
370 
371                     ch_free( concat.bv_val );
372 
373                     bi->sql_subtree_cond = bb.bb_val;
374 
375                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
376                               "setting \"%s\" as default \"subtree_cond\"\n",
377                               bi->sql_subtree_cond.bv_val );
378           }
379 
380           if ( bi->sql_children_cond.bv_val == NULL ) {
381                     /*
382                      * Prepare concat function for children search condition
383                      */
384                     struct berval       concat;
385                     struct berval       values[] = {
386                               BER_BVC( "'%,'" ),
387                               BER_BVC( "?" ),
388                               BER_BVNULL
389                     };
390                     struct berbuf       bb = BB_NULL;
391 
392                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
393                               "children search SQL condition not specified "
394                               "(use \"children_cond\" directive in slapd.conf); "
395                               "preparing default\n" );
396 
397                     if ( backsql_prepare_pattern( bi->sql_concat_func, values,
398                                         &concat ) ) {
399                               Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
400                                         "unable to prepare CONCAT pattern for children search" );
401                               return 1;
402                     }
403 
404                     if ( bi->sql_upper_func.bv_val ) {
405 
406                               /*
407                                * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?))
408                                */
409 
410                               backsql_strfcat_x( &bb, NULL, "blbbb",
411                                                   &bi->sql_upper_func,
412                                                   (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ),
413                                                             "(ldap_entries.dn) LIKE ",
414                                                   &bi->sql_upper_func_open,
415                                                   &concat,
416                                                   &bi->sql_upper_func_close );
417 
418                     } else {
419 
420                               /*
421                                * ldap_entries.dn LIKE CONCAT('%,',?)
422                                */
423 
424                               backsql_strfcat_x( &bb, NULL, "lb",
425                                                   (ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ),
426                                                             "ldap_entries.dn LIKE ",
427                                                   &concat );
428                     }
429 
430                     ch_free( concat.bv_val );
431 
432                     bi->sql_children_cond = bb.bb_val;
433 
434                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
435                               "setting \"%s\" as default \"children_cond\"\n",
436                               bi->sql_children_cond.bv_val );
437           }
438 
439           if ( bi->sql_dn_match_cond.bv_val == NULL ) {
440                     /*
441                      * Prepare concat function for dn match search condition
442                      */
443                     struct berbuf       bb = BB_NULL;
444 
445                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
446                               "DN match search SQL condition not specified "
447                               "(use \"dn_match_cond\" directive in slapd.conf); "
448                               "preparing default\n" );
449 
450                     if ( bi->sql_upper_func.bv_val ) {
451 
452                               /*
453                                * UPPER(ldap_entries.dn)=?
454                                */
455 
456                               backsql_strfcat_x( &bb, NULL, "blbcb",
457                                                   &bi->sql_upper_func,
458                                                   (ber_len_t)STRLENOF( "(ldap_entries.dn)=" ),
459                                                             "(ldap_entries.dn)=",
460                                                   &bi->sql_upper_func_open,
461                                                   '?',
462                                                   &bi->sql_upper_func_close );
463 
464                     } else {
465 
466                               /*
467                                * ldap_entries.dn=?
468                                */
469 
470                               backsql_strfcat_x( &bb, NULL, "l",
471                                                   (ber_len_t)STRLENOF( "ldap_entries.dn=?" ),
472                                                             "ldap_entries.dn=?" );
473                     }
474 
475                     bi->sql_dn_match_cond = bb.bb_val;
476 
477                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
478                               "setting \"%s\" as default \"dn_match_cond\"\n",
479                               bi->sql_dn_match_cond.bv_val );
480           }
481 
482           if ( bi->sql_oc_query == NULL ) {
483                     if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
484                               bi->sql_oc_query =
485                                         ch_strdup( backsql_def_needs_select_oc_query );
486 
487                     } else {
488                               bi->sql_oc_query = ch_strdup( backsql_def_oc_query );
489                     }
490 
491                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
492                               "objectclass mapping SQL statement not specified "
493                               "(use \"oc_query\" directive in slapd.conf)\n" );
494                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
495                               "setting \"%s\" by default\n", bi->sql_oc_query );
496           }
497 
498           if ( bi->sql_at_query == NULL ) {
499                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
500                               "attribute mapping SQL statement not specified "
501                               "(use \"at_query\" directive in slapd.conf)\n" );
502                     Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
503                               "setting \"%s\" by default\n",
504                               backsql_def_at_query );
505                     bi->sql_at_query = ch_strdup( backsql_def_at_query );
506           }
507 
508           if ( bi->sql_insentry_stmt == NULL ) {
509                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
510                               "entry insertion SQL statement not specified "
511                               "(use \"insentry_stmt\" directive in slapd.conf)\n" );
512                     Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
513                               "setting \"%s\" by default\n",
514                               backsql_def_insentry_stmt );
515                     bi->sql_insentry_stmt = ch_strdup( backsql_def_insentry_stmt );
516           }
517 
518           if ( bi->sql_delentry_stmt == NULL ) {
519                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
520                               "entry deletion SQL statement not specified "
521                               "(use \"delentry_stmt\" directive in slapd.conf)\n" );
522                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
523                               "setting \"%s\" by default\n",
524                               backsql_def_delentry_stmt );
525                     bi->sql_delentry_stmt = ch_strdup( backsql_def_delentry_stmt );
526           }
527 
528           if ( bi->sql_renentry_stmt == NULL ) {
529                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
530                               "entry deletion SQL statement not specified "
531                               "(use \"renentry_stmt\" directive in slapd.conf)\n" );
532                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
533                               "setting \"%s\" by default\n",
534                               backsql_def_renentry_stmt );
535                     bi->sql_renentry_stmt = ch_strdup( backsql_def_renentry_stmt );
536           }
537 
538           if ( bi->sql_delobjclasses_stmt == NULL ) {
539                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
540                               "objclasses deletion SQL statement not specified "
541                               "(use \"delobjclasses_stmt\" directive in slapd.conf)\n" );
542                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
543                               "setting \"%s\" by default\n",
544                               backsql_def_delobjclasses_stmt );
545                     bi->sql_delobjclasses_stmt = ch_strdup( backsql_def_delobjclasses_stmt );
546           }
547 
548           /* This should just be to force schema loading */
549           connection_fake_init2( &conn, &opbuf, thrctx, 0 );
550           op = &opbuf.ob_op;
551           op->o_bd = bd;
552           if ( backsql_get_db_conn( op, &dbh ) != LDAP_SUCCESS ) {
553                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
554                               "connection failed, exiting\n" );
555                     return 1;
556           }
557           if ( backsql_load_schema_map( bi, dbh ) != LDAP_SUCCESS ) {
558                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
559                               "schema mapping failed, exiting\n" );
560                     return 1;
561           }
562           if ( backsql_free_db_conn( op, dbh ) != SQL_SUCCESS ) {
563                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
564                               "connection free failed\n" );
565           }
566           if ( !BACKSQL_SCHEMA_LOADED( bi ) ) {
567                     Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
568                               "test failed, schema map not loaded - exiting\n" );
569                     return 1;
570           }
571 
572           /*
573            * Prepare ID selection query
574            */
575           if ( bi->sql_id_query == NULL ) {
576                     /* no custom id_query provided */
577                     if ( bi->sql_upper_func.bv_val == NULL ) {
578                               backsql_strcat_x( &bb, NULL, backsql_id_query, "dn=?", NULL );
579 
580                     } else {
581                               if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
582                                         backsql_strcat_x( &bb, NULL, backsql_id_query,
583                                                             "dn_ru=?", NULL );
584                               } else {
585                                         if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
586                                                   backsql_strfcat_x( &bb, NULL, "sbl",
587                                                                       backsql_id_query,
588                                                                       &bi->sql_upper_func,
589                                                                       (ber_len_t)STRLENOF( "(dn)=?" ), "(dn)=?" );
590                                         } else {
591                                                   backsql_strfcat_x( &bb, NULL, "sblbcb",
592                                                                       backsql_id_query,
593                                                                       &bi->sql_upper_func,
594                                                                       (ber_len_t)STRLENOF( "(dn)=" ), "(dn)=",
595                                                                       &bi->sql_upper_func_open,
596                                                                       '?',
597                                                                       &bi->sql_upper_func_close );
598                                         }
599                               }
600                     }
601                     bi->sql_id_query = bb.bb_val.bv_val;
602           }
603 
604           /*
605            * Prepare children count query
606            */
607           BER_BVZERO( &bb.bb_val );
608           bb.bb_len = 0;
609           backsql_strfcat_x( &bb, NULL, "sbsb",
610                               "SELECT COUNT(distinct subordinates.id) "
611                               "FROM ldap_entries,ldap_entries ",
612                               &bi->sql_aliasing, "subordinates "
613                               "WHERE subordinates.parent=ldap_entries.id AND ",
614                               &bi->sql_dn_match_cond );
615           bi->sql_has_children_query = bb.bb_val.bv_val;
616 
617           /*
618            * Prepare DN and objectClass aliasing bit of query
619            */
620           BER_BVZERO( &bb.bb_val );
621           bb.bb_len = 0;
622           backsql_strfcat_x( &bb, NULL, "sbbsbsbbsb",
623                               " ", &bi->sql_aliasing, &bi->sql_aliasing_quote,
624                               "objectClass", &bi->sql_aliasing_quote,
625                               ",ldap_entries.dn ", &bi->sql_aliasing,
626                               &bi->sql_aliasing_quote, "dn", &bi->sql_aliasing_quote );
627           bi->sql_dn_oc_aliasing = bb.bb_val;
628 
629           /* should never happen! */
630           assert( bd->be_nsuffix != NULL );
631 
632           if ( BER_BVISNULL( &bd->be_nsuffix[ 1 ] ) ) {
633                     /* enable if only one suffix is defined */
634                     bi->sql_flags |= BSQLF_USE_SUBTREE_SHORTCUT;
635           }
636 
637           bi->sql_flags |= BSQLF_CHECK_SCHEMA;
638 
639           Debug( LDAP_DEBUG_TRACE, "<==backsql_db_open(): "
640                     "test succeeded, schema map loaded\n" );
641           return 0;
642 }
643 
644 int
backsql_db_close(BackendDB * bd,ConfigReply * cr)645 backsql_db_close(
646           BackendDB *bd,
647           ConfigReply         *cr )
648 {
649           backsql_info        *bi = (backsql_info*)bd->be_private;
650 
651           Debug( LDAP_DEBUG_TRACE, "==>backsql_db_close()\n" );
652 
653           backsql_conn_destroy( bi );
654 
655           Debug( LDAP_DEBUG_TRACE, "<==backsql_db_close()\n" );
656 
657           return 0;
658 }
659 
660 #if SLAPD_SQL == SLAPD_MOD_DYNAMIC
661 
662 /* conditionally define the init_module() function */
663 SLAP_BACKEND_INIT_MODULE( sql )
664 
665 #endif /* SLAPD_SQL == SLAPD_MOD_DYNAMIC */
666 
667