]> git.sur5r.net Git - openldap/blob - servers/slapd/back-sql/init.c
69c72e85c70ed20574274acc6ca80e14388de1f0
[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 LDAP_CONTROL_X_TREE_DELETE
43                 LDAP_CONTROL_X_TREE_DELETE,
44 #endif /* LDAP_CONTROL_X_TREE_DELETE */
45 #ifdef LDAP_CONTROL_VALUESRETURNFILTER
46                 LDAP_CONTROL_VALUESRETURNFILTER,
47 #endif /* LDAP_CONTROL_VALUESRETURNFILTER */
48                 NULL
49         };
50
51         bi->bi_controls = controls;
52
53         bi->bi_flags |=
54 #if 0
55                 SLAP_BFLAG_INCREMENT |
56 #endif
57                 SLAP_BFLAG_REFERRALS;
58
59         Debug( LDAP_DEBUG_TRACE,"==>sql_back_initialize()\n", 0, 0, 0 );
60         
61         bi->bi_db_init = backsql_db_init;
62         bi->bi_db_config = backsql_db_config;
63         bi->bi_db_open = backsql_db_open;
64         bi->bi_db_close = backsql_db_close;
65         bi->bi_db_destroy = backsql_db_destroy;
66
67         bi->bi_op_abandon = 0;
68         bi->bi_op_compare = backsql_compare;
69         bi->bi_op_bind = backsql_bind;
70         bi->bi_op_unbind = 0;
71         bi->bi_op_search = backsql_search;
72         bi->bi_op_modify = backsql_modify;
73         bi->bi_op_modrdn = backsql_modrdn;
74         bi->bi_op_add = backsql_add;
75         bi->bi_op_delete = backsql_delete;
76         
77         bi->bi_chk_referrals = 0;
78         bi->bi_operational = backsql_operational;
79         bi->bi_entry_get_rw = backsql_entry_get;
80  
81         bi->bi_connection_init = 0;
82         bi->bi_connection_destroy = backsql_connection_destroy;
83
84         Debug( LDAP_DEBUG_TRACE,"<==sql_back_initialize()\n", 0, 0, 0 );
85         return 0;
86 }
87
88 int
89 backsql_destroy( 
90         BackendInfo     *bi )
91 {
92         Debug( LDAP_DEBUG_TRACE, "==>backsql_destroy()\n", 0, 0, 0 );
93         Debug( LDAP_DEBUG_TRACE, "<==backsql_destroy()\n", 0, 0, 0 );
94         return 0;
95 }
96
97 int
98 backsql_db_init(
99         BackendDB       *bd )
100 {
101         backsql_info    *bi;
102  
103         Debug( LDAP_DEBUG_TRACE, "==>backsql_db_init()\n", 0, 0, 0 );
104         bi = (backsql_info *)ch_calloc( 1, sizeof( backsql_info ) );
105         memset( bi, '\0', sizeof( backsql_info ) );
106         ldap_pvt_thread_mutex_init( &bi->sql_dbconn_mutex );
107         ldap_pvt_thread_mutex_init( &bi->sql_schema_mutex );
108         backsql_init_db_env( bi );
109
110         bd->be_private = bi;
111         Debug( LDAP_DEBUG_TRACE, "<==backsql_db_init()\n", 0, 0, 0 );
112         return 0;
113 }
114
115 int
116 backsql_db_destroy(
117         BackendDB       *bd )
118 {
119         backsql_info    *bi = (backsql_info*)bd->be_private;
120  
121         Debug( LDAP_DEBUG_TRACE, "==>backsql_db_destroy()\n", 0, 0, 0 );
122         ldap_pvt_thread_mutex_lock( &bi->sql_dbconn_mutex );
123         backsql_free_db_env( bi );
124         ldap_pvt_thread_mutex_unlock( &bi->sql_dbconn_mutex );
125         ldap_pvt_thread_mutex_destroy( &bi->sql_dbconn_mutex );
126         ldap_pvt_thread_mutex_lock( &bi->sql_schema_mutex );
127         backsql_destroy_schema_map( bi );
128         ldap_pvt_thread_mutex_unlock( &bi->sql_schema_mutex );
129         ldap_pvt_thread_mutex_destroy( &bi->sql_schema_mutex );
130         free( bi->sql_dbname );
131         free( bi->sql_dbuser );
132         if ( bi->sql_dbpasswd ) {
133                 free( bi->sql_dbpasswd );
134         }
135         if ( bi->sql_dbhost ) {
136                 free( bi->sql_dbhost );
137         }
138         if ( bi->sql_upper_func.bv_val ) {
139                 free( bi->sql_upper_func.bv_val );
140                 free( bi->sql_upper_func_open.bv_val );
141                 free( bi->sql_upper_func_close.bv_val );
142         }
143         
144         free( bi->sql_subtree_cond.bv_val );
145         free( bi->sql_oc_query );
146         free( bi->sql_at_query );
147         free( bi->sql_insentry_stmt );
148         free( bi->sql_delentry_stmt );
149         free( bi->sql_renentry_stmt );
150         free( bi->sql_delobjclasses_stmt );
151
152         if ( bi->sql_anlist ) {
153                 int     i;
154
155                 for ( i = 0; !BER_BVISNULL( &bi->sql_anlist[i].an_name ); i++ )
156                 {
157                         ch_free( bi->sql_anlist[i].an_name.bv_val );
158                 }
159                 ch_free( bi->sql_anlist );
160         }
161
162         if ( bi->sql_baseObject ) {
163                 entry_free( bi->sql_baseObject );
164         }
165         
166         free( bi );
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    *bi = (backsql_info*)bd->be_private;
177         SQLHDBC         dbh = SQL_NULL_HDBC;
178         struct berbuf   bb = BB_NULL;
179
180         char            opbuf[ OPERATION_BUFFER_SIZE ];
181         Operation*      op = (Operation *)opbuf;
182         
183         Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): "
184                 "testing RDBMS connection\n", 0, 0, 0 );
185         if ( bi->sql_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 ( bi->sql_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                                 &bi->sql_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 ( bi->sql_upper_func.bv_val ) {
210                 char buf[1024];
211
212                 if ( BACKSQL_UPPER_NEEDS_CAST( bi ) ) {
213                         snprintf( buf, sizeof( buf ), 
214                                 "%s(cast (" /* ? as varchar(%d))) */ , 
215                                 bi->sql_upper_func.bv_val );
216                         ber_str2bv( buf, 0, 1, &bi->sql_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, &bi->sql_upper_func_close );
222
223                 } else {
224                         snprintf( buf, sizeof( buf ), "%s(" /* ?) */ ,
225                                         bi->sql_upper_func.bv_val );
226                         ber_str2bv( buf, 0, 1, &bi->sql_upper_func_open );
227
228                         ber_str2bv( /* (? */ ")", 0, 1, &bi->sql_upper_func_close );
229                 }
230         }
231
232         /* normalize filter values only if necessary */
233         bi->sql_caseIgnoreMatch = mr_find( "caseIgnoreMatch" );
234         assert( bi->sql_caseIgnoreMatch );
235
236         bi->sql_telephoneNumberMatch = mr_find( "telephoneNumberMatch" );
237         assert( bi->sql_telephoneNumberMatch );
238
239         if ( bi->sql_dbuser == NULL ) {
240                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
241                         "user name not specified "
242                         "(use \"dbuser\" directive in slapd.conf)\n", 0, 0, 0 );
243                 return 1;
244         }
245         
246         if ( bi->sql_subtree_cond.bv_val == NULL ) {
247                 /*
248                  * Prepare concat function for subtree search condition
249                  */
250                 struct berval   concat;
251                 struct berval   values[] = {
252                         BER_BVC( "'%'" ),
253                         BER_BVC( "?" ),
254                         BER_BVNULL
255                 };
256                 struct berbuf   bb = BB_NULL;
257
258                 if ( backsql_prepare_pattern( bi->sql_concat_func, values, 
259                                 &concat ) ) {
260                         Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
261                                 "unable to prepare CONCAT pattern", 0, 0, 0 );
262                         return 1;
263                 }
264                         
265                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
266                         "subtree search SQL condition not specified "
267                         "(use \"subtree_cond\" directive in slapd.conf)\n", 
268                         0, 0, 0);
269
270                 if ( bi->sql_upper_func.bv_val ) {
271
272                         /*
273                          * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%',?))
274                          */
275
276                         backsql_strfcat( &bb, "blbbb",
277                                         &bi->sql_upper_func,
278                                         (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ),
279                                                 "(ldap_entries.dn) LIKE ",
280                                         &bi->sql_upper_func_open,
281                                         &concat,
282                                         &bi->sql_upper_func_close );
283
284                 } else {
285
286                         /*
287                          * ldap_entries.dn LIKE CONCAT('%',?)
288                          */
289
290                         backsql_strfcat( &bb, "lb",
291                                         (ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ),
292                                                 "ldap_entries.dn LIKE ",
293                                         &concat );
294                 }
295
296                 bi->sql_subtree_cond = bb.bb_val;
297                         
298                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
299                         "setting \"%s\" as default\n",
300                         bi->sql_subtree_cond.bv_val, 0, 0 );
301         }
302
303         if ( bi->sql_children_cond.bv_val == NULL ) {
304                 struct berbuf   bb = BB_NULL;
305
306                 if ( bi->sql_upper_func.bv_val ) {
307
308                         /*
309                          * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?))
310                          */
311
312                         backsql_strfcat( &bb, "blbl",
313                                         &bi->sql_upper_func,
314                                         (ber_len_t)STRLENOF( "(ldap_entries.dn)=" ),
315                                                 "(ldap_entries.dn)=",
316                                         &bi->sql_upper_func,
317                                         (ber_len_t)STRLENOF( "(?)" ), "(?)" );
318
319                 } else {
320
321                         /*
322                          * ldap_entries.dn LIKE CONCAT('%,',?)
323                          */
324
325                         backsql_strfcat( &bb, "l",
326                                         (ber_len_t)STRLENOF( "ldap_entries.dn=?" ),
327                                                 "ldap_entries.dn=?");
328                 }
329
330                 bi->sql_children_cond = bb.bb_val;
331                         
332                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
333                         "setting \"%s\" as default\n",
334                         bi->sql_children_cond.bv_val, 0, 0 );
335         }
336
337         if ( bi->sql_oc_query == NULL ) {
338                 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
339                         bi->sql_oc_query =
340                                 ch_strdup( backsql_def_needs_select_oc_query );
341
342                 } else {
343                         bi->sql_oc_query = ch_strdup( backsql_def_oc_query );
344                 }
345
346                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
347                         "objectclass mapping SQL statement not specified "
348                         "(use \"oc_query\" directive in slapd.conf)\n", 
349                         0, 0, 0 );
350                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
351                         "setting \"%s\" by default\n", bi->sql_oc_query, 0, 0 );
352         }
353         
354         if ( bi->sql_at_query == NULL ) {
355                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
356                         "attribute mapping SQL statement not specified "
357                         "(use \"at_query\" directive in slapd.conf)\n",
358                         0, 0, 0 );
359                 Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
360                         "setting \"%s\" by default\n",
361                         backsql_def_at_query, 0, 0 );
362                 bi->sql_at_query = ch_strdup( backsql_def_at_query );
363         }
364         
365         if ( bi->sql_insentry_stmt == NULL ) {
366                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
367                         "entry insertion SQL statement not specified "
368                         "(use \"insentry_stmt\" directive in slapd.conf)\n",
369                         0, 0, 0 );
370                 Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
371                         "setting \"%s\" by default\n",
372                         backsql_def_insentry_stmt, 0, 0 );
373                 bi->sql_insentry_stmt = ch_strdup( backsql_def_insentry_stmt );
374         }
375         
376         if ( bi->sql_delentry_stmt == NULL ) {
377                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
378                         "entry deletion SQL statement not specified "
379                         "(use \"delentry_stmt\" directive in slapd.conf)\n",
380                         0, 0, 0 );
381                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
382                         "setting \"%s\" by default\n",
383                         backsql_def_delentry_stmt, 0, 0 );
384                 bi->sql_delentry_stmt = ch_strdup( backsql_def_delentry_stmt );
385         }
386
387         if ( bi->sql_renentry_stmt == NULL ) {
388                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
389                         "entry deletion SQL statement not specified "
390                         "(use \"renentry_stmt\" directive in slapd.conf)\n",
391                         0, 0, 0 );
392                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
393                         "setting \"%s\" by default\n",
394                         backsql_def_renentry_stmt, 0, 0 );
395                 bi->sql_renentry_stmt = ch_strdup( backsql_def_renentry_stmt );
396         }
397
398         if ( bi->sql_delobjclasses_stmt == NULL ) {
399                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
400                         "objclasses deletion SQL statement not specified "
401                         "(use \"delobjclasses_stmt\" directive in slapd.conf)\n",
402                         0, 0, 0 );
403                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
404                         "setting \"%s\" by default\n",
405                         backsql_def_delobjclasses_stmt, 0, 0 );
406                 bi->sql_delobjclasses_stmt = ch_strdup( backsql_def_delobjclasses_stmt );
407         }
408
409         op->o_hdr = (Opheader *)&op[ 1 ];
410         op->o_connid = (unsigned long)(-1);
411         op->o_bd = bd;
412         if ( backsql_get_db_conn( op, &dbh ) != LDAP_SUCCESS ) {
413                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
414                         "connection failed, exiting\n", 0, 0, 0 );
415                 return 1;
416         }
417
418         /*
419          * Prepare ID selection query
420          */
421         if ( bi->sql_id_query == NULL ) {
422                 /* no custom id_query provided */
423                 if ( bi->sql_upper_func.bv_val == NULL ) {
424                         backsql_strcat( &bb, backsql_id_query, "dn=?", NULL );
425
426                 } else {
427                         if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
428                                 backsql_strcat( &bb, backsql_id_query,
429                                                 "dn_ru=?", NULL );
430                         } else {
431                                 if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
432                                         backsql_strfcat( &bb, "sbl",
433                                                         backsql_id_query,
434                                                         &bi->sql_upper_func, 
435                                                         (ber_len_t)STRLENOF( "(dn)=?" ), "(dn)=?" );
436                                 } else {
437                                         backsql_strfcat( &bb, "sblbcb",
438                                                         backsql_id_query,
439                                                         &bi->sql_upper_func, 
440                                                         (ber_len_t)STRLENOF( "(dn)=" ), "(dn)=",
441                                                         &bi->sql_upper_func_open, 
442                                                         '?', 
443                                                         &bi->sql_upper_func_close );
444                                 }
445                         }
446                 }
447                 bi->sql_id_query = bb.bb_val.bv_val;
448         }
449
450         /*
451          * Prepare children ID selection query
452          */
453         bi->sql_has_children_query = NULL;
454
455         bb.bb_val.bv_val = NULL;
456         bb.bb_val.bv_len = 0;
457         bb.bb_len = 0;
458         backsql_strfcat( &bb, "sb",
459                         "SELECT COUNT(distinct subordinates.id) "
460                         "FROM ldap_entries,ldap_entries " BACKSQL_ALIASING "subordinates "
461                         "WHERE subordinates.parent=ldap_entries.id AND ",
462                         &bi->sql_children_cond );
463         bi->sql_has_children_query = bb.bb_val.bv_val;
464  
465         backsql_free_db_conn( op );
466         if ( !BACKSQL_SCHEMA_LOADED( bi ) ) {
467                 Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
468                         "test failed, schema map not loaded - exiting\n",
469                         0, 0, 0 );
470                 return 1;
471         }
472
473         /* should never happen! */
474         assert( bd->be_nsuffix != NULL );
475         
476         if ( BER_BVISNULL( &bd->be_nsuffix[ 1 ] ) ) {
477                 /* enable if only one suffix is defined */
478                 bi->sql_flags |= BSQLF_USE_SUBTREE_SHORTCUT;
479         }
480         
481         Debug( LDAP_DEBUG_TRACE, "<==backsql_db_open(): "
482                 "test succeeded, schema map loaded\n", 0, 0, 0 );
483         return 0;
484 }
485
486 int
487 backsql_db_close(
488         BackendDB       *bd )
489 {
490         Debug( LDAP_DEBUG_TRACE, "==>backsql_db_close()\n", 0, 0, 0 );
491         Debug( LDAP_DEBUG_TRACE, "<==backsql_db_close()\n", 0, 0, 0 );
492         return 0;
493 }
494
495 int
496 backsql_connection_destroy( Backend *bd, Connection *c )
497 {
498         char            opbuf[ OPERATION_BUFFER_SIZE ];
499         Operation*      op = (Operation *)opbuf;
500
501         op->o_hdr = (Opheader *)&op[ 1 ];
502         op->o_connid = c->c_connid;
503         op->o_bd = bd;
504
505         Debug( LDAP_DEBUG_TRACE, "==>backsql_connection_destroy()\n", 0, 0, 0 );
506         backsql_free_db_conn( op );
507         Debug( LDAP_DEBUG_TRACE, "<==backsql_connection_destroy()\n", 0, 0, 0 );
508
509         return 0;
510 }
511
512 #if SLAPD_SQL == SLAPD_MOD_DYNAMIC
513
514 /* conditionally define the init_module() function */
515 SLAP_BACKEND_INIT_MODULE( sql )
516
517 #endif /* SLAPD_SQL == SLAPD_MOD_DYNAMIC */
518