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