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