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