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