]> git.sur5r.net Git - openldap/blob - servers/slapd/back-sql/entry-id.c
cleanup naming; minor fixes
[openldap] / servers / slapd / back-sql / entry-id.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2004 The OpenLDAP Foundation.
5  * Portions Copyright 1999 Dmitry Kovalev.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
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>.
15  */
16 /* ACKNOWLEDGEMENTS:
17  * This work was initially developed by Dmitry Kovalev for inclusion
18  * by OpenLDAP Software.
19  */
20
21 #include "portable.h"
22
23 #ifdef SLAPD_SQL
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 backsql_entryID *
33 backsql_free_entryID( backsql_entryID *id, int freeit )
34 {
35         backsql_entryID         *next;
36
37         assert( id );
38
39         next = id->eid_next;
40
41         if ( id->eid_dn.bv_val != NULL ) {
42                 free( id->eid_dn.bv_val );
43         }
44
45 #ifdef BACKSQL_ARBITRARY_KEY
46         if ( id->eid_id.bv_val ) {
47                 free( id->eid_id.bv_val );
48         }
49
50         if ( id->eid_keyval.bv_val ) {
51                 free( id->eid_keyval.bv_val );
52         }
53 #endif /* BACKSQL_ARBITRARY_KEY */
54
55         if ( freeit ) {
56                 free( id );
57         }
58
59         return next;
60 }
61
62 int
63 backsql_dn2id(
64         backsql_info            *bi,
65         backsql_entryID         *id,
66         SQLHDBC                 dbh,
67         struct berval           *dn )
68 {
69         SQLHSTMT                sth; 
70         BACKSQL_ROW_NTS         row;
71         RETCODE                 rc;
72         int                     res;
73
74         /* TimesTen */
75         char                    upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
76         struct berval           toBind;
77         int                     i, j;
78
79         /*
80          * NOTE: id can be NULL; in this case, the function
81          * simply checks whether the DN can be successfully 
82          * turned into an ID, returning LDAP_SUCCESS for
83          * positive cases, or the most appropriate error
84          */
85
86         Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): dn=\"%s\"%s\n", 
87                         dn->bv_val, id == NULL ? " (no ID)" : "", 0 );
88
89         if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
90                 Debug( LDAP_DEBUG_TRACE, 
91                         "backsql_dn2id(): DN \"%s\" (%ld bytes) "
92                         "exceeds max DN length (%d):\n",
93                         dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
94                 return LDAP_OTHER;
95         }
96         
97         /* begin TimesTen */
98         Debug(LDAP_DEBUG_TRACE, "id_query \"%s\"\n", bi->sql_id_query, 0, 0);
99         assert( bi->sql_id_query );
100         rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 );
101         if ( rc != SQL_SUCCESS ) {
102                 Debug( LDAP_DEBUG_TRACE, 
103                         "backsql_dn2id(): error preparing SQL:\n%s", 
104                         bi->sql_id_query, 0, 0);
105                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
106                 SQLFreeStmt( sth, SQL_DROP );
107                 return LDAP_OTHER;
108         }
109
110         if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
111                 /*
112                  * Prepare an upper cased, byte reversed version 
113                  * that can be searched using indexes
114                  */
115
116                 for ( i = 0, j = dn->bv_len - 1; dn->bv_val[ i ]; i++, j--) {
117                         upperdn[ i ] = dn->bv_val[ j ];
118                 }
119                 upperdn[ i ] = '\0';
120                 ldap_pvt_str2upper( upperdn );
121
122                 Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): upperdn=\"%s\"\n",
123                                 upperdn, 0, 0 );
124                 ber_str2bv( upperdn, 0, 0, &toBind );
125
126         } else {
127                 if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
128                         AC_MEMCPY( upperdn, dn->bv_val, dn->bv_len + 1 );
129                         ldap_pvt_str2upper( upperdn );
130                         Debug( LDAP_DEBUG_TRACE,
131                                 "==>backsql_dn2id(): upperdn=\"%s\"\n",
132                                 upperdn, 0, 0 );
133                         ber_str2bv( upperdn, 0, 0, &toBind );
134
135                 } else {
136                         toBind = *dn;
137                 }
138         }
139
140         rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &toBind );
141         if ( rc != SQL_SUCCESS) {
142                 /* end TimesTen */ 
143                 Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
144                         "error binding dn=\"%s\" parameter:\n", 
145                         toBind.bv_val, 0, 0 );
146                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
147                 SQLFreeStmt( sth, SQL_DROP );
148                 return LDAP_OTHER;
149         }
150
151         rc = SQLExecute( sth );
152         if ( rc != SQL_SUCCESS ) {
153                 Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
154                         "error executing query (\"%s\", \"%s\"):\n", 
155                         bi->sql_id_query, toBind.bv_val, 0 );
156                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
157                 SQLFreeStmt( sth, SQL_DROP );
158                 return LDAP_OTHER;
159         }
160
161         backsql_BindRowAsStrings( sth, &row );
162         rc = SQLFetch( sth );
163         if ( BACKSQL_SUCCESS( rc ) ) {
164                 res = LDAP_SUCCESS;
165                 Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(): id=%s keyval=%s oc_id=%s\n",
166                                 row.cols[ 0 ], row.cols[ 1 ], row.cols[ 2 ] );
167
168                 if ( id != NULL ) {
169 #ifdef BACKSQL_ARBITRARY_KEY
170                         ber_str2bv( row.cols[ 0 ], 0, 1, &id->eid_id );
171                         ber_str2bv( row.cols[ 1 ], 0, 1, &id->eid_keyval );
172 #else /* ! BACKSQL_ARBITRARY_KEY */
173                         id->eid_id = strtol( row.cols[ 0 ], NULL, 0 );
174                         id->eid_keyval = strtol( row.cols[ 1 ], NULL, 0 );
175 #endif /* ! BACKSQL_ARBITRARY_KEY */
176                         id->eid_oc_id = strtol( row.cols[ 2 ], NULL, 0 );
177
178                         ber_dupbv( &id->eid_dn, dn );
179                         id->eid_next = NULL;
180                 }
181
182         } else {
183                 res = LDAP_NO_SUCH_OBJECT;
184                 Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(): no match\n",
185                                 0, 0, 0 );
186         }
187         backsql_FreeRow( &row );
188
189         SQLFreeStmt( sth, SQL_DROP );
190         return res;
191 }
192
193 int
194 backsql_count_children(
195         backsql_info            *bi,
196         SQLHDBC                 dbh,
197         struct berval           *dn,
198         unsigned long           *nchildren )
199 {
200         SQLHSTMT                sth; 
201         BACKSQL_ROW_NTS         row;
202         RETCODE                 rc;
203         int                     res = LDAP_SUCCESS;
204
205         Debug( LDAP_DEBUG_TRACE, "==>backsql_count_children(): dn=\"%s\"\n", 
206                         dn->bv_val, 0, 0 );
207
208         if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
209                 Debug( LDAP_DEBUG_TRACE, 
210                         "backsql_count_children(): DN \"%s\" (%ld bytes) "
211                         "exceeds max DN length (%d):\n",
212                         dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
213                 return LDAP_OTHER;
214         }
215         
216         /* begin TimesTen */
217         Debug(LDAP_DEBUG_TRACE, "children id query \"%s\"\n", 
218                         bi->sql_has_children_query, 0, 0);
219         assert( bi->sql_has_children_query );
220         rc = backsql_Prepare( dbh, &sth, bi->sql_has_children_query, 0 );
221         if ( rc != SQL_SUCCESS ) {
222                 Debug( LDAP_DEBUG_TRACE, 
223                         "backsql_count_children(): error preparing SQL:\n%s", 
224                         bi->sql_has_children_query, 0, 0);
225                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
226                 SQLFreeStmt( sth, SQL_DROP );
227                 return LDAP_OTHER;
228         }
229
230         rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, dn );
231         if ( rc != SQL_SUCCESS) {
232                 /* end TimesTen */ 
233                 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
234                         "error binding dn=\"%s\" parameter:\n", 
235                         dn->bv_val, 0, 0 );
236                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
237                 SQLFreeStmt( sth, SQL_DROP );
238                 return LDAP_OTHER;
239         }
240
241         rc = SQLExecute( sth );
242         if ( rc != SQL_SUCCESS ) {
243                 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
244                         "error executing query (\"%s\", \"%s\"):\n", 
245                         bi->sql_has_children_query, dn->bv_val, 0 );
246                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
247                 SQLFreeStmt( sth, SQL_DROP );
248                 return LDAP_OTHER;
249         }
250
251         backsql_BindRowAsStrings( sth, &row );
252         
253         rc = SQLFetch( sth );
254         if ( BACKSQL_SUCCESS( rc ) ) {
255                 char *end;
256
257                 *nchildren = strtol( row.cols[ 0 ], &end, 0 );
258                 if ( end[ 0 ] != '\0' && end[0] != '.' ) {
259                         /* FIXME: braindead RDBMSes return
260                          * a fractional number from COUNT!
261                          */
262                         res = LDAP_OTHER;
263                 }
264
265         } else {
266                 res = LDAP_OTHER;
267         }
268         backsql_FreeRow( &row );
269
270         SQLFreeStmt( sth, SQL_DROP );
271
272         Debug( LDAP_DEBUG_TRACE, "<==backsql_count_children(): %lu\n",
273                         *nchildren, 0, 0 );
274
275         return res;
276 }
277
278 int
279 backsql_has_children(
280         backsql_info            *bi,
281         SQLHDBC                 dbh,
282         struct berval           *dn )
283 {
284         unsigned long   nchildren;
285         int             rc;
286
287         rc = backsql_count_children( bi, dbh, dn, &nchildren );
288
289         if ( rc == LDAP_SUCCESS ) {
290                 return nchildren > 0 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
291         }
292
293         return rc;
294 }
295
296 static int
297 backsql_get_attr_vals( void *v_at, void *v_bsi )
298 {
299         backsql_at_map_rec      *at = v_at;
300         backsql_srch_info       *bsi = v_bsi;
301         backsql_info            *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
302         RETCODE                 rc;
303         SQLHSTMT                sth;
304         BACKSQL_ROW_NTS         row;
305         int                     i;
306
307         assert( at );
308         assert( bsi );
309
310 #ifdef BACKSQL_ARBITRARY_KEY
311         Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
312                 "oc=\"%s\" attr=\"%s\" keyval=%s\n",
313                 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val, 
314                 bsi->bsi_c_eid->eid_keyval.bv_val );
315 #else /* ! BACKSQL_ARBITRARY_KEY */
316         Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
317                 "oc=\"%s\" attr=\"%s\" keyval=%ld\n",
318                 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val, 
319                 bsi->bsi_c_eid->eid_keyval );
320 #endif /* ! BACKSQL_ARBITRARY_KEY */
321
322         rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 );
323         if ( rc != SQL_SUCCESS ) {
324                 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
325                         "error preparing query: %s\n", at->bam_query, 0, 0 );
326                 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
327                 return 1;
328         }
329
330         rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
331                         &bsi->bsi_c_eid->eid_keyval );
332         if ( rc != SQL_SUCCESS ) {
333                 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
334                         "error binding key value parameter\n", 0, 0, 0 );
335                 return 1;
336         }
337
338 #ifdef BACKSQL_TRACE
339 #ifdef BACKSQL_ARBITRARY_KEY
340         Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
341                 "query=\"%s\" keyval=%s\n", at->bam_query,
342                 bsi->bsi_c_eid->eid_keyval.bv_val, 0 );
343 #else /* !BACKSQL_ARBITRARY_KEY */
344         Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
345                 "query=\"%s\" keyval=%d\n", at->bam_query,
346                 bsi->bsi_c_eid->eid_keyval, 0 );
347 #endif /* ! BACKSQL_ARBITRARY_KEY */
348 #endif /* BACKSQL_TRACE */
349
350         rc = SQLExecute( sth );
351         if ( ! BACKSQL_SUCCESS( rc ) ) {
352                 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
353                         "error executing attribute query \"%s\"\n",
354                         at->bam_query, 0, 0 );
355                 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
356                 SQLFreeStmt( sth, SQL_DROP );
357                 return 1;
358         }
359
360         backsql_BindRowAsStrings( sth, &row );
361
362         rc = SQLFetch( sth );
363         for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
364                 for ( i = 0; i < row.ncols; i++ ) {
365                         if ( row.value_len[ i ] > 0 ) {
366                                 struct berval   bv;
367
368                                 bv.bv_val = row.cols[ i ];
369 #if 0
370                                 bv.bv_len = row.col_prec[ i ];
371 #else
372                                 /*
373                                  * FIXME: what if a binary 
374                                  * is fetched?
375                                  */
376                                 bv.bv_len = strlen( row.cols[ i ] );
377 #endif
378                                 backsql_entry_addattr( bsi->bsi_e, 
379                                                 &row.col_names[ i ], &bv,
380                                                 bsi->bsi_op->o_tmpmemctx );
381
382 #ifdef BACKSQL_TRACE
383                                 Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
384                                         (int)row.col_prec[ i ], 0, 0 );
385                         } else {
386                                 Debug( LDAP_DEBUG_TRACE, "NULL value "
387                                         "in this row for attribute \"%s\"\n",
388                                         row.col_names[ i ].bv_val, 0, 0 );
389 #endif /* BACKSQL_TRACE */
390                         }
391                 }
392         }
393
394         backsql_FreeRow( &row );
395         SQLFreeStmt( sth, SQL_DROP );
396         Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 );
397
398         if ( at->bam_next ) {
399                 return backsql_get_attr_vals( at->bam_next, v_bsi );
400         }
401
402         return 1;
403 }
404
405 int
406 backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
407 {
408         int                     i;
409         int                     rc;
410         AttributeDescription    *ad_oc = slap_schema.si_ad_objectClass;
411
412         Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );
413
414         assert( bsi->bsi_e );
415
416         memset( bsi->bsi_e, 0, sizeof( Entry ) );
417
418         rc = dnPrettyNormal( NULL, &eid->eid_dn,
419                         &bsi->bsi_e->e_name, &bsi->bsi_e->e_nname,
420                         bsi->bsi_op->o_tmpmemctx );
421         if ( rc != LDAP_SUCCESS ) {
422                 return rc;
423         }
424
425         bsi->bsi_e->e_attrs = NULL;
426         bsi->bsi_e->e_private = NULL;
427
428         bsi->bsi_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
429                         eid->eid_oc_id );
430         bsi->bsi_c_eid = eid;
431
432 #ifndef BACKSQL_ARBITRARY_KEY   
433         bsi->bsi_e->e_id = eid->eid_id;
434 #endif /* ! BACKSQL_ARBITRARY_KEY */
435  
436         rc = attr_merge_normalize_one( bsi->bsi_e, ad_oc,
437                                 &bsi->bsi_oc->bom_oc->soc_cname,
438                                 bsi->bsi_op->o_tmpmemctx );
439         if ( rc != LDAP_SUCCESS ) {
440                 entry_clean( bsi->bsi_e );
441                 return rc;
442         }
443
444         if ( bsi->bsi_attrs != NULL ) {
445                 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
446                         "custom attribute list\n", 0, 0, 0 );
447                 for ( i = 0; bsi->bsi_attrs[ i ].an_name.bv_val; i++ ) {
448                         backsql_at_map_rec      **vat;
449                         AttributeName           *an = &bsi->bsi_attrs[ i ];
450                         int                     j;
451
452                         /* if one of the attributes listed here is
453                          * a subtype of another, it must be ignored,
454                          * because subtypes are already dealt with
455                          * by backsql_supad2at()
456                          */
457                         for ( j = 0; bsi->bsi_attrs[ j ].an_name.bv_val; j++ ) {
458                                 /* skip self */
459                                 if ( j == i ) {
460                                         continue;
461                                 }
462
463                                 /* skip subtypes */
464                                 if ( is_at_subtype( an->an_desc->ad_type,
465                                                         bsi->bsi_attrs[ j ].an_desc->ad_type ) )
466                                 {
467                                         goto next;
468                                 }
469                         }
470
471                         rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
472                         if ( rc != 0 || vat == NULL ) {
473                                 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
474                                                 "attribute \"%s\" is not defined "
475                                                 "for objectlass \"%s\"\n",
476                                                 an->an_name.bv_val, 
477                                                 BACKSQL_OC_NAME( bsi->bsi_oc ), 0 );
478                                 continue;
479                         }
480
481                         for ( j = 0; vat[j]; j++ ) {
482                                 backsql_get_attr_vals( vat[j], bsi );
483                         }
484
485                         ch_free( vat );
486
487 next:;
488                 }
489
490         } else {
491                 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
492                         "retrieving all attributes\n", 0, 0, 0 );
493                 avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
494                                 bsi, 0, AVL_INORDER );
495         }
496
497         if ( global_schemacheck ) {
498                 const char      *text = NULL;
499                 char            textbuf[ 1024 ];
500                 size_t          textlen = sizeof( textbuf );
501                 struct berval   bv[ 2 ];
502                 struct berval   soc;
503                 int rc;
504
505                 bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
506                 bv[ 1 ].bv_val = NULL;
507
508                 rc = structural_class( bv, &soc, NULL, 
509                                 &text, textbuf, textlen );
510                 if ( rc != LDAP_SUCCESS ) {
511                         Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
512                                 "structural_class() failed %d (%s)\n",
513                                 bsi->bsi_e->e_name.bv_val,
514                                 rc, text ? text : "" );
515                         entry_clean( bsi->bsi_e );
516                         return rc;
517                 }
518
519                 if ( ( bsi->bsi_flags | BSQL_SF_ALL_OPER )
520                                 || an_find( bsi->bsi_attrs, &AllOper ) ) {
521                         rc = attr_merge_normalize_one( bsi->bsi_e,
522                                         slap_schema.si_ad_structuralObjectClass,
523                                         &soc, bsi->bsi_op->o_tmpmemctx );
524                         if ( rc != LDAP_SUCCESS ) {
525                                 entry_clean( bsi->bsi_e );
526                                 return rc;
527                         }
528                 }
529         }
530
531         Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
532
533         return LDAP_SUCCESS;
534 }
535
536 #endif /* SLAPD_SQL */
537