]> git.sur5r.net Git - openldap/blob - servers/slapd/back-sql/schema-map.c
2598849c481ec4c01562101b016b7532a4f1411a
[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 "back-sql.h"
19 #include "sql-wrap.h"
20 #include "schema-map.h"
21 #include "util.h"
22
23 int backsql_dummy( void *, void * );
24
25 int
26 backsql_cmp_oc_name( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
27 {
28         return strcasecmp( m1->name, m2->name );
29 }
30
31 int
32 backsql_cmp_oc_id( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
33 {
34         if ( m1->id < m2->id ) {
35                 return -1;
36         }
37         if ( m1->id > m2->id ) {
38                 return 1;
39         }
40         return 0;
41 }
42
43 int
44 backsql_cmp_attr( 
45         backsql_at_map_rec      *m1, 
46         backsql_at_map_rec      *m2 )
47 {
48         return strcasecmp( m1->name, m2->name );
49 }
50
51 char *
52 backsql_make_attr_query( 
53         backsql_oc_map_rec      *oc_map,
54         backsql_at_map_rec      *at_map )
55 {
56         struct berval   tmps = { 0, NULL };
57         int             tmpslen = 0;
58
59         backsql_strcat( &tmps, &tmpslen, "SELECT ", at_map->sel_expr, 
60                         " AS ", at_map->name, " FROM ", at_map->from_tbls,
61                         " WHERE ", oc_map->keytbl,".", oc_map->keycol,
62                         "=?", NULL );
63         if ( at_map->join_where != NULL ) {
64                 backsql_strcat( &tmps, &tmpslen, " AND ", 
65                                 at_map->join_where, NULL );
66         }
67
68         at_map->query = tmps.bv_val;
69         
70         return at_map->query;
71 }
72
73 int
74 backsql_add_sysmaps( backsql_oc_map_rec *oc_map )
75 {
76         backsql_at_map_rec      *at_map;
77         int                     len;
78         char                    s[ 30 ]; 
79         struct berval           bv;
80
81         snprintf( s, sizeof( s ), "%ld", oc_map->id );
82
83         at_map = (backsql_at_map_rec *)ch_calloc(1, 
84                         sizeof( backsql_at_map_rec ) );
85         at_map->name = ch_strdup( "objectClass" );
86         at_map->sel_expr = ch_strdup( "ldap_entry_objclasses.oc_name" );
87         at_map->from_tbls = ch_strdup( "ldap_entry_objclasses,ldap_entries" );
88         len = strlen( at_map->from_tbls );
89         backsql_merge_from_clause( &at_map->from_tbls, &len, oc_map->keytbl );
90         len = 0;
91         bv.bv_val = NULL;
92         bv.bv_len = 0;
93         backsql_strcat( &bv, &len,
94                         "ldap_entries.id=ldap_entry_objclasses.entry_id "
95                         "and ldap_entries.keyval=",
96                         oc_map->keytbl, ".", oc_map->keycol,
97                         " and ldap_entries.oc_map_id=", s, NULL );
98         at_map->join_where = bv.bv_val;
99         at_map->add_proc = NULL;
100         at_map->delete_proc = NULL;
101         at_map->param_order = 0;
102         at_map->expect_return = 0;
103         backsql_make_attr_query( oc_map, at_map );
104         avl_insert( &oc_map->attrs, at_map, 
105                         (AVL_CMP)backsql_cmp_attr, backsql_dummy );
106
107         at_map = (backsql_at_map_rec *)ch_calloc( 1, 
108                         sizeof( backsql_at_map_rec ) );
109         at_map->name = ch_strdup( "ref" );
110         at_map->sel_expr = ch_strdup( "ldap_referrals.url" );
111         at_map->from_tbls = ch_strdup( "ldap_referrals,ldap_entries" );
112         len = strlen( at_map->from_tbls );
113         backsql_merge_from_clause( &at_map->from_tbls, &len,oc_map->keytbl );
114
115         /* FIXME: no free? */
116         at_map->join_where = NULL;
117
118         len = 0;
119         bv.bv_val = NULL;
120         bv.bv_len = 0;
121         backsql_strcat( &bv, &len,
122                         "ldap_entries.id=ldap_referrals.entry_id "
123                         "and ldap_entries.keyval=",
124                         oc_map->keytbl, ".", oc_map->keycol,
125                         " and ldap_entries.oc_map_id=", s, NULL );
126         at_map->join_where = bv.bv_val;
127         at_map->add_proc = NULL;
128         at_map->delete_proc = NULL;
129         at_map->param_order = 0;
130         at_map->expect_return = 0;
131         backsql_make_attr_query( oc_map, at_map );
132         avl_insert( &oc_map->attrs, at_map, 
133                         (AVL_CMP)backsql_cmp_attr, backsql_dummy );
134
135         return 1;
136 }
137
138 int
139 backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
140 {
141         SQLHSTMT                oc_sth, at_sth;
142         RETCODE                 rc;
143         BACKSQL_ROW_NTS         oc_row, at_row;
144         unsigned long           oc_id;
145         backsql_oc_map_rec      *oc_map;
146         backsql_at_map_rec      *at_map;
147         char                    *tmps;
148         int                     tmpslen;
149
150         Debug( LDAP_DEBUG_TRACE, "==>load_schema_map()\n", 0, 0, 0 );
151
152         /* 
153          * TimesTen : See if the ldap_entries.dn_ru field exists in the schema
154          */
155         if ( si->has_ldapinfo_dn_ru == -1 ) {
156                 rc = backsql_Prepare( dbh, &oc_sth, 
157                                 backsql_check_dn_ru_query, 0 );
158                 if ( rc == SQL_SUCCESS ) {
159                         si->has_ldapinfo_dn_ru = 1;  /* Yes, the field exists */
160                         Debug( LDAP_DEBUG_TRACE, "ldapinfo.dn_ru field exists "
161                                 "in the schema\n", 0, 0, 0 );
162                 } else {
163                         si->has_ldapinfo_dn_ru = 0;  /* No such field exists */
164                 }
165
166                 SQLFreeStmt( oc_sth, SQL_DROP );
167         }
168
169
170         rc = backsql_Prepare( dbh, &oc_sth, si->oc_query, 0 );
171         if ( rc != SQL_SUCCESS ) {
172                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
173                         "error preparing oc_query: '%s'\n", 
174                         si->oc_query, 0, 0 );
175                 backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
176                 return -1;
177         }
178         Debug( LDAP_DEBUG_TRACE, "load_schema_map(): at_query '%s'\n", 
179                         si->at_query, 0, 0 );
180
181         rc = backsql_Prepare( dbh, &at_sth, si->at_query, 0 );
182         if ( rc != SQL_SUCCESS ) {
183                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
184                         "error preparing at_query: '%s'\n", 
185                         si->at_query, 0, 0 );
186                 backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
187                 return -1;
188         }
189
190         rc = backsql_BindParamID( at_sth, 1, &oc_id );
191         if ( rc != SQL_SUCCESS ) {
192                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
193                         "error binding param for at_query: \n", 0, 0, 0 );
194                 backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
195                 return -1;
196         }
197
198         rc = SQLExecute( oc_sth );
199         if ( rc != SQL_SUCCESS ) {
200                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
201                         "error executing oc_query: \n", 0, 0, 0 );
202                 backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
203                 return -1;
204         }
205
206         backsql_BindRowAsStrings( oc_sth, &oc_row );
207         rc = SQLFetch( oc_sth );
208         for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( oc_sth ) ) {
209                 oc_map = (backsql_oc_map_rec *)ch_calloc( 1,
210                                 sizeof( backsql_oc_map_rec ) );
211                 oc_map->id = atoi( oc_row.cols[ 0 ] );
212                 oc_map->name = ch_strdup( oc_row.cols[ 1 ] );
213                 oc_map->keytbl = ch_strdup( oc_row.cols[ 2 ] );
214                 oc_map->keycol = ch_strdup( oc_row.cols[ 3 ] );
215                 oc_map->create_proc = ( oc_row.is_null[ 4 ] < 0 ) ? NULL 
216                         : ch_strdup( oc_row.cols[ 4 ] );
217                 oc_map->delete_proc = ( oc_row.is_null[ 5 ] < 0 ) ? NULL 
218                         : ch_strdup( oc_row.cols[ 5 ] );
219                 oc_map->expect_return = atoi( oc_row.cols[ 6 ] );
220
221                 /*
222                  * FIXME: first attempt to check for offending
223                  * instructions in {create|delete}_proc
224                  */
225
226                 oc_map->attrs = NULL;
227                 avl_insert( &si->oc_by_name, oc_map,
228                                 (AVL_CMP)backsql_cmp_oc_name, backsql_dummy );
229                 avl_insert( &si->oc_by_id, oc_map,
230                                 (AVL_CMP)backsql_cmp_oc_id, backsql_dummy );
231                 oc_id = oc_map->id;
232                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
233                         "objectClass '%s': keytbl='%s' keycol='%s'\n",
234                         oc_map->name, oc_map->keytbl, oc_map->keycol );
235                 if ( oc_map->delete_proc ) {
236                         Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n", 
237                                 oc_map->delete_proc, 0, 0 );
238                 }
239                 if ( oc_map->create_proc ) {
240                         Debug( LDAP_DEBUG_TRACE, "create_proc='%s'\n",
241                                 oc_map->create_proc, 0, 0 );
242                 }
243                 Debug( LDAP_DEBUG_TRACE, "expect_return=%d; attributes:\n",
244                         oc_map->expect_return, 0, 0 );
245
246                 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
247                         "autoadding 'objectClass' and 'ref' mappings\n",
248                         0, 0, 0 );
249                 backsql_add_sysmaps( oc_map );
250                 rc = SQLExecute( at_sth );
251                 if ( rc != SQL_SUCCESS ) {
252                         Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
253                                 "error executing at_query: \n", 0, 0, 0 );
254                         backsql_PrintErrors( SQL_NULL_HENV, dbh, at_sth, rc );
255                         return -1;
256                 }
257
258                 backsql_BindRowAsStrings( at_sth, &at_row );
259                 rc = SQLFetch( at_sth );
260                 for ( ; BACKSQL_SUCCESS(rc); rc = SQLFetch( at_sth ) ) {
261                         Debug( LDAP_DEBUG_TRACE, "********'%s'\n",
262                                 at_row.cols[ 0 ], 0, 0 );
263                         Debug( LDAP_DEBUG_TRACE, 
264                                 "name='%s',sel_expr='%s' from='%s'",
265                                 at_row.cols[ 0 ], at_row.cols[ 1 ],
266                                 at_row.cols[ 2 ] );
267                         Debug( LDAP_DEBUG_TRACE, 
268                                 "join_where='%s',add_proc='%s'",
269                                 at_row.cols[ 3 ], at_row.cols[ 4 ], 0 );
270                         Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n",
271                                         at_row.cols[ 5 ], 0, 0 );
272                         /* TimesTen */
273                         Debug( LDAP_DEBUG_TRACE, "sel_expr_u='%s'\n",
274                                         at_row.cols[ 8 ], 0, 0 );
275                         at_map = (backsql_at_map_rec *)ch_calloc( 1,
276                                         sizeof( backsql_at_map_rec ) );
277                         at_map->name = ch_strdup( at_row.cols[ 0 ] );
278                         at_map->sel_expr = ch_strdup( at_row.cols[ 1 ] );
279                         at_map->sel_expr_u = ( at_row.is_null[ 8 ] < 0 ) ? NULL
280                                 : ch_strdup( at_row.cols[ 8 ] );
281                         tmps = NULL;
282                         tmpslen = 0;
283                         backsql_merge_from_clause( &tmps, &tmpslen,
284                                         at_row.cols[ 2 ] );
285                         at_map->from_tbls = tmps;
286                         at_map->join_where = ( at_row.is_null[ 3 ] < 0 ) ? NULL 
287                                 : ch_strdup( at_row.cols[ 3 ] );
288                         at_map->add_proc = ( at_row.is_null[ 4 ] < 0 ) ? NULL
289                                 : ch_strdup( at_row.cols[4] );
290                         at_map->delete_proc = ( at_row.is_null[ 5 ] < 0 ) ? NULL
291                                 : ch_strdup( at_row.cols[ 5 ] );
292                         at_map->param_order = atoi( at_row.cols[ 6 ] );
293                         at_map->expect_return = atoi( at_row.cols[ 7 ] );
294                         backsql_make_attr_query( oc_map, at_map );
295                         Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
296                                 "preconstructed query '%s'\n",
297                                 at_map->query, 0, 0 );
298                         avl_insert( &oc_map->attrs, at_map, 
299                                         (AVL_CMP)backsql_cmp_attr,
300                                         backsql_dummy );
301                 }
302                 backsql_FreeRow( &at_row );
303                 SQLFreeStmt( at_sth, SQL_CLOSE );
304         }
305         backsql_FreeRow( &oc_row );
306         SQLFreeStmt( at_sth, SQL_DROP );
307         SQLFreeStmt( oc_sth, SQL_DROP );
308         si->schema_loaded = 1;
309         Debug( LDAP_DEBUG_TRACE, "<==load_schema_map()\n", 0, 0, 0 );
310         return 1;
311 }
312
313 backsql_oc_map_rec *
314 backsql_oc_with_name( backsql_info *si, char *objclass )
315 {
316         backsql_oc_map_rec      tmp, *res;
317
318 #if 0
319         Debug( LDAP_DEBUG_TRACE, "==>oc_with_name(): "
320                 "searching for objectclass with name='%s'\n",
321                 objclass, 0, 0 );
322 #endif
323         
324         tmp.name = objclass;
325         res = (backsql_oc_map_rec *)avl_find( si->oc_by_name, &tmp,
326                         (AVL_CMP)backsql_cmp_oc_name );
327 #if 0
328         if ( res != NULL ) {
329                 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
330                         "found name='%s', id=%d\n", res->name, res->id, 0 );
331         } else {
332                 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
333                         "not found\n", 0, 0, 0 );
334         }
335 #endif
336  
337         return res;
338 }
339
340 backsql_oc_map_rec *
341 backsql_oc_with_id( backsql_info *si, unsigned long id )
342 {
343         backsql_oc_map_rec      tmp, *res;
344  
345 #if 0
346         Debug( LDAP_DEBUG_TRACE, "==>oc_with_id(): "
347                 "searching for objectclass with id='%d'\n", id, 0, 0 );
348 #endif
349
350         tmp.id = id;
351         res = (backsql_oc_map_rec *)avl_find( si->oc_by_id, &tmp,
352                         (AVL_CMP)backsql_cmp_oc_id );
353
354 #if 0
355         if ( res != NULL ) {
356                 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
357                         "found name='%s', id=%d\n", res->name, res->id, 0 );
358         } else {
359                 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
360                         "not found\n", 0, 0, 0 );
361         }
362 #endif
363         
364         return res;
365 }
366
367 backsql_at_map_rec *
368 backsql_at_with_name( backsql_oc_map_rec* objclass, char *attr )
369 {
370         backsql_at_map_rec      tmp, *res;
371  
372 #if 0
373         Debug( LDAP_DEBUG_TRACE, "==>at_with_name(): "
374                 "searching for attribute '%s' for objectclass '%s'\n",
375                 attr, objclass->name, 0 );
376 #endif
377         tmp.name = attr;
378         res = (backsql_at_map_rec *)avl_find( objclass->attrs, &tmp,
379                         (AVL_CMP)backsql_cmp_attr );
380
381 #if 0
382         if ( res != NULL ) {
383                 Debug( LDAP_DEBUG_TRACE, "<==at_with_name(): "
384                         "found name='%s', sel_expr='%s'\n",
385                         res->name, res->sel_expr, 0 );
386         } else {
387                 Debug( LDAP_DEBUG_TRACE, "<==at_with_name(): "
388                         "not found\n", 0, 0, 0 );
389         }
390 #endif
391
392         return res;
393 }
394
395 int
396 backsql_free_attr( backsql_at_map_rec *at )
397 {
398         Debug( LDAP_DEBUG_TRACE, "==>free_attr(): '%s'\n", at->name, 0, 0 );
399         ch_free( at->name );
400         ch_free( at->sel_expr );
401         if ( at->from_tbls != NULL ) {
402                 ch_free( at->from_tbls );
403         }
404         if ( at->join_where != NULL ) {
405                 ch_free( at->join_where );
406         }
407         if ( at->add_proc != NULL ) {
408                 ch_free( at->add_proc );
409         }
410         if ( at->delete_proc != NULL ) {
411                 ch_free( at->delete_proc );
412         }
413         if ( at->query ) {
414                 ch_free( at->query );
415         }
416         ch_free( at );
417
418         /* TimesTen */
419         if ( at->sel_expr_u ) {
420                 ch_free( at->sel_expr_u );
421         }
422         
423         Debug( LDAP_DEBUG_TRACE, "<==free_attr()\n", 0, 0, 0 );
424
425         return 1;
426 }
427
428 int
429 backsql_free_oc( backsql_oc_map_rec *oc )
430 {
431         Debug( LDAP_DEBUG_TRACE, "==>free_oc(): '%s'\n", oc->name, 0, 0 );
432         avl_free( oc->attrs, (AVL_FREE)backsql_free_attr );
433         ch_free( oc->name );
434         ch_free( oc->keytbl );
435         ch_free( oc->keycol );
436         if ( oc->create_proc != NULL ) {
437                 ch_free( oc->create_proc );
438         }
439         if ( oc->delete_proc != NULL ) {
440                 ch_free( oc->delete_proc );
441         }
442         ch_free( oc );
443
444         Debug( LDAP_DEBUG_TRACE, "<==free_oc()\n", 0, 0, 0 );
445         return 1;
446 }
447
448 int
449 backsql_destroy_schema_map( backsql_info *si )
450 {
451         Debug( LDAP_DEBUG_TRACE, "==>destroy_schema_map()\n", 0, 0, 0 );
452         avl_free( si->oc_by_id, (AVL_FREE)backsql_free_oc );
453         avl_free( si->oc_by_name, (AVL_FREE)backsql_dummy );
454         Debug( LDAP_DEBUG_TRACE, "<==destroy_schema_map()\n", 0, 0, 0 );
455         return 0;
456 }
457
458 #endif /* SLAPD_SQL */
459