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