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