2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2003 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
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>.
17 * This work was initially developed by Dmitry Kovalev for inclusion
18 * by OpenLDAP Software.
26 #include <sys/types.h>
27 #include "ac/string.h"
33 #include "schema-map.h"
37 * Uses the pointer to the ObjectClass structure
40 backsql_cmp_oc( const void *v_m1, const void *v_m2 )
42 const backsql_oc_map_rec *m1 = v_m1, *m2 = v_m2;
43 return SLAP_PTRCMP( m1->oc, m2->oc );
47 backsql_cmp_oc_id( const void *v_m1, const void *v_m2 )
49 const backsql_oc_map_rec *m1 = v_m1, *m2 = v_m2;
50 return ( m1->id < m2->id ? -1 : ( m1->id > m2->id ? 1 : 0 ) );
54 * Uses the pointer to the AttributeDescription structure
57 backsql_cmp_attr( const void *v_m1, const void *v_m2 )
59 const backsql_at_map_rec *m1 = v_m1, *m2 = v_m2;
60 return SLAP_PTRCMP( m1->ad, m2->ad );
64 backsql_make_attr_query(
65 backsql_oc_map_rec *oc_map,
66 backsql_at_map_rec *at_map )
68 struct berbuf bb = BB_NULL;
70 backsql_strfcat( &bb, "lblblblbcbl",
71 (ber_len_t)sizeof( "SELECT " ) - 1, "SELECT ",
73 (ber_len_t)sizeof( " AS " ) - 1, " AS ",
74 &at_map->ad->ad_cname,
75 (ber_len_t)sizeof( " FROM " ) - 1, " FROM ",
77 (ber_len_t)sizeof( " WHERE " ) - 1, " WHERE ",
81 (ber_len_t)sizeof( "=?" ) - 1, "=?" );
83 if ( at_map->join_where.bv_val != NULL ) {
84 backsql_strfcat( &bb, "lb",
85 (ber_len_t)sizeof( " AND ") - 1, " AND ",
86 &at_map->join_where );
89 at_map->query = bb.bb_val.bv_val;
95 backsql_add_sysmaps( backsql_oc_map_rec *oc_map )
97 backsql_at_map_rec *at_map;
98 char s[] = "+9223372036854775807L";
103 snprintf( s, sizeof( s ), "%ld", oc_map->id );
106 at_map = (backsql_at_map_rec *)ch_calloc(1,
107 sizeof( backsql_at_map_rec ) );
108 at_map->ad = slap_schema.si_ad_objectClass;
109 ber_str2bv( "ldap_entry_objclasses.oc_name", 0, 1, &at_map->sel_expr );
110 ber_str2bv( "ldap_entry_objclasses,ldap_entries", 0, 1,
111 &at_map->from_tbls );
113 bb.bb_len = at_map->from_tbls.bv_len + 1;
114 bb.bb_val = at_map->from_tbls;
115 backsql_merge_from_clause( &bb, &oc_map->keytbl );
116 at_map->from_tbls = bb.bb_val;
118 bb.bb_val.bv_val = NULL;
119 bb.bb_val.bv_len = 0;
121 backsql_strfcat( &bb, "lbcbll",
122 (ber_len_t)sizeof( "ldap_entries.id=ldap_entry_objclasses.entry_id and ldap_entries.keyval=" ) - 1,
123 "ldap_entries.id=ldap_entry_objclasses.entry_id and ldap_entries.keyval=",
127 (ber_len_t)sizeof( " and ldap_entries.oc_map_id=" ) - 1,
128 " and ldap_entries.oc_map_id=",
131 at_map->join_where = bb.bb_val;
132 at_map->add_proc = NULL;
133 at_map->delete_proc = NULL;
134 at_map->param_order = 0;
135 at_map->expect_return = 0;
137 backsql_make_attr_query( oc_map, at_map );
138 avl_insert( &oc_map->attrs, at_map, backsql_cmp_attr, NULL );
140 at_map = (backsql_at_map_rec *)ch_calloc( 1,
141 sizeof( backsql_at_map_rec ) );
142 at_map->ad = slap_schema.si_ad_ref;
143 ber_str2bv( "ldap_referrals.url", 0, 1, &at_map->sel_expr );
144 ber_str2bv( "ldap_referrals,ldap_entries", 0, 1, &at_map->from_tbls );
146 bb.bb_val.bv_val = NULL;
147 bb.bb_val.bv_len = 0;
148 bb.bb_len = at_map->from_tbls.bv_len + 1;
149 backsql_merge_from_clause( &bb, &oc_map->keytbl );
150 at_map->from_tbls = bb.bb_val;
152 bb.bb_val.bv_val = NULL;
153 bb.bb_val.bv_len = 0;
155 backsql_strfcat( &bb, "lbcbll",
156 (ber_len_t)sizeof( "ldap_entries.id=ldap_referrals.entry_id and ldap_entries.keyval=" ) - 1,
157 "ldap_entries.id=ldap_referrals.entry_id and ldap_entries.keyval=",
161 (ber_len_t)sizeof( " and ldap_entries.oc_map_id=" ) - 1,
162 " and ldap_entries.oc_map_id=",
165 at_map->join_where = bb.bb_val;
166 at_map->add_proc = NULL;
167 at_map->delete_proc = NULL;
168 at_map->param_order = 0;
169 at_map->expect_return = 0;
171 backsql_make_attr_query( oc_map, at_map );
172 avl_insert( &oc_map->attrs, at_map, backsql_cmp_attr, NULL );
178 backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
180 SQLHSTMT oc_sth, at_sth;
182 BACKSQL_ROW_NTS oc_row, at_row;
184 backsql_oc_map_rec *oc_map;
185 backsql_at_map_rec *at_map;
187 Debug( LDAP_DEBUG_TRACE, "==>load_schema_map()\n", 0, 0, 0 );
190 * TimesTen : See if the ldap_entries.dn_ru field exists in the schema
192 if ( !BACKSQL_DONTCHECK_LDAPINFO_DN_RU( si ) ) {
193 rc = backsql_Prepare( dbh, &oc_sth,
194 backsql_check_dn_ru_query, 0 );
195 if ( rc == SQL_SUCCESS ) {
196 /* Yes, the field exists */
197 si->bsql_flags |= BSQLF_HAS_LDAPINFO_DN_RU;
198 Debug( LDAP_DEBUG_TRACE, "ldapinfo.dn_ru field exists "
199 "in the schema\n", 0, 0, 0 );
201 /* No such field exists */
202 si->bsql_flags &= ~BSQLF_HAS_LDAPINFO_DN_RU;
205 SQLFreeStmt( oc_sth, SQL_DROP );
209 rc = backsql_Prepare( dbh, &oc_sth, si->oc_query, 0 );
210 if ( rc != SQL_SUCCESS ) {
211 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
212 "error preparing oc_query: '%s'\n",
213 si->oc_query, 0, 0 );
214 backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
217 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): at_query '%s'\n",
218 si->at_query, 0, 0 );
220 rc = backsql_Prepare( dbh, &at_sth, si->at_query, 0 );
221 if ( rc != SQL_SUCCESS ) {
222 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
223 "error preparing at_query: '%s'\n",
224 si->at_query, 0, 0 );
225 backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
229 rc = backsql_BindParamID( at_sth, 1, &oc_id );
230 if ( rc != SQL_SUCCESS ) {
231 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
232 "error binding param for at_query: \n", 0, 0, 0 );
233 backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
237 rc = SQLExecute( oc_sth );
238 if ( rc != SQL_SUCCESS ) {
239 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
240 "error executing oc_query: \n", 0, 0, 0 );
241 backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
245 backsql_BindRowAsStrings( oc_sth, &oc_row );
246 rc = SQLFetch( oc_sth );
247 for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( oc_sth ) ) {
250 oc_map = (backsql_oc_map_rec *)ch_calloc( 1,
251 sizeof( backsql_oc_map_rec ) );
253 oc_map->id = strtol( oc_row.cols[ 0 ], NULL, 0 );
255 oc_map->oc = oc_find( oc_row.cols[ 1 ] );
256 if ( oc_map->oc == NULL ) {
257 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
258 "objectClass '%s' is not defined in schema\n",
259 oc_row.cols[ 1 ], 0, 0 );
260 return LDAP_OTHER; /* undefined objectClass ? */
263 ber_str2bv( oc_row.cols[ 2 ], 0, 1, &oc_map->keytbl );
264 ber_str2bv( oc_row.cols[ 3 ], 0, 1, &oc_map->keycol );
265 oc_map->create_proc = ( oc_row.value_len[ 4 ] < 0 ) ? NULL
266 : ch_strdup( oc_row.cols[ 4 ] );
269 if ( BACKSQL_CREATE_NEEDS_SELECT( si ) ) {
271 oc_map->create_keyval = ( oc_row.value_len[ 5 ] < 0 )
272 ? NULL : ch_strdup( oc_row.cols[ 5 ] );
274 oc_map->delete_proc = ( oc_row.value_len[ colnum ] < 0 ) ? NULL
275 : ch_strdup( oc_row.cols[ colnum ] );
276 oc_map->expect_return = strtol( oc_row.cols[ colnum + 1 ],
280 * FIXME: first attempt to check for offending
281 * instructions in {create|delete}_proc
284 oc_map->attrs = NULL;
285 avl_insert( &si->oc_by_oc, oc_map, backsql_cmp_oc, NULL );
286 avl_insert( &si->oc_by_id, oc_map, backsql_cmp_oc_id, NULL );
288 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
289 "objectClass '%s': keytbl='%s' keycol='%s'\n",
290 BACKSQL_OC_NAME( oc_map ),
291 oc_map->keytbl.bv_val, oc_map->keycol.bv_val );
292 if ( oc_map->create_proc ) {
293 Debug( LDAP_DEBUG_TRACE, "create_proc='%s'\n",
294 oc_map->create_proc, 0, 0 );
296 if ( oc_map->create_keyval ) {
297 Debug( LDAP_DEBUG_TRACE, "create_keyval='%s'\n",
298 oc_map->create_keyval, 0, 0 );
300 if ( oc_map->delete_proc ) {
301 Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n",
302 oc_map->delete_proc, 0, 0 );
304 Debug( LDAP_DEBUG_TRACE, "expect_return: "
305 "add=%d, del=%d; attributes:\n",
306 BACKSQL_IS_ADD( oc_map->expect_return ),
307 BACKSQL_IS_DEL( oc_map->expect_return ), 0 );
309 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
310 "autoadding 'objectClass' and 'ref' mappings\n",
312 backsql_add_sysmaps( oc_map );
313 rc = SQLExecute( at_sth );
314 if ( rc != SQL_SUCCESS ) {
315 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
316 "error executing at_query: \n", 0, 0, 0 );
317 backsql_PrintErrors( SQL_NULL_HENV, dbh, at_sth, rc );
321 backsql_BindRowAsStrings( at_sth, &at_row );
322 rc = SQLFetch( at_sth );
323 for ( ; BACKSQL_SUCCESS(rc); rc = SQLFetch( at_sth ) ) {
324 const char *text = NULL;
326 struct berbuf bb = BB_NULL;
328 Debug( LDAP_DEBUG_TRACE, "********'%s'\n",
329 at_row.cols[ 0 ], 0, 0 );
330 Debug( LDAP_DEBUG_TRACE,
331 "name='%s',sel_expr='%s' from='%s'",
332 at_row.cols[ 0 ], at_row.cols[ 1 ],
334 Debug( LDAP_DEBUG_TRACE,
335 "join_where='%s',add_proc='%s'",
336 at_row.cols[ 3 ], at_row.cols[ 4 ], 0 );
337 Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n",
338 at_row.cols[ 5 ], 0, 0 );
340 Debug( LDAP_DEBUG_TRACE, "sel_expr_u='%s'\n",
341 at_row.cols[ 8 ], 0, 0 );
342 at_map = (backsql_at_map_rec *)ch_calloc( 1,
343 sizeof( backsql_at_map_rec ) );
344 rc = slap_str2ad( at_row.cols[ 0 ],
345 &at_map->ad, &text );
346 if ( rc != LDAP_SUCCESS ) {
347 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
348 "attribute '%s' for objectClass '%s' "
349 "is not defined in schema: %s\n",
351 BACKSQL_OC_NAME( oc_map ), text );
352 return LDAP_CONSTRAINT_VIOLATION;
355 ber_str2bv( at_row.cols[ 1 ], 0, 1, &at_map->sel_expr );
356 if ( at_row.value_len[ 8 ] < 0 ) {
357 at_map->sel_expr_u.bv_val = NULL;
358 at_map->sel_expr_u.bv_len = 0;
360 ber_str2bv( at_row.cols[ 8 ], 0, 1,
361 &at_map->sel_expr_u );
364 ber_str2bv( at_row.cols[ 2 ], 0, 0, &bv );
365 backsql_merge_from_clause( &bb, &bv );
366 at_map->from_tbls = bb.bb_val;
367 if ( at_row.value_len[ 3 ] < 0 ) {
368 at_map->join_where.bv_val = NULL;
369 at_map->join_where.bv_len = 0;
371 ber_str2bv( at_row.cols[ 3 ], 0, 1,
372 &at_map->join_where );
374 at_map->add_proc = NULL;
375 if ( at_row.value_len[ 4 ] > 0 ) {
376 at_map->add_proc = ch_strdup( at_row.cols[4] );
378 at_map->delete_proc = NULL;
379 if ( at_row.value_len[ 5 ] > 0 ) {
381 = ch_strdup( at_row.cols[ 5 ] );
383 at_map->param_order = strtol( at_row.cols[ 6 ],
385 at_map->expect_return = strtol( at_row.cols[ 7 ],
387 backsql_make_attr_query( oc_map, at_map );
388 Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
389 "preconstructed query '%s'\n",
390 at_map->query, 0, 0 );
391 avl_insert( &oc_map->attrs, at_map, backsql_cmp_attr, NULL );
393 backsql_FreeRow( &at_row );
394 SQLFreeStmt( at_sth, SQL_CLOSE );
396 backsql_FreeRow( &oc_row );
397 SQLFreeStmt( at_sth, SQL_DROP );
398 SQLFreeStmt( oc_sth, SQL_DROP );
399 si->bsql_flags |= BSQLF_SCHEMA_LOADED;
400 Debug( LDAP_DEBUG_TRACE, "<==load_schema_map()\n", 0, 0, 0 );
405 backsql_oc2oc( backsql_info *si, ObjectClass *oc )
407 backsql_oc_map_rec tmp, *res;
410 Debug( LDAP_DEBUG_TRACE, "==>backsql_oc2oc(): "
411 "searching for objectclass with name='%s'\n",
413 #endif /* BACKSQL_TRACE */
416 res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp, backsql_cmp_oc );
419 Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
420 "found name='%s', id=%d\n",
421 BACKSQL_OC_NAME( res ), res->id, 0 );
423 Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
424 "not found\n", 0, 0, 0 );
426 #endif /* BACKSQL_TRACE */
432 backsql_name2oc( backsql_info *si, struct berval *oc_name )
434 backsql_oc_map_rec tmp, *res;
437 Debug( LDAP_DEBUG_TRACE, "==>oc_with_name(): "
438 "searching for objectclass with name='%s'\n",
440 #endif /* BACKSQL_TRACE */
442 tmp.oc = oc_bvfind( oc_name );
443 if ( tmp.oc == NULL ) {
447 res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp, backsql_cmp_oc );
450 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
451 "found name='%s', id=%d\n",
452 BACKSQL_OC_NAME( res ), res->id, 0 );
454 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
455 "not found\n", 0, 0, 0 );
457 #endif /* BACKSQL_TRACE */
463 backsql_id2oc( backsql_info *si, unsigned long id )
465 backsql_oc_map_rec tmp, *res;
468 Debug( LDAP_DEBUG_TRACE, "==>oc_with_id(): "
469 "searching for objectclass with id='%d'\n", id, 0, 0 );
470 #endif /* BACKSQL_TRACE */
473 res = (backsql_oc_map_rec *)avl_find( si->oc_by_id, &tmp,
478 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
479 "found name='%s', id=%d\n",
480 BACKSQL_OC_NAME( res ), res->id, 0 );
482 Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
483 "not found\n", 0, 0, 0 );
485 #endif /* BACKSQL_TRACE */
491 backsql_ad2at( backsql_oc_map_rec* objclass, AttributeDescription *ad )
493 backsql_at_map_rec tmp, *res;
496 Debug( LDAP_DEBUG_TRACE, "==>backsql_ad2at(): "
497 "searching for attribute '%s' for objectclass '%s'\n",
498 attr, BACKSQL_OC_NAME( objclass ), 0 );
499 #endif /* BACKSQL_TRACE */
502 res = (backsql_at_map_rec *)avl_find( objclass->attrs, &tmp,
507 Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
508 "found name='%s', sel_expr='%s'\n",
509 res->ad->ad_cname.bv_val, res->sel_expr.bv_val, 0 );
511 Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
512 "not found\n", 0, 0, 0 );
514 #endif /* BACKSQL_TRACE */
523 backsql_name2at( backsql_oc_map_rec* objclass, struct berval *attr )
525 backsql_at_map_rec tmp, *res;
526 const char *text = NULL;
529 Debug( LDAP_DEBUG_TRACE, "==>backsql_name2at(): "
530 "searching for attribute '%s' for objectclass '%s'\n",
531 attr, BACKSQL_OC_NAME( objclass ), 0 );
532 #endif /* BACKSQL_TRACE */
534 if ( slap_bv2ad( attr, &tmp.ad, &text ) != LDAP_SUCCESS ) {
538 res = (backsql_at_map_rec *)avl_find( objclass->attrs, &tmp,
543 Debug( LDAP_DEBUG_TRACE, "<==backsql_name2at(): "
544 "found name='%s', sel_expr='%s'\n",
545 res->name, res->sel_expr.bv_val, 0 );
547 Debug( LDAP_DEBUG_TRACE, "<==backsql_name2at(): "
548 "not found\n", 0, 0, 0 );
550 #endif /* BACKSQL_TRACE */
556 backsql_free_attr( void *v_at )
558 backsql_at_map_rec *at = v_at;
559 Debug( LDAP_DEBUG_TRACE, "==>free_attr(): '%s'\n",
560 at->ad->ad_cname.bv_val, 0, 0 );
561 ch_free( at->sel_expr.bv_val );
562 if ( at->from_tbls.bv_val != NULL ) {
563 ch_free( at->from_tbls.bv_val );
565 if ( at->join_where.bv_val != NULL ) {
566 ch_free( at->join_where.bv_val );
568 if ( at->add_proc != NULL ) {
569 ch_free( at->add_proc );
571 if ( at->delete_proc != NULL ) {
572 ch_free( at->delete_proc );
575 ch_free( at->query );
579 if ( at->sel_expr_u.bv_val ) {
580 ch_free( at->sel_expr_u.bv_val );
585 Debug( LDAP_DEBUG_TRACE, "<==free_attr()\n", 0, 0, 0 );
589 backsql_free_oc( void *v_oc )
591 backsql_oc_map_rec *oc = v_oc;
592 Debug( LDAP_DEBUG_TRACE, "==>free_oc(): '%s'\n",
593 BACKSQL_OC_NAME( oc ), 0, 0 );
594 avl_free( oc->attrs, backsql_free_attr );
595 ch_free( oc->keytbl.bv_val );
596 ch_free( oc->keycol.bv_val );
597 if ( oc->create_proc != NULL ) {
598 ch_free( oc->create_proc );
600 if ( oc->create_keyval != NULL ) {
601 ch_free( oc->create_keyval );
603 if ( oc->delete_proc != NULL ) {
604 ch_free( oc->delete_proc );
608 Debug( LDAP_DEBUG_TRACE, "<==free_oc()\n", 0, 0, 0 );
612 backsql_destroy_schema_map( backsql_info *si )
614 Debug( LDAP_DEBUG_TRACE, "==>destroy_schema_map()\n", 0, 0, 0 );
615 avl_free( si->oc_by_oc, 0 );
616 avl_free( si->oc_by_id, backsql_free_oc );
617 Debug( LDAP_DEBUG_TRACE, "<==destroy_schema_map()\n", 0, 0, 0 );
621 #endif /* SLAPD_SQL */