]> git.sur5r.net Git - openldap/blob - servers/slapd/back-sql/init.c
Consolidated static/dynamic backend switches
[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-2004 The OpenLDAP Foundation.
5  * Portions Copyright 1999 Dmitry Kovalev.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* ACKNOWLEDGEMENTS:
17  * This work was initially developed by Dmitry Kovalev for inclusion
18  * by OpenLDAP Software.
19  */
20
21 #include "portable.h"
22
23 #ifdef SLAPD_SQL
24
25 #include <stdio.h>
26 #include <sys/types.h>
27
28 #include "slap.h"
29 #include "ldap_pvt.h"
30 #include "proto-sql.h"
31
32 #if SLAPD_SQL == SLAPD_MOD_DYNAMIC
33
34 int
35 init_module(
36         int             argc, 
37         char            *argv[] )
38 {
39         BackendInfo bi;
40
41         memset( &bi, '\0', sizeof( bi ) );
42         bi.bi_type = "sql";
43         bi.bi_init = sql_back_initialize;
44
45         backend_add( &bi );
46         return 0;
47 }
48
49 #endif /* SLAPD_SQL */
50
51 int
52 sql_back_initialize(
53         BackendInfo     *bi )
54
55         static char *controls[] = {
56 #if 0 /* needs updating */
57 #ifdef LDAP_CONTROL_NOOP
58                 LDAP_CONTROL_NOOP,
59 #endif /* LDAP_CONTROL_NOOP */
60 #endif
61 #ifdef LDAP_CONTROL_VALUESRETURNFILTER
62                 LDAP_CONTROL_VALUESRETURNFILTER,
63 #endif /* LDAP_CONTROL_VALUESRETURNFILTER */
64                 NULL
65         };
66
67         bi->bi_controls = controls;
68
69         Debug( LDAP_DEBUG_TRACE,"==>backsql_initialize()\n", 0, 0, 0 );
70         
71         bi->bi_open = 0;
72         bi->bi_config = 0;
73         bi->bi_close = 0;
74         bi->bi_destroy = 0;
75
76         bi->bi_db_init = backsql_db_init;
77         bi->bi_db_config = backsql_db_config;
78         bi->bi_db_open = backsql_db_open;
79         bi->bi_db_close = backsql_db_close;
80         bi->bi_db_destroy = backsql_db_destroy;
81
82         bi->bi_op_abandon = 0;
83         bi->bi_op_compare = backsql_compare;
84         bi->bi_op_bind = backsql_bind;
85         bi->bi_op_unbind = 0;
86         bi->bi_op_search = backsql_search;
87         bi->bi_op_modify = backsql_modify;
88         bi->bi_op_modrdn = backsql_modrdn;
89         bi->bi_op_add = backsql_add;
90         bi->bi_op_delete = backsql_delete;
91         
92         bi->bi_chk_referrals = 0;
93         bi->bi_operational = backsql_operational;
94  
95         bi->bi_connection_init = 0;
96         bi->bi_connection_destroy = backsql_connection_destroy;
97         
98         Debug( LDAP_DEBUG_TRACE,"<==backsql_initialize()\n", 0, 0, 0 );
99         return 0;
100 }
101
102
103 int
104 backsql_destroy( 
105         BackendInfo     *bi )
106 {
107         Debug( LDAP_DEBUG_TRACE, "==>backsql_destroy()\n", 0, 0, 0 );
108         Debug( LDAP_DEBUG_TRACE, "<==backsql_destroy()\n", 0, 0, 0 );
109         return 0;
110 }
111
112 int
113 backsql_db_init(
114         BackendDB       *bd )
115 {
116         backsql_info *si;
117  
118         Debug( LDAP_DEBUG_TRACE, "==>backsql_db_init()\n", 0, 0, 0 );
119         si = (backsql_info *)ch_calloc( 1, sizeof( backsql_info ) );
120         memset( si, '\0', sizeof( backsql_info ) );
121         ldap_pvt_thread_mutex_init( &si->dbconn_mutex );
122         ldap_pvt_thread_mutex_init( &si->schema_mutex );
123         backsql_init_db_env( si );
124
125         bd->be_private = si;
126         Debug( LDAP_DEBUG_TRACE, "<==backsql_db_init()\n", 0, 0, 0 );
127         return 0;
128 }
129
130 int
131 backsql_db_destroy(
132         BackendDB       *bd )
133 {
134         backsql_info *si = (backsql_info*)bd->be_private;
135  
136         Debug( LDAP_DEBUG_TRACE, "==>backsql_db_destroy()\n", 0, 0, 0 );
137         ldap_pvt_thread_mutex_lock( &si->dbconn_mutex );
138         backsql_free_db_env( si );
139         ldap_pvt_thread_mutex_unlock( &si->dbconn_mutex );
140         ldap_pvt_thread_mutex_destroy( &si->dbconn_mutex );
141         ldap_pvt_thread_mutex_lock( &si->schema_mutex );
142         backsql_destroy_schema_map( si );
143         ldap_pvt_thread_mutex_unlock( &si->schema_mutex );
144         ldap_pvt_thread_mutex_destroy( &si->schema_mutex );
145         free( si->dbname );
146         free( si->dbuser );
147         if ( si->dbpasswd ) {
148                 free( si->dbpasswd );
149         }
150         if ( si->dbhost ) {
151                 free( si->dbhost );
152         }
153         if ( si->upper_func.bv_val ) {
154                 free( si->upper_func.bv_val );
155                 free( si->upper_func_open.bv_val );
156                 free( si->upper_func_close.bv_val );
157         }
158         
159         free( si->subtree_cond.bv_val );
160         free( si->oc_query );
161         free( si->at_query );
162         free( si->insentry_query );
163         free( si->delentry_query );
164         free( si );
165         
166         Debug( LDAP_DEBUG_TRACE, "<==backsql_db_destroy()\n", 0, 0, 0 );
167         return 0;
168 }
169
170 int
171 backsql_db_open(
172         BackendDB       *bd )
173 {
174         backsql_info    *si = (backsql_info*)bd->be_private;
175         SQLHDBC         dbh;
176         ber_len_t       idq_len;
177         struct berbuf   bb = BB_NULL;
178
179         Operation       otmp;
180                 
181         Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): "
182                 "testing RDBMS connection\n", 0, 0, 0 );
183         if ( si->dbname == NULL ) {
184                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
185                         "datasource name not specified "
186                         "(use \"dbname\" directive in slapd.conf)\n", 0, 0, 0 );
187                 return 1;
188         }
189
190         if ( si->concat_func == NULL ) {
191                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
192                         "concat func not specified (use \"concat_pattern\" "
193                         "directive in slapd.conf)\n", 0, 0, 0 );
194
195                 if ( backsql_split_pattern( backsql_def_concat_func, 
196                                 &si->concat_func, 2 ) ) {
197                         Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
198                                 "unable to parse pattern '%s'",
199                                 backsql_def_concat_func, 0, 0 );
200                         return 1;
201                 }
202         }
203
204         /*
205          * Prepare cast string as required
206          */
207         if ( si->upper_func.bv_val ) {
208                 char buf[1024];
209
210                 if ( BACKSQL_UPPER_NEEDS_CAST( si ) ) {
211                         snprintf( buf, sizeof( buf ), 
212                                 "%s(cast (" /* ? as varchar(%d))) */ , 
213                                 si->upper_func.bv_val );
214                         ber_str2bv( buf, 0, 1, &si->upper_func_open );
215
216                         snprintf( buf, sizeof( buf ),
217                                 /* (cast(? */ " as varchar(%d)))",
218                                 BACKSQL_MAX_DN_LEN );
219                         ber_str2bv( buf, 0, 1, &si->upper_func_close );
220
221                 } else {
222                         snprintf( buf, sizeof( buf ), "%s(" /* ?) */ ,
223                                         si->upper_func.bv_val );
224                         ber_str2bv( buf, 0, 1, &si->upper_func_open );
225
226                         ber_str2bv( /* (? */ ")", 0, 1, &si->upper_func_close );
227                 }
228         }
229
230         /* normalize filter values only if necessary */
231         si->bi_caseIgnoreMatch = mr_find( "caseIgnoreMatch" );
232
233         if ( si->dbuser == NULL ) {
234                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
235                         "user name not specified "
236                         "(use \"dbuser\" directive in slapd.conf)\n", 0, 0, 0 );
237                 return 1;
238         }
239         
240         if ( si->subtree_cond.bv_val == NULL ) {
241                 /*
242                  * Prepare concat function for subtree search condition
243                  */
244                 struct berval   concat;
245                 struct berval   values[] = {
246                         { sizeof( "'%'" ) - 1,  "'%'" },
247                         { sizeof( "?" ) - 1,    "?" },
248                         { 0,                    NULL }
249                 };
250                 struct berbuf   bb = BB_NULL;
251
252                 if ( backsql_prepare_pattern( si->concat_func, values, 
253                                 &concat ) ) {
254                         Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
255                                 "unable to prepare CONCAT pattern", 0, 0, 0 );
256                         return 1;
257                 }
258                         
259                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
260                         "subtree search SQL condition not specified "
261                         "(use \"subtree_cond\" directive in slapd.conf)\n", 
262                         0, 0, 0);
263
264                 if ( si->upper_func.bv_val ) {
265
266                         /*
267                          * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%',?))
268                          */
269
270                         backsql_strfcat( &bb, "blbbb",
271                                         &si->upper_func,
272                                         (ber_len_t)sizeof( "(ldap_entries.dn) LIKE " ) - 1,
273                                                 "(ldap_entries.dn) LIKE ",
274                                         &si->upper_func_open,
275                                         &concat,
276                                         &si->upper_func_close );
277
278                 } else {
279
280                         /*
281                          * ldap_entries.dn LIKE CONCAT('%',?)
282                          */
283
284                         backsql_strfcat( &bb, "lb",
285                                         (ber_len_t)sizeof( "ldap_entries.dn LIKE " ) - 1,
286                                                 "ldap_entries.dn LIKE ",
287                                         &concat );
288                 }
289
290                 si->subtree_cond = bb.bb_val;
291                         
292                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
293                         "setting '%s' as default\n",
294                         si->subtree_cond.bv_val, 0, 0 );
295         }
296
297         if ( si->children_cond.bv_val == NULL ) {
298                 struct berbuf   bb = BB_NULL;
299
300                 if ( si->upper_func.bv_val ) {
301
302                         /*
303                          * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?))
304                          */
305
306                         backsql_strfcat( &bb, "blbl",
307                                         &si->upper_func,
308                                         (ber_len_t)sizeof( "(ldap_entries.dn)=" ) - 1,
309                                                 "(ldap_entries.dn)=",
310                                         &si->upper_func,
311                                         (ber_len_t)sizeof( "(?)" ) - 1, "(?)" );
312
313                 } else {
314
315                         /*
316                          * ldap_entries.dn LIKE CONCAT('%,',?)
317                          */
318
319                         backsql_strfcat( &bb, "l",
320                                         (ber_len_t)sizeof( "ldap_entries.dn=?" ) - 1,
321                                                 "ldap_entries.dn=?");
322                 }
323
324                 si->children_cond = bb.bb_val;
325                         
326                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
327                         "setting '%s' as default\n",
328                         si->children_cond.bv_val, 0, 0 );
329         }
330
331         if ( si->oc_query == NULL ) {
332                 if ( BACKSQL_CREATE_NEEDS_SELECT( si ) ) {
333                         si->oc_query =
334                                 ch_strdup( backsql_def_needs_select_oc_query );
335
336                 } else {
337                         si->oc_query = ch_strdup( backsql_def_oc_query );
338                 }
339
340                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
341                         "objectclass mapping SQL statement not specified "
342                         "(use \"oc_query\" directive in slapd.conf)\n", 
343                         0, 0, 0 );
344                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
345                         "setting '%s' by default\n", si->oc_query, 0, 0 );
346         }
347         
348         if ( si->at_query == NULL ) {
349                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
350                         "attribute mapping SQL statement not specified "
351                         "(use \"at_query\" directive in slapd.conf)\n",
352                         0, 0, 0 );
353                 Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
354                         "setting '%s' by default\n",
355                         backsql_def_at_query, 0, 0 );
356                 si->at_query = ch_strdup( backsql_def_at_query );
357         }
358         
359         if ( si->insentry_query == NULL ) {
360                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
361                         "entry insertion SQL statement not specified "
362                         "(use \"insentry_query\" directive in slapd.conf)\n",
363                         0, 0, 0 );
364                 Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
365                         "setting '%s' by default\n",
366                         backsql_def_insentry_query, 0, 0 );
367                 si->insentry_query = ch_strdup( backsql_def_insentry_query );
368         }
369         
370         if ( si->delentry_query == NULL ) {
371                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
372                         "entry deletion SQL statement not specified "
373                         "(use \"delentry_query\" directive in slapd.conf)\n",
374                         0, 0, 0 );
375                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
376                         "setting '%s' by default\n",
377                         backsql_def_delentry_query, 0, 0 );
378                 si->delentry_query = ch_strdup( backsql_def_delentry_query );
379         }
380
381         otmp.o_connid = -1;
382         otmp.o_bd = bd;
383         if ( backsql_get_db_conn( &otmp, &dbh ) != LDAP_SUCCESS ) {
384                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
385                         "connection failed, exiting\n", 0, 0, 0 );
386                 return 1;
387         }
388
389         /*
390          * Prepare ID selection query
391          */
392         si->id_query = NULL;
393         idq_len = 0;
394
395         if ( si->upper_func.bv_val == NULL ) {
396                 backsql_strcat( &bb, backsql_id_query, "dn=?", NULL );
397         } else {
398                 if ( BACKSQL_HAS_LDAPINFO_DN_RU( si ) ) {
399                         backsql_strcat( &bb, backsql_id_query,
400                                         "dn_ru=?", NULL );
401                 } else {
402                         if ( BACKSQL_USE_REVERSE_DN( si ) ) {
403                                 backsql_strfcat( &bb, "sbl",
404                                                 backsql_id_query,
405                                                 &si->upper_func, 
406                                                 (ber_len_t)sizeof( "(dn)=?" ) - 1, "(dn)=?" );
407                         } else {
408                                 backsql_strfcat( &bb, "sblbcb",
409                                                 backsql_id_query,
410                                                 &si->upper_func, 
411                                                 (ber_len_t)sizeof( "(dn)=" ) - 1, "(dn)=",
412                                                 &si->upper_func_open, 
413                                                 '?', 
414                                                 &si->upper_func_close );
415                         }
416                 }
417         }
418         si->id_query = bb.bb_val.bv_val;
419
420         /*
421          * Prepare children ID selection query
422          */
423         si->has_children_query = NULL;
424
425         bb.bb_val.bv_val = NULL;
426         bb.bb_val.bv_len = 0;
427         bb.bb_len = 0;
428         backsql_strfcat( &bb, "sb",
429                         "SELECT COUNT(distinct subordinates.id) FROM ldap_entries,ldap_entries subordinates WHERE subordinates.parent=ldap_entries.id AND ",
430
431                         &si->children_cond );
432         si->has_children_query = bb.bb_val.bv_val;
433  
434         backsql_free_db_conn( &otmp );
435         if ( !BACKSQL_SCHEMA_LOADED( si ) ) {
436                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
437                         "test failed, schema map not loaded - exiting\n",
438                         0, 0, 0 );
439                 return 1;
440         }
441         
442         Debug( LDAP_DEBUG_TRACE, "<==backsql_db_open(): "
443                 "test succeeded, schema map loaded\n", 0, 0, 0 );
444         return 0;
445 }
446
447 int
448 backsql_db_close(
449         BackendDB       *bd )
450 {
451         Debug( LDAP_DEBUG_TRACE, "==>backsql_db_close()\n", 0, 0, 0 );
452         Debug( LDAP_DEBUG_TRACE, "<==backsql_db_close()\n", 0, 0, 0 );
453         return 0;
454 }
455
456 int
457 backsql_connection_destroy( Backend *bd, Connection *c )
458 {
459         Operation o;
460         o.o_bd = bd;
461         o.o_connid = c->c_connid;
462
463         Debug( LDAP_DEBUG_TRACE, "==>backsql_connection_destroy()\n", 0, 0, 0 );
464         backsql_free_db_conn( &o );
465         Debug( LDAP_DEBUG_TRACE, "<==backsql_connection_destroy()\n", 0, 0, 0 );
466         return 0;
467 }
468
469 #endif /* SLAPD_SQL */
470