]> git.sur5r.net Git - openldap/blob - servers/slapd/back-sql/schema-map.c
cf765adc93466d78f48f750c87b262e4d2500e00
[openldap] / servers / slapd / back-sql / schema-map.c
1 /*
2  *       Copyright 1999, Dmitry Kovalev <mit@openldap.org>, All rights reserved.
3  *
4  *       Redistribution and use in source and binary forms are permitted only
5  *       as authorized by the OpenLDAP Public License.  A copy of this
6  *       license is available at http://www.OpenLDAP.org/license.html or
7  *       in file LICENSE in the top-level directory of the distribution.
8  */
9
10 #include "portable.h"
11
12 #ifdef SLAPD_SQL
13
14 #include <stdio.h>
15 #include <sys/types.h>
16 #include <string.h>
17 #include "slap.h"
18 #include "ldap_pvt.h"
19 #include "back-sql.h"
20 #include "sql-wrap.h"
21 #include "schema-map.h"
22 #include "util.h"
23
24 /*
25  * Deprecated
26  */
27 #if 0
28 static int
29 backsql_cmp_oc_name( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
30 {
31         return BACKSQL_NCMP( &m1->name, &m2->name );
32 }
33 #endif
34
35 /*
36  * Uses the pointer to the ObjectClass structure
37  */
38 static int
39 backsql_cmp_oc( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
40 {
41         return ( m1->oc < m2->oc ? -1 : ( m1->oc > m2->oc ? 1 : 0 ) );
42 }
43
44 static int
45 backsql_cmp_oc_id( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
46 {
47         return ( m1->id < m2->id ? -1 : ( m1->id > m2->id ? 1 : 0 ) );
48 }
49
50 /*
51  * Deprecated
52  */
53 #if 0
54 static int
55 backsql_cmp_attr_name( backsql_at_map_rec *m1, backsql_at_map_rec *m2 )
56 {
57         return BACKSQL_NCMP( &m1->name, &m2->name );
58 }
59 #endif
60
61 /*
62  * Uses the pointer to the AttributeDescription structure
63  */
64 static int
65 backsql_cmp_attr( backsql_at_map_rec *m1, backsql_at_map_rec *m2 )
66 {
67         return ( m1->ad < m2->ad ? -1 : ( m1->ad > m2->ad ? 1 : 0 ) );
68 }
69
70 static int
71 backsql_make_attr_query( 
72         backsql_oc_map_rec      *oc_map,
73         backsql_at_map_rec      *at_map )
74 {
75         struct berval   tmps = { 0, NULL };
76         int             tmpslen = 0;
77
78         backsql_strcat( &tmps, &tmpslen, "SELECT ", at_map->sel_expr, 
79                         " AS ", at_map->name.bv_val, 
80                         " FROM ", at_map->from_tbls,
81                         " WHERE ", oc_map->keytbl,".", oc_map->keycol,
82                         "=?", NULL );
83         if ( at_map->join_where != NULL ) {
84                 backsql_strcat( &tmps, &tmpslen, " AND ", 
85                                 at_map->join_where, NULL );
86         }
87
88         at_map->query = tmps.bv_val;
89         
90         return 0;
91 }
92
93 static int
94 backsql_add_sysmaps( backsql_oc_map_rec *oc_map )
95 {
96         backsql_at_map_rec      *at_map;
97         int                     len;
98         char                    s[ 30 ]; 
99         struct berval           bv;
100
101         snprintf( s, sizeof( s ), "%ld", oc_map->id );
102
103         at_map = (backsql_at_map_rec *)ch_calloc(1, 
104                         sizeof( backsql_at_map_rec ) );
105         at_map->ad = slap_schema.si_ad_objectClass;
106         ber_dupbv( &at_map->name, &at_map->ad->ad_cname );
107         at_map->sel_expr = ch_strdup( "ldap_entry_objclasses.oc_name" );
108         at_map->from_tbls = ch_strdup( "ldap_entry_objclasses,ldap_entries" );
109         len = strlen( at_map->from_tbls );
110         backsql_merge_from_clause( &at_map->from_tbls, &len, oc_map->keytbl );
111
112         len = 0;
113         bv.bv_val = NULL;
114         bv.bv_len = 0;
115         backsql_strcat( &bv, &len,
116                         "ldap_entries.id=ldap_entry_objclasses.entry_id "
117                         "and ldap_entries.keyval=",
118                         oc_map->keytbl, ".", oc_map->keycol,
119                         " and ldap_entries.oc_map_id=", s, NULL );
120         at_map->join_where = bv.bv_val;
121
122         at_map->add_proc = NULL;
123         at_map->delete_proc = NULL;
124         at_map->param_order = 0;
125         at_map->expect_return = 0;
126         backsql_make_attr_query( oc_map, at_map );
127         avl_insert( &oc_map->attrs, at_map, 
128                         (AVL_CMP)backsql_cmp_attr, NULL );
129
130         at_map = (backsql_at_map_rec *)ch_calloc( 1, 
131                         sizeof( backsql_at_map_rec ) );
132         at_map->ad = slap_schema.si_ad_ref;
133         ber_dupbv( &at_map->name, &at_map->ad->ad_cname );
134         at_map->sel_expr = ch_strdup( "ldap_referrals.url" );
135         at_map->from_tbls = ch_strdup( "ldap_referrals,ldap_entries" );
136         len = strlen( at_map->from_tbls );
137         backsql_merge_from_clause( &at_map->from_tbls, &len,oc_map->keytbl );
138
139         len = 0;
140         bv.bv_val = NULL;
141         bv.bv_len = 0;
142         backsql_strcat( &bv, &len,
143                         "ldap_entries.id=ldap_referrals.entry_id "
144                         "and ldap_entries.keyval=",
145                         oc_map->keytbl, ".", oc_map->keycol,
146                         " and ldap_entries.oc_map_id=", s, NULL );
147         at_map->join_where = bv.bv_val;
148
149         at_map->add_proc = NULL;
150         at_map->delete_proc = NULL;
151         at_map->param_order = 0;
152         at_map->expect_return = 0;
153         backsql_make_attr_query( oc_map, at_map );
154         avl_insert( &oc_map->attrs, at_map, 
155                         (AVL_CMP)backsql_cmp_attr, NULL );
156
157         return 1;
158 }
159
160 int
161 backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
162 {
163         SQLHSTMT                oc_sth, at_sth;
164         RETCODE                 rc;
165         BACKSQL_ROW_NTS         oc_row, at_row;
166         unsigned long           oc_id;
167         backsql_oc_map_rec      *oc_map;
168         backsql_at_map_rec      *at_map;
169         char                    *tmps;
170         int                     tmpslen;
171
172         Debug( LDAP_DEBUG_TRACE, "==>load_schema_map()\n", 0, 0, 0 );
173
174         /* 
175          * TimesTen : See if the ldap_entries.dn_ru field exists in the schema
176          */
177         if ( si->has_ldapinfo_dn_ru == -1 ) {
178                 rc = backsql_Prepare( dbh, &oc_sth, 
179                                 backsql_check_dn_ru_query, 0 );
180                 if ( rc == SQL_SUCCESS ) {
181                         si->has_ldapinfo_dn_ru = 1;  /* Yes, the field exists */
182                         Debug( LDAP_DEBUG_TRACE, "ldapinfo.dn_ru field exists "
183                                 "in the schema\n", 0, 0, 0 );
184                 } else {
185                         si->has_ldapinfo_dn_ru = 0;  /* No such field exists */
186                 }
187
188                 SQLFreeStmt( oc_sth, SQL_DROP );
189         }
190
191
192         rc = backsql_Prepare( dbh, &oc_sth, si->oc_query, 0 );
193         if ( rc != SQL_SUCCESS ) {
194                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
195                         "error preparing oc_query: '%s'\n", 
196                         si->oc_query, 0, 0 );
197                 backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
198                 return LDAP_OTHER;
199         }
200         Debug( LDAP_DEBUG_TRACE, "load_schema_map(): at_query '%s'\n", 
201                         si->at_query, 0, 0 );
202
203         rc = backsql_Prepare( dbh, &at_sth, si->at_query, 0 );
204         if ( rc != SQL_SUCCESS ) {
205                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
206                         "error preparing at_query: '%s'\n", 
207                         si->at_query, 0, 0 );
208                 backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
209                 return LDAP_OTHER;
210         }
211
212         rc = backsql_BindParamID( at_sth, 1, &oc_id );
213         if ( rc != SQL_SUCCESS ) {
214                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
215                         "error binding param for at_query: \n", 0, 0, 0 );
216                 backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
217                 return LDAP_OTHER;
218         }
219
220         rc = SQLExecute( oc_sth );
221         if ( rc != SQL_SUCCESS ) {
222                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
223                         "error executing oc_query: \n", 0, 0, 0 );
224                 backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
225                 return LDAP_OTHER;
226         }
227
228         backsql_BindRowAsStrings( oc_sth, &oc_row );
229         rc = SQLFetch( oc_sth );
230         for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( oc_sth ) ) {
231                 oc_map = (backsql_oc_map_rec *)ch_calloc( 1,
232                                 sizeof( backsql_oc_map_rec ) );
233
234                 oc_map->id = atoi( oc_row.cols[ 0 ] );
235
236                 ber_str2bv( oc_row.cols[ 1 ], 0, 1, &oc_map->name );
237                 oc_map->oc = oc_bvfind( &oc_map->name );
238                 if ( oc_map->oc == NULL ) {
239                         Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
240                                 "objectClass '%s' is not defined in schema\n", 
241                                 oc_map->name.bv_val, 0, 0 );
242                         return LDAP_OTHER;      /* undefined objectClass ? */
243                 }
244                 
245                 oc_map->keytbl = ch_strdup( oc_row.cols[ 2 ] );
246                 oc_map->keycol = ch_strdup( oc_row.cols[ 3 ] );
247                 oc_map->create_proc = ( oc_row.is_null[ 4 ] < 0 ) ? NULL 
248                         : ch_strdup( oc_row.cols[ 4 ] );
249                 oc_map->delete_proc = ( oc_row.is_null[ 5 ] < 0 ) ? NULL 
250                         : ch_strdup( oc_row.cols[ 5 ] );
251                 oc_map->expect_return = atoi( oc_row.cols[ 6 ] );
252
253                 /*
254                  * FIXME: first attempt to check for offending
255                  * instructions in {create|delete}_proc
256                  */
257
258                 oc_map->attrs = NULL;
259                 avl_insert( &si->oc_by_oc, oc_map,
260                                 (AVL_CMP)backsql_cmp_oc, NULL );
261                 avl_insert( &si->oc_by_id, oc_map,
262                                 (AVL_CMP)backsql_cmp_oc_id, NULL );
263                 oc_id = oc_map->id;
264                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
265                         "objectClass '%s': keytbl='%s' keycol='%s'\n",
266                         oc_map->name.bv_val, oc_map->keytbl, oc_map->keycol );
267                 if ( oc_map->create_proc ) {
268                         Debug( LDAP_DEBUG_TRACE, "create_proc='%s'\n",
269                                 oc_map->create_proc, 0, 0 );
270                 }
271                 if ( oc_map->delete_proc ) {
272                         Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n", 
273                                 oc_map->delete_proc, 0, 0 );
274                 }
275                 Debug( LDAP_DEBUG_TRACE, "expect_return: "
276                         "add=%s, del=%s; attributes:\n",
277                         BACKSQL_IS_ADD( oc_map->expect_return ), 
278                         BACKSQL_IS_DEL( oc_map->expect_return ), 0 );
279
280                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
281                         "autoadding 'objectClass' and 'ref' mappings\n",
282                         0, 0, 0 );
283                 backsql_add_sysmaps( oc_map );
284                 rc = SQLExecute( at_sth );
285                 if ( rc != SQL_SUCCESS ) {
286                         Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
287                                 "error executing at_query: \n", 0, 0, 0 );
288                         backsql_PrintErrors( SQL_NULL_HENV, dbh, at_sth, rc );
289                         return LDAP_OTHER;
290                 }
291
292                 backsql_BindRowAsStrings( at_sth, &at_row );
293                 rc = SQLFetch( at_sth );
294                 for ( ; BACKSQL_SUCCESS(rc); rc = SQLFetch( at_sth ) ) {
295                         const char      *text = NULL;
296
297                         Debug( LDAP_DEBUG_TRACE, "********'%s'\n",
298                                 at_row.cols[ 0 ], 0, 0 );
299                         Debug( LDAP_DEBUG_TRACE, 
300                                 "name='%s',sel_expr='%s' from='%s'",
301                                 at_row.cols[ 0 ], at_row.cols[ 1 ],
302                                 at_row.cols[ 2 ] );
303                         Debug( LDAP_DEBUG_TRACE, 
304                                 "join_where='%s',add_proc='%s'",
305                                 at_row.cols[ 3 ], at_row.cols[ 4 ], 0 );
306                         Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n",
307                                         at_row.cols[ 5 ], 0, 0 );
308                         /* TimesTen */
309                         Debug( LDAP_DEBUG_TRACE, "sel_expr_u='%s'\n",
310                                         at_row.cols[ 8 ], 0, 0 );
311                         at_map = (backsql_at_map_rec *)ch_calloc( 1,
312                                         sizeof( backsql_at_map_rec ) );
313                         ber_str2bv( at_row.cols[ 0 ], 0, 1, &at_map->name );
314                         rc = slap_bv2ad( &at_map->name, &at_map->ad, &text );
315                         if ( rc != LDAP_SUCCESS ) {
316                                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
317                                         "attribute '%s' for objectClass '%s' "
318                                         "is not defined in schema: %s\n", 
319                                         at_map->name.bv_val, 
320                                         oc_map->name.bv_val, text );
321                                 return LDAP_CONSTRAINT_VIOLATION;
322                         }
323                                 
324                         at_map->sel_expr = ch_strdup( at_row.cols[ 1 ] );
325                         at_map->sel_expr_u = ( at_row.is_null[ 8 ] < 0 ) ? NULL
326                                 : ch_strdup( at_row.cols[ 8 ] );
327                         tmps = NULL;
328                         tmpslen = 0;
329                         backsql_merge_from_clause( &tmps, &tmpslen,
330                                         at_row.cols[ 2 ] );
331                         at_map->from_tbls = tmps;
332                         at_map->join_where = ( at_row.is_null[ 3 ] < 0 ) ? NULL 
333                                 : ch_strdup( at_row.cols[ 3 ] );
334                         at_map->add_proc = ( at_row.is_null[ 4 ] < 0 ) ? NULL
335                                 : ch_strdup( at_row.cols[4] );
336                         at_map->delete_proc = ( at_row.is_null[ 5 ] < 0 ) ? NULL
337                                 : ch_strdup( at_row.cols[ 5 ] );
338                         at_map->param_order = atoi( at_row.cols[ 6 ] );
339                         at_map->expect_return = atoi( at_row.cols[ 7 ] );
340                         backsql_make_attr_query( oc_map, at_map );
341                         Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
342                                 "preconstructed query '%s'\n",
343                                 at_map->query, 0, 0 );
344                         avl_insert( &oc_map->attrs, at_map, 
345                                         (AVL_CMP)backsql_cmp_attr, NULL );
346                 }
347                 backsql_FreeRow( &at_row );
348                 SQLFreeStmt( at_sth, SQL_CLOSE );
349         }
350         backsql_FreeRow( &oc_row );
351         SQLFreeStmt( at_sth, SQL_DROP );
352         SQLFreeStmt( oc_sth, SQL_DROP );
353         si->schema_loaded = 1;
354         Debug( LDAP_DEBUG_TRACE, "<==load_schema_map()\n", 0, 0, 0 );
355         return LDAP_SUCCESS;
356 }
357
358 backsql_oc_map_rec *
359 backsql_oc2oc( backsql_info *si, ObjectClass *oc )
360 {
361         backsql_oc_map_rec      tmp, *res;
362
363 #if 0
364         Debug( LDAP_DEBUG_TRACE, "==>backsql_oc2oc(): "
365                 "searching for objectclass with name='%s'\n",
366                 objclass, 0, 0 );
367 #endif
368
369         tmp.oc = oc;
370         res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp,
371                         (AVL_CMP)backsql_cmp_oc );
372 #if 0
373         if ( res != NULL ) {
374                 Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
375                         "found name='%s', id=%d\n", res->name, res->id, 0 );
376         } else {
377                 Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
378                         "not found\n", 0, 0, 0 );
379         }
380 #endif
381  
382         return res;
383 }
384
385 /*
386  * Deprecated
387  */
388 backsql_oc_map_rec *
389 backsql_name2oc( backsql_info *si, struct berval *oc_name )
390 {
391         backsql_oc_map_rec      tmp, *res;
392
393 #if 0
394         Debug( LDAP_DEBUG_TRACE, "==>oc_with_name(): "
395                 "searching for objectclass with name='%s'\n",
396                 objclass, 0, 0 );
397 #endif
398
399         tmp.oc = oc_bvfind( oc_name );
400         if ( tmp.oc == NULL ) {
401                 return NULL;
402         }
403
404         res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp,
405                         (AVL_CMP)backsql_cmp_oc );
406 #if 0
407         if ( res != NULL ) {
408                 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
409                         "found name='%s', id=%d\n", res->name, res->id, 0 );
410         } else {
411                 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
412                         "not found\n", 0, 0, 0 );
413         }
414 #endif
415  
416         return res;
417 }
418
419 backsql_oc_map_rec *
420 backsql_id2oc( backsql_info *si, unsigned long id )
421 {
422         backsql_oc_map_rec      tmp, *res;
423  
424 #if 0
425         Debug( LDAP_DEBUG_TRACE, "==>oc_with_id(): "
426                 "searching for objectclass with id='%d'\n", id, 0, 0 );
427 #endif
428
429         tmp.id = id;
430         res = (backsql_oc_map_rec *)avl_find( si->oc_by_id, &tmp,
431                         (AVL_CMP)backsql_cmp_oc_id );
432
433 #if 0
434         if ( res != NULL ) {
435                 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
436                         "found name='%s', id=%d\n", res->name, res->id, 0 );
437         } else {
438                 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
439                         "not found\n", 0, 0, 0 );
440         }
441 #endif
442         
443         return res;
444 }
445
446 backsql_at_map_rec *
447 backsql_ad2at( backsql_oc_map_rec* objclass, AttributeDescription *ad )
448 {
449         backsql_at_map_rec      tmp, *res;
450  
451 #if 0
452         Debug( LDAP_DEBUG_TRACE, "==>backsql_ad2at(): "
453                 "searching for attribute '%s' for objectclass '%s'\n",
454                 attr, objclass->name, 0 );
455 #endif
456         tmp.ad = ad;
457         res = (backsql_at_map_rec *)avl_find( objclass->attrs, &tmp,
458                         (AVL_CMP)backsql_cmp_attr );
459
460 #if 0
461         if ( res != NULL ) {
462                 Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
463                         "found name='%s', sel_expr='%s'\n",
464                         res->name, res->sel_expr, 0 );
465         } else {
466                 Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
467                         "not found\n", 0, 0, 0 );
468         }
469 #endif
470
471         return res;
472 }
473
474 /*
475  * Deprecated
476  */
477 backsql_at_map_rec *
478 backsql_name2at( backsql_oc_map_rec* objclass, struct berval *attr )
479 {
480         backsql_at_map_rec      tmp, *res;
481         const char              *text = NULL;
482  
483 #if 0
484         Debug( LDAP_DEBUG_TRACE, "==>backsql_name2at(): "
485                 "searching for attribute '%s' for objectclass '%s'\n",
486                 attr, objclass->name, 0 );
487 #endif
488
489         if ( slap_bv2ad( attr, &tmp.ad, &text ) != LDAP_SUCCESS ) {
490                 return NULL;
491         }
492
493         res = (backsql_at_map_rec *)avl_find( objclass->attrs, &tmp,
494                         (AVL_CMP)backsql_cmp_attr );
495
496 #if 0
497         if ( res != NULL ) {
498                 Debug( LDAP_DEBUG_TRACE, "<==backsql_name2at(): "
499                         "found name='%s', sel_expr='%s'\n",
500                         res->name, res->sel_expr, 0 );
501         } else {
502                 Debug( LDAP_DEBUG_TRACE, "<==backsql_name2at(): "
503                         "not found\n", 0, 0, 0 );
504         }
505 #endif
506
507         return res;
508 }
509
510 static void
511 backsql_free_attr( backsql_at_map_rec *at )
512 {
513         Debug( LDAP_DEBUG_TRACE, "==>free_attr(): '%s'\n", 
514                         at->name.bv_val, 0, 0 );
515         ch_free( at->name.bv_val );
516         ch_free( at->sel_expr );
517         if ( at->from_tbls != NULL ) {
518                 ch_free( at->from_tbls );
519         }
520         if ( at->join_where != NULL ) {
521                 ch_free( at->join_where );
522         }
523         if ( at->add_proc != NULL ) {
524                 ch_free( at->add_proc );
525         }
526         if ( at->delete_proc != NULL ) {
527                 ch_free( at->delete_proc );
528         }
529         if ( at->query ) {
530                 ch_free( at->query );
531         }
532
533         /* TimesTen */
534         if ( at->sel_expr_u ) {
535                 ch_free( at->sel_expr_u );
536         }
537         
538         ch_free( at );
539
540         Debug( LDAP_DEBUG_TRACE, "<==free_attr()\n", 0, 0, 0 );
541 }
542
543 static void
544 backsql_free_oc( backsql_oc_map_rec *oc )
545 {
546         Debug( LDAP_DEBUG_TRACE, "==>free_oc(): '%s'\n", 
547                         oc->name.bv_val, 0, 0 );
548         avl_free( oc->attrs, (AVL_FREE)backsql_free_attr );
549         ch_free( oc->name.bv_val );
550         ch_free( oc->keytbl );
551         ch_free( oc->keycol );
552         if ( oc->create_proc != NULL ) {
553                 ch_free( oc->create_proc );
554         }
555         if ( oc->delete_proc != NULL ) {
556                 ch_free( oc->delete_proc );
557         }
558         ch_free( oc );
559
560         Debug( LDAP_DEBUG_TRACE, "<==free_oc()\n", 0, 0, 0 );
561 }
562
563 int
564 backsql_destroy_schema_map( backsql_info *si )
565 {
566         Debug( LDAP_DEBUG_TRACE, "==>destroy_schema_map()\n", 0, 0, 0 );
567         avl_free( si->oc_by_oc, NULL );
568         avl_free( si->oc_by_id, (AVL_FREE)backsql_free_oc );
569         Debug( LDAP_DEBUG_TRACE, "<==destroy_schema_map()\n", 0, 0, 0 );
570         return 0;
571 }
572
573 #endif /* SLAPD_SQL */
574