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