]> git.sur5r.net Git - openldap/blob - servers/slapd/back-sql/back-sql.h
638267a7deffbac70d7e0472ffa8867daae85d7d
[openldap] / servers / slapd / back-sql / back-sql.h
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2011 The OpenLDAP Foundation.
5  * Portions Copyright 1999 Dmitry Kovalev.
6  * Portions Copyright 2002 Pierangelo Mararati.
7  * Portions Copyright 2004 Mark Adamson.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS:
19  * This work was initially developed by Dmitry Kovalev for inclusion
20  * by OpenLDAP Software.  Additional significant contributors include
21  * Pierangelo Masarati and Mark Adamson.
22  */
23 /*
24  * The following changes have been addressed:
25  *       
26  * Enhancements:
27  *   - re-styled code for better readability
28  *   - upgraded backend API to reflect recent changes
29  *   - LDAP schema is checked when loading SQL/LDAP mapping
30  *   - AttributeDescription/ObjectClass pointers used for more efficient
31  *     mapping lookup
32  *   - bervals used where string length is required often
33  *   - atomized write operations by committing at the end of each operation
34  *     and defaulting connection closure to rollback
35  *   - added LDAP access control to write operations
36  *   - fully implemented modrdn (with rdn attrs change, deleteoldrdn,
37  *     access check, parent/children check and more)
38  *   - added parent access control, children control to delete operation
39  *   - added structuralObjectClass operational attribute check and
40  *     value return on search
41  *   - added hasSubordinate operational attribute on demand
42  *   - search limits are appropriately enforced
43  *   - function backsql_strcat() has been made more efficient
44  *   - concat function has been made configurable by means of a pattern
45  *   - added config switches:
46  *       - fail_if_no_mapping   write operations fail if there is no mapping
47  *       - has_ldapinfo_dn_ru   overrides autodetect
48  *       - concat_pattern       a string containing two '?' is used
49  *                              (note that "?||?" should be more portable
50  *                              than builtin function "CONCAT(?,?)")
51  *       - strcast_func         cast of string constants in "SELECT DISTINCT
52  *                              statements (needed by PostgreSQL)
53  *       - upper_needs_cast     cast the argument of upper when required
54  *                              (basically when building dn substring queries)
55  *   - added noop control
56  *   - added values return filter control
57  *   - hasSubordinate can be used in search filters (with limitations)
58  *   - eliminated oc->name; use oc->oc->soc_cname instead
59  * 
60  * Todo:
61  *   - add security checks for SQL statements that can be injected (?)
62  *   - re-test with previously supported RDBMs
63  *   - replace dn_ru and so with normalized dn (no need for upper() and so
64  *     in dn match)
65  *   - implement a backsql_normalize() function to replace the upper()
66  *     conversion routines
67  *   - note that subtree deletion, subtree renaming and so could be easily
68  *     implemented (rollback and consistency checks are available :)
69  *   - implement "lastmod" and other operational stuff (ldap_entries table ?)
70  *   - check how to allow multiple operations with one statement, to remove
71  *     BACKSQL_REALLOC_STMT from modify.c (a more recent unixODBC lib?)
72  */
73 /*
74  * Improvements submitted by (ITS#3432)
75  *
76  * 1. id_query.patch            applied (with changes)
77  * 2. shortcut.patch            applied (reworked)
78  * 3. create_hint.patch         applied
79  * 4. count_query.patch         applied (reworked)
80  * 5. returncodes.patch         applied (with sanity checks)
81  * 6. connpool.patch            under evaluation
82  * 7. modoc.patch               under evaluation (requires
83  *                              manageDSAit and "manage"
84  *                              access privileges)
85  * 8. miscfixes.patch           applied (reworked; other
86  *                              operations need to load the
87  *                              entire entry for ACL purposes;
88  *                              see ITS#3480, now fixed)
89  *
90  * original description:
91
92          Changes that were made to the SQL backend.
93
94 The patches were made against 2.2.18 and can be applied individually,
95 but would best be applied in the numerical order of the file names.
96 A synopsis of each patch is given here:
97
98
99 1. Added an option to set SQL query for the "id_query" operation.
100
101 2. Added an option to the SQL backend called "use_subtree_shortcut".
102 When a search is performed, the SQL query includes a WHERE clause
103 which says the DN must be "LIKE %<searchbase>".  The LIKE operation
104 can be slow in an RDBM. This shortcut option says that if the
105 searchbase of the LDAP search is the root DN of the SQL backend,
106 and thus all objects will match the LIKE operator, do not include
107 the "LIKE %<searchbase>" clause in the SQL query (it is replaced
108 instead by the always true "1=1" clause to keep the "AND"'s 
109 working correctly).  This option is off by default, and should be
110 turned on only if all objects to be found in the RDBM are under the
111 same root DN. Multiple backends working within the same RDBM table
112 space would encounter problems. LDAP searches whose searchbase are
113 not at the root DN will bypass this shortcut and employ the LIKE 
114 clause.
115
116 3. Added a "create_hint" column to ldap_oc_mappings table. Allows
117 taking the value of an attr named in "create_hint" and passing it to
118 the create_proc procedure.  This is necessary for when an objectClass's
119 table is partition indexed by some indexing column and thus the value
120 in that indexing column cannot change after the row is created. The
121 value for the indexed column is passed into the create_proc, which
122 uses it to fill in the indexed column as the new row is created.
123
124 4. When loading the values of an attribute, the count(*) of the number
125 of values is fetched first and memory is allocated for the array of
126 values and normalized values. The old system of loading the values one
127 by one and running realloc() on the array of values and normalized
128 values each time was badly fragmenting memory. The array of values and
129 normalized values would be side by side in memory, and realloc()'ing
130 them over and over would force them to leapfrog each other through all
131 of available memory. Attrs with a large number of values could not be
132 loaded without crashing the slapd daemon.
133
134 5. Added code to interpret the value returned by stored procedures
135 which have expect_return set. Returned value is interpreted as an LDAP
136 return code. This allows the distinction between the SQL failing to
137 execute and the SQL running to completion and returning an error code
138 which can indicate a policy violation.
139
140 6. Added RDBM connection pooling. Once an operation is finished the
141 connection to the RDBM is returned to a pool rather than closing.
142 Allows the next operation to skip the initialization and authentication
143 phases of contacting the RDBM. Also, if licensing with ODBC places
144 a limit on the number of connections, an LDAP thread can block waiting
145 for another thread to finish, so that no LDAP errors are returned
146 for having more LDAP connections than allowed RDBM connections. An
147 RDBM connection which receives an SQL error is marked as "tainted"
148 so that it will be closed rather than returned to the pool.
149   Also, RDBM connections must be bound to a given LDAP connection AND
150 operation number, and NOT just the connection number.  Asynchronous
151 LDAP clients can have multiple simultaneous LDAP operations which
152 should not share the same RDBM connection.  A given LDAP operation can
153 even make multiple SQL operations (e.g. a BIND operation which
154 requires SASL to perform an LDAP search to convert the SASL ID to an
155 LDAP DN), so each RDBM connection now has a refcount that must reach
156 zero before the connection is returned to the free pool.
157
158 7. Added ability to change the objectClass of an object. Required 
159 considerable work to copy all attributes out of old object and into
160 new object.  Does a schema check before proceeding.  Creates a new
161 object, fills it in, deletes the old object, then changes the 
162 oc_map_id and keyval of the entry in the "ldap_entries" table.
163
164 8.  Generic fixes. Includes initializing pointers before they
165 get used in error branch cases, pointer checks before dereferencing,
166 resetting a return code to success after a COMPARE op, sealing
167 memory leaks, and in search.c, changing some of the "1=1" tests to
168 "2=2", "3=3", etc so that when reading slapd trace output, the 
169 location in the source code where the x=x test was added to the SQL
170 can be easily distinguished.
171  */
172
173 #ifndef __BACKSQL_H__
174 #define __BACKSQL_H__
175
176 /* former sql-types.h */
177 #include <sql.h>
178 #include <sqlext.h>
179
180 typedef struct {
181         SWORD           ncols;
182         BerVarray       col_names;
183         UDWORD          *col_prec;
184         SQLSMALLINT     *col_type;
185         char            **cols;
186         SQLINTEGER      *value_len;
187 } BACKSQL_ROW_NTS;
188
189 /*
190  * Better use the standard length of 8192 (as of slap.h)?
191  *
192  * NOTE: must be consistent with definition in ldap_entries table
193  */
194 /* #define BACKSQL_MAX_DN_LEN   SLAP_LDAPDN_MAXLEN */
195 #define BACKSQL_MAX_DN_LEN      255
196
197 /*
198  * define to enable very extensive trace logging (debug only)
199  */
200 #undef BACKSQL_TRACE
201
202 /*
203  * define if using MS SQL and workaround needed (see sql-wrap.c)
204  */
205 #undef BACKSQL_MSSQL_WORKAROUND
206
207 /*
208  * define to enable values counting for attributes
209  */
210 #define BACKSQL_COUNTQUERY
211
212 /*
213  * define to enable prettification/validation of values
214  */
215 #define BACKSQL_PRETTY_VALIDATE
216
217 /*
218  * define to enable varchars as unique keys in user tables
219  *
220  * by default integers are used (and recommended)
221  * for performances.  Integers are used anyway in back-sql
222  * related tables.
223  */
224 #undef BACKSQL_ARBITRARY_KEY
225
226 /*
227  * type used for keys
228  */
229 #if defined(HAVE_LONG_LONG) && defined(SQL_C_UBIGINT) && \
230         ( defined(HAVE_STRTOULL) || defined(HAVE_STRTOUQ) )
231 typedef unsigned long long backsql_key_t;
232 #define BACKSQL_C_NUMID SQL_C_UBIGINT
233 #define BACKSQL_IDNUMFMT "%llu"
234 #define BACKSQL_STR2ID lutil_atoullx
235 #else /* ! HAVE_LONG_LONG || ! SQL_C_UBIGINT */
236 typedef unsigned long backsql_key_t;
237 #define BACKSQL_C_NUMID SQL_C_ULONG
238 #define BACKSQL_IDNUMFMT "%lu"
239 #define BACKSQL_STR2ID lutil_atoulx
240 #endif /* ! HAVE_LONG_LONG */
241
242 /*
243  * define to enable support for syncprov overlay
244  */
245 #define BACKSQL_SYNCPROV
246
247 /*
248  * define to the appropriate aliasing string
249  *
250  * some RDBMSes tolerate (or require) that " AS " is not used
251  * when aliasing tables/columns
252  */
253 #define BACKSQL_ALIASING        "AS "
254 /* #define      BACKSQL_ALIASING        "" */
255
256 /*
257  * define to the appropriate quoting char
258  *
259  * some RDBMSes tolerate/require that the aliases be enclosed
260  * in quotes.  This is especially true for those that do not
261  * allow keywords used as aliases.
262  */
263 #define BACKSQL_ALIASING_QUOTE  ""
264 /* #define BACKSQL_ALIASING_QUOTE       "\"" */
265 /* #define BACKSQL_ALIASING_QUOTE       "'" */
266
267 /*
268  * API
269  *
270  * a simple mechanism to allow DN mucking between the LDAP
271  * and the stored string representation.
272  */
273 typedef struct backsql_api {
274         char                    *ba_name;
275         int                     (*ba_config)( struct backsql_api *self, int argc, char *argv[] );
276         int                     (*ba_destroy)( struct backsql_api *self );
277
278         int                     (*ba_dn2odbc)( Operation *op, SlapReply *rs, struct berval *dn );
279         int                     (*ba_odbc2dn)( Operation *op, SlapReply *rs, struct berval *dn );
280
281         void                    *ba_private;
282         struct backsql_api      *ba_next;
283 } backsql_api;
284
285 /*
286  * "structural" objectClass mapping structure
287  */
288 typedef struct backsql_oc_map_rec {
289         /*
290          * Structure of corresponding LDAP objectClass definition
291          */
292         ObjectClass             *bom_oc;
293 #define BACKSQL_OC_NAME(ocmap)  ((ocmap)->bom_oc->soc_cname.bv_val)
294         
295         struct berval           bom_keytbl;
296         struct berval           bom_keycol;
297         /* expected to return keyval of newly created entry */
298         char                    *bom_create_proc;
299         /* in case create_proc does not return the keyval of the newly
300          * created row */
301         char                    *bom_create_keyval;
302         /* supposed to expect keyval as parameter and delete 
303          * all the attributes as well */
304         char                    *bom_delete_proc;
305         /* flags whether delete_proc is a function (whether back-sql 
306          * should bind first parameter as output for return code) */
307         int                     bom_expect_return;
308         backsql_key_t           bom_id;
309         Avlnode                 *bom_attrs;
310         AttributeDescription    *bom_create_hint;
311 } backsql_oc_map_rec;
312
313 /*
314  * attributeType mapping structure
315  */
316 typedef struct backsql_at_map_rec {
317         /* Description of corresponding LDAP attribute type */
318         AttributeDescription    *bam_ad;
319         AttributeDescription    *bam_true_ad;
320         /* ObjectClass if bam_ad is objectClass */
321         ObjectClass             *bam_oc;
322
323         struct berval   bam_from_tbls;
324         struct berval   bam_join_where;
325         struct berval   bam_sel_expr;
326
327         /* TimesTen, or, if a uppercase function is defined,
328          * an uppercased version of bam_sel_expr */
329         struct berval   bam_sel_expr_u;
330
331         /* supposed to expect 2 binded values: entry keyval 
332          * and attr. value to add, like "add_name(?,?,?)" */
333         char            *bam_add_proc;
334         /* supposed to expect 2 binded values: entry keyval 
335          * and attr. value to delete */
336         char            *bam_delete_proc;
337         /* for optimization purposes attribute load query 
338          * is preconstructed from parts on schemamap load time */
339         char            *bam_query;
340 #ifdef BACKSQL_COUNTQUERY
341         char            *bam_countquery;
342 #endif /* BACKSQL_COUNTQUERY */
343         /* following flags are bitmasks (first bit used for add_proc, 
344          * second - for delete_proc) */
345         /* order of parameters for procedures above; 
346          * 1 means "data then keyval", 0 means "keyval then data" */
347         int             bam_param_order;
348         /* flags whether one or more of procedures is a function 
349          * (whether back-sql should bind first parameter as output 
350          * for return code) */
351         int             bam_expect_return;
352
353         /* next mapping for attribute */
354         struct backsql_at_map_rec       *bam_next;
355 } backsql_at_map_rec;
356
357 #define BACKSQL_AT_MAP_REC_INIT { NULL, NULL, BER_BVC(""), BER_BVC(""), BER_BVNULL, BER_BVNULL, NULL, NULL, NULL, 0, 0, NULL }
358
359 /* define to uppercase filters only if the matching rule requires it
360  * (currently broken) */
361 /* #define      BACKSQL_UPPERCASE_FILTER */
362
363 #define BACKSQL_AT_CANUPPERCASE(at)     ( !BER_BVISNULL( &(at)->bam_sel_expr_u ) )
364
365 /* defines to support bitmasks above */
366 #define BACKSQL_ADD     0x1
367 #define BACKSQL_DEL     0x2
368
369 #define BACKSQL_IS_ADD(x)       ( ( BACKSQL_ADD & (x) ) == BACKSQL_ADD )
370 #define BACKSQL_IS_DEL(x)       ( ( BACKSQL_DEL & (x) ) == BACKSQL_DEL )
371
372 #define BACKSQL_NCMP(v1,v2)     ber_bvcmp((v1),(v2))
373
374 #define BACKSQL_CONCAT
375 /*
376  * berbuf structure: a berval with a buffer size associated
377  */
378 typedef struct berbuf {
379         struct berval   bb_val;
380         ber_len_t       bb_len;
381 } BerBuffer;
382
383 #define BB_NULL         { BER_BVNULL, 0 }
384
385 /*
386  * Entry ID structure
387  */
388 typedef struct backsql_entryID {
389         /* #define BACKSQL_ARBITRARY_KEY to allow a non-numeric key.
390          * It is required by some special applications that use
391          * strings as keys for the main table.
392          * In this case, #define BACKSQL_MAX_KEY_LEN consistently
393          * with the key size definition */
394 #ifdef BACKSQL_ARBITRARY_KEY
395         struct berval           eid_id;
396         struct berval           eid_keyval;
397 #define BACKSQL_MAX_KEY_LEN     64
398 #else /* ! BACKSQL_ARBITRARY_KEY */
399         /* The original numeric key is maintained as default. */
400         backsql_key_t           eid_id;
401         backsql_key_t           eid_keyval;
402 #endif /* ! BACKSQL_ARBITRARY_KEY */
403
404         backsql_key_t           eid_oc_id;
405         backsql_oc_map_rec      *eid_oc;
406         struct berval           eid_dn;
407         struct berval           eid_ndn;
408         struct backsql_entryID  *eid_next;
409 } backsql_entryID;
410
411 #ifdef BACKSQL_ARBITRARY_KEY
412 #define BACKSQL_ENTRYID_INIT { BER_BVNULL, BER_BVNULL, 0, NULL, BER_BVNULL, BER_BVNULL, NULL }
413 #else /* ! BACKSQL_ARBITRARY_KEY */
414 #define BACKSQL_ENTRYID_INIT { 0, 0, 0, NULL, BER_BVNULL, BER_BVNULL, NULL }
415 #endif /* BACKSQL_ARBITRARY_KEY */
416
417 /* the function must collect the entry associated to nbase */
418 #define BACKSQL_ISF_GET_ID      0x1U
419 #define BACKSQL_ISF_GET_ENTRY   ( 0x2U | BACKSQL_ISF_GET_ID )
420 #define BACKSQL_ISF_GET_OC      ( 0x4U | BACKSQL_ISF_GET_ID )
421 #define BACKSQL_ISF_MATCHED     0x8U
422 #define BACKSQL_IS_GET_ID(f) \
423         ( ( (f) & BACKSQL_ISF_GET_ID ) == BACKSQL_ISF_GET_ID )
424 #define BACKSQL_IS_GET_ENTRY(f) \
425         ( ( (f) & BACKSQL_ISF_GET_ENTRY ) == BACKSQL_ISF_GET_ENTRY )
426 #define BACKSQL_IS_GET_OC(f) \
427         ( ( (f) & BACKSQL_ISF_GET_OC ) == BACKSQL_ISF_GET_OC )
428 #define BACKSQL_IS_MATCHED(f) \
429         ( ( (f) & BACKSQL_ISF_MATCHED ) == BACKSQL_ISF_MATCHED )
430 typedef struct backsql_srch_info {
431         Operation               *bsi_op;
432         SlapReply               *bsi_rs;
433
434         unsigned                bsi_flags;
435 #define BSQL_SF_NONE                    0x0000U
436 #define BSQL_SF_ALL_USER                0x0001U
437 #define BSQL_SF_ALL_OPER                0x0002U
438 #define BSQL_SF_ALL_ATTRS               (BSQL_SF_ALL_USER|BSQL_SF_ALL_OPER)
439 #define BSQL_SF_FILTER_HASSUBORDINATE   0x0010U
440 #define BSQL_SF_FILTER_ENTRYUUID        0x0020U
441 #define BSQL_SF_FILTER_ENTRYCSN         0x0040U
442 #define BSQL_SF_RETURN_ENTRYUUID        (BSQL_SF_FILTER_ENTRYUUID << 8)
443 #define BSQL_ISF(bsi, f)                ( ( (bsi)->bsi_flags & f ) == f )
444 #define BSQL_ISF_ALL_USER(bsi)          BSQL_ISF(bsi, BSQL_SF_ALL_USER)
445 #define BSQL_ISF_ALL_OPER(bsi)          BSQL_ISF(bsi, BSQL_SF_ALL_OPER)
446 #define BSQL_ISF_ALL_ATTRS(bsi)         BSQL_ISF(bsi, BSQL_SF_ALL_ATTRS)
447
448         struct berval           *bsi_base_ndn;
449         int                     bsi_use_subtree_shortcut;
450         backsql_entryID         bsi_base_id;
451         int                     bsi_scope;
452 /* BACKSQL_SCOPE_BASE_LIKE can be set by API in ors_scope
453  * whenever the search base DN contains chars that cannot
454  * be mapped into the charset used in the RDBMS; so they're
455  * turned into '%' and an approximate ('LIKE') condition
456  * is used */
457 #define BACKSQL_SCOPE_BASE_LIKE         ( LDAP_SCOPE_BASE | 0x1000 )
458         Filter                  *bsi_filter;
459         time_t                  bsi_stoptime;
460
461         backsql_entryID         *bsi_id_list,
462                                 **bsi_id_listtail,
463                                 *bsi_c_eid;
464         int                     bsi_n_candidates;
465         int                     bsi_status;
466
467         backsql_oc_map_rec      *bsi_oc;
468         struct berbuf           bsi_sel,
469                                 bsi_from,
470                                 bsi_join_where,
471                                 bsi_flt_where;
472         ObjectClass             *bsi_filter_oc;
473         SQLHDBC                 bsi_dbh;
474         AttributeName           *bsi_attrs;
475
476         Entry                   *bsi_e;
477 } backsql_srch_info;
478
479 /*
480  * Backend private data structure
481  */
482 typedef struct backsql_info {
483         char            *sql_dbhost;
484         int             sql_dbport;
485         char            *sql_dbuser;
486         char            *sql_dbpasswd;
487         char            *sql_dbname;
488
489         /*
490          * SQL condition for subtree searches differs in syntax:
491          * "LIKE CONCAT('%',?)" or "LIKE '%'+?" or "LIKE '%'||?"
492          * or smtg else 
493          */
494         struct berval   sql_subtree_cond;
495         struct berval   sql_children_cond;
496         struct berval   sql_dn_match_cond;
497         char            *sql_oc_query;
498         char            *sql_at_query;
499         char            *sql_insentry_stmt;
500         char            *sql_delentry_stmt;
501         char            *sql_renentry_stmt;
502         char            *sql_delobjclasses_stmt;
503         char            *sql_id_query;
504         char            *sql_has_children_query;
505         char            *sql_list_children_query;
506
507         MatchingRule    *sql_caseIgnoreMatch;
508         MatchingRule    *sql_telephoneNumberMatch;
509
510         struct berval   sql_upper_func;
511         struct berval   sql_upper_func_open;
512         struct berval   sql_upper_func_close;
513         BerVarray       sql_concat_func;
514         struct berval   sql_strcast_func;
515
516         struct berval   sql_aliasing;
517         struct berval   sql_aliasing_quote;
518         struct berval   sql_dn_oc_aliasing;
519
520         AttributeName   *sql_anlist;
521
522         unsigned int    sql_flags;
523 #define BSQLF_SCHEMA_LOADED             0x0001
524 #define BSQLF_UPPER_NEEDS_CAST          0x0002
525 #define BSQLF_CREATE_NEEDS_SELECT       0x0004
526 #define BSQLF_FAIL_IF_NO_MAPPING        0x0008
527 #define BSQLF_HAS_LDAPINFO_DN_RU        0x0010
528 #define BSQLF_DONTCHECK_LDAPINFO_DN_RU  0x0020
529 #define BSQLF_USE_REVERSE_DN            0x0040
530 #define BSQLF_ALLOW_ORPHANS             0x0080
531 #define BSQLF_USE_SUBTREE_SHORTCUT      0x0100
532 #define BSQLF_FETCH_ALL_USERATTRS       0x0200
533 #define BSQLF_FETCH_ALL_OPATTRS         0x0400
534 #define BSQLF_FETCH_ALL_ATTRS           (BSQLF_FETCH_ALL_USERATTRS|BSQLF_FETCH_ALL_OPATTRS)
535 #define BSQLF_CHECK_SCHEMA              0x0800
536 #define BSQLF_AUTOCOMMIT_ON             0x1000
537
538 #define BACKSQL_ISF(si, f) \
539         (((si)->sql_flags & f) == f)
540
541 #define BACKSQL_SCHEMA_LOADED(si) \
542         BACKSQL_ISF(si, BSQLF_SCHEMA_LOADED)
543 #define BACKSQL_UPPER_NEEDS_CAST(si) \
544         BACKSQL_ISF(si, BSQLF_UPPER_NEEDS_CAST)
545 #define BACKSQL_CREATE_NEEDS_SELECT(si) \
546         BACKSQL_ISF(si, BSQLF_CREATE_NEEDS_SELECT)
547 #define BACKSQL_FAIL_IF_NO_MAPPING(si) \
548         BACKSQL_ISF(si, BSQLF_FAIL_IF_NO_MAPPING)
549 #define BACKSQL_HAS_LDAPINFO_DN_RU(si) \
550         BACKSQL_ISF(si, BSQLF_HAS_LDAPINFO_DN_RU)
551 #define BACKSQL_DONTCHECK_LDAPINFO_DN_RU(si) \
552         BACKSQL_ISF(si, BSQLF_DONTCHECK_LDAPINFO_DN_RU)
553 #define BACKSQL_USE_REVERSE_DN(si) \
554         BACKSQL_ISF(si, BSQLF_USE_REVERSE_DN)
555 #define BACKSQL_CANUPPERCASE(si) \
556         (!BER_BVISNULL( &(si)->sql_upper_func ))
557 #define BACKSQL_ALLOW_ORPHANS(si) \
558         BACKSQL_ISF(si, BSQLF_ALLOW_ORPHANS)
559 #define BACKSQL_USE_SUBTREE_SHORTCUT(si) \
560         BACKSQL_ISF(si, BSQLF_USE_SUBTREE_SHORTCUT)
561 #define BACKSQL_FETCH_ALL_USERATTRS(si) \
562         BACKSQL_ISF(si, BSQLF_FETCH_ALL_USERATTRS)
563 #define BACKSQL_FETCH_ALL_OPATTRS(si) \
564         BACKSQL_ISF(si, BSQLF_FETCH_ALL_OPATTRS)
565 #define BACKSQL_FETCH_ALL_ATTRS(si) \
566         BACKSQL_ISF(si, BSQLF_FETCH_ALL_ATTRS)
567 #define BACKSQL_CHECK_SCHEMA(si) \
568         BACKSQL_ISF(si, BSQLF_CHECK_SCHEMA)
569 #define BACKSQL_AUTOCOMMIT_ON(si) \
570         BACKSQL_ISF(si, BSQLF_AUTOCOMMIT_ON)
571
572         Entry           *sql_baseObject;
573 #ifdef BACKSQL_ARBITRARY_KEY
574 #define BACKSQL_BASEOBJECT_IDSTR        "baseObject"
575 #define BACKSQL_BASEOBJECT_KEYVAL       BACKSQL_BASEOBJECT_IDSTR
576 #define BACKSQL_IS_BASEOBJECT_ID(id)    (bvmatch((id), &backsql_baseObject_bv))
577 #else /* ! BACKSQL_ARBITRARY_KEY */
578 #define BACKSQL_BASEOBJECT_ID           0
579 #define BACKSQL_BASEOBJECT_IDSTR        LDAP_XSTRING(BACKSQL_BASEOBJECT_ID)
580 #define BACKSQL_BASEOBJECT_KEYVAL       0
581 #define BACKSQL_IS_BASEOBJECT_ID(id)    (*(id) == BACKSQL_BASEOBJECT_ID)
582 #endif /* ! BACKSQL_ARBITRARY_KEY */
583 #define BACKSQL_BASEOBJECT_OC           0
584         
585         Avlnode         *sql_db_conns;
586         SQLHDBC         sql_dbh;
587         ldap_pvt_thread_mutex_t         sql_dbconn_mutex;
588         Avlnode         *sql_oc_by_oc;
589         Avlnode         *sql_oc_by_id;
590         ldap_pvt_thread_mutex_t         sql_schema_mutex;
591         SQLHENV         sql_db_env;
592
593         backsql_api     *sql_api;
594 } backsql_info;
595
596 #define BACKSQL_SUCCESS( rc ) \
597         ( (rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO )
598
599 #define BACKSQL_AVL_STOP                0
600 #define BACKSQL_AVL_CONTINUE            1
601
602 /* see ldap.h for the meaning of the macros and of the values */
603 #define BACKSQL_LEGAL_ERROR( rc ) \
604         ( LDAP_RANGE( (rc), 0x00, 0x0e ) \
605           || LDAP_ATTR_ERROR( (rc) ) \
606           || LDAP_NAME_ERROR( (rc) ) \
607           || LDAP_SECURITY_ERROR( (rc) ) \
608           || LDAP_SERVICE_ERROR( (rc) ) \
609           || LDAP_UPDATE_ERROR( (rc) ) )
610 #define BACKSQL_SANITIZE_ERROR( rc ) \
611         ( BACKSQL_LEGAL_ERROR( (rc) ) ? (rc) : LDAP_OTHER )
612
613 #define BACKSQL_IS_BINARY(ct) \
614         ( (ct) == SQL_BINARY \
615           || (ct) == SQL_VARBINARY \
616           || (ct) == SQL_LONGVARBINARY)
617
618 #ifdef BACKSQL_ARBITRARY_KEY
619 #define BACKSQL_IDFMT "%s"
620 #define BACKSQL_IDARG(arg) ((arg).bv_val)
621 #else /* ! BACKSQL_ARBITRARY_KEY */
622 #define BACKSQL_IDFMT BACKSQL_IDNUMFMT
623 #define BACKSQL_IDARG(arg) (arg)
624 #endif /* ! BACKSQL_ARBITRARY_KEY */
625
626 #endif /* __BACKSQL_H__ */
627