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