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 94The patches were made against 2.2.18 and can be applied individually, 95but would best be applied in the numerical order of the file names. 96A synopsis of each patch is given here: 97 98 991. Added an option to set SQL query for the "id_query" operation. 100 1012. Added an option to the SQL backend called "use_subtree_shortcut". 102When a search is performed, the SQL query includes a WHERE clause 103which says the DN must be "LIKE %<searchbase>". The LIKE operation 104can be slow in an RDBM. This shortcut option says that if the 105searchbase of the LDAP search is the root DN of the SQL backend, 106and thus all objects will match the LIKE operator, do not include 107the "LIKE %<searchbase>" clause in the SQL query (it is replaced 108instead by the always true "1=1" clause to keep the "AND"'s 109working correctly). This option is off by default, and should be 110turned on only if all objects to be found in the RDBM are under the 111same root DN. Multiple backends working within the same RDBM table 112space would encounter problems. LDAP searches whose searchbase are 113not at the root DN will bypass this shortcut and employ the LIKE 114clause. 115 1163. Added a "create_hint" column to ldap_oc_mappings table. Allows 117taking the value of an attr named in "create_hint" and passing it to 118the create_proc procedure. This is necessary for when an objectClass's 119table is partition indexed by some indexing column and thus the value 120in that indexing column cannot change after the row is created. The 121value for the indexed column is passed into the create_proc, which 122uses it to fill in the indexed column as the new row is created. 123 1244. When loading the values of an attribute, the count(*) of the number 125of values is fetched first and memory is allocated for the array of 126values and normalized values. The old system of loading the values one 127by one and running realloc() on the array of values and normalized 128values each time was badly fragmenting memory. The array of values and 129normalized values would be side by side in memory, and realloc()'ing 130them over and over would force them to leapfrog each other through all 131of available memory. Attrs with a large number of values could not be 132loaded without crashing the slapd daemon. 133 1345. Added code to interpret the value returned by stored procedures 135which have expect_return set. Returned value is interpreted as an LDAP 136return code. This allows the distinction between the SQL failing to 137execute and the SQL running to completion and returning an error code 138which can indicate a policy violation. 139 1406. Added RDBM connection pooling. Once an operation is finished the 141connection to the RDBM is returned to a pool rather than closing. 142Allows the next operation to skip the initialization and authentication 143phases of contacting the RDBM. Also, if licensing with ODBC places 144a limit on the number of connections, an LDAP thread can block waiting 145for another thread to finish, so that no LDAP errors are returned 146for having more LDAP connections than allowed RDBM connections. An 147RDBM connection which receives an SQL error is marked as "tainted" 148so that it will be closed rather than returned to the pool. 149 Also, RDBM connections must be bound to a given LDAP connection AND 150operation number, and NOT just the connection number. Asynchronous 151LDAP clients can have multiple simultaneous LDAP operations which 152should not share the same RDBM connection. A given LDAP operation can 153even make multiple SQL operations (e.g. a BIND operation which 154requires SASL to perform an LDAP search to convert the SASL ID to an 155LDAP DN), so each RDBM connection now has a refcount that must reach 156zero before the connection is returned to the free pool. 157 1587. Added ability to change the objectClass of an object. Required 159considerable work to copy all attributes out of old object and into 160new object. Does a schema check before proceeding. Creates a new 161object, fills it in, deletes the old object, then changes the 162oc_map_id and keyval of the entry in the "ldap_entries" table. 163 1648. Generic fixes. Includes initializing pointers before they 165get used in error branch cases, pointer checks before dereferencing, 166resetting a return code to success after a COMPARE op, sealing 167memory 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 169location in the source code where the x=x test was added to the SQL 170can 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 180typedef struct { 181 SWORD ncols; 182 BerVarray col_names; 183 UDWORD *col_prec; 184 SQLSMALLINT *col_type; 185 char **cols; 186 SQLLEN *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) ) 231typedef 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 */ 236typedef 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 */ 273typedef 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 char **ba_argv; 284 int ba_argc; 285} backsql_api; 286 287/* 288 * "structural" objectClass mapping structure 289 */ 290typedef struct backsql_oc_map_rec { 291 /* 292 * Structure of corresponding LDAP objectClass definition 293 */ 294 ObjectClass *bom_oc; 295#define BACKSQL_OC_NAME(ocmap) ((ocmap)->bom_oc->soc_cname.bv_val) 296 297 struct berval bom_keytbl; 298 struct berval bom_keycol; 299 /* expected to return keyval of newly created entry */ 300 char *bom_create_proc; 301 /* in case create_proc does not return the keyval of the newly 302 * created row */ 303 char *bom_create_keyval; 304 /* supposed to expect keyval as parameter and delete 305 * all the attributes as well */ 306 char *bom_delete_proc; 307 /* flags whether delete_proc is a function (whether back-sql 308 * should bind first parameter as output for return code) */ 309 int bom_expect_return; 310 backsql_key_t bom_id; 311 Avlnode *bom_attrs; 312 AttributeDescription *bom_create_hint; 313} backsql_oc_map_rec; 314 315/* 316 * attributeType mapping structure 317 */ 318typedef struct backsql_at_map_rec { 319 /* Description of corresponding LDAP attribute type */ 320 AttributeDescription *bam_ad; 321 AttributeDescription *bam_true_ad; 322 /* ObjectClass if bam_ad is objectClass */ 323 ObjectClass *bam_oc; 324 325 struct berval bam_from_tbls; 326 struct berval bam_join_where; 327 struct berval bam_sel_expr; 328 329 /* TimesTen, or, if a uppercase function is defined, 330 * an uppercased version of bam_sel_expr */ 331 struct berval bam_sel_expr_u; 332 333 /* supposed to expect 2 binded values: entry keyval 334 * and attr. value to add, like "add_name(?,?,?)" */ 335 char *bam_add_proc; 336 /* supposed to expect 2 binded values: entry keyval 337 * and attr. value to delete */ 338 char *bam_delete_proc; 339 /* for optimization purposes attribute load query 340 * is preconstructed from parts on schemamap load time */ 341 char *bam_query; 342#ifdef BACKSQL_COUNTQUERY 343 char *bam_countquery; 344#endif /* BACKSQL_COUNTQUERY */ 345 /* following flags are bitmasks (first bit used for add_proc, 346 * second - for delete_proc) */ 347 /* order of parameters for procedures above; 348 * 1 means "data then keyval", 0 means "keyval then data" */ 349 int bam_param_order; 350 /* flags whether one or more of procedures is a function 351 * (whether back-sql should bind first parameter as output 352 * for return code) */ 353 int bam_expect_return; 354 355 /* next mapping for attribute */ 356 struct backsql_at_map_rec *bam_next; 357} backsql_at_map_rec; 358 359#define BACKSQL_AT_MAP_REC_INIT { NULL, NULL, BER_BVC(""), BER_BVC(""), BER_BVNULL, BER_BVNULL, NULL, NULL, NULL, 0, 0, NULL } 360 361/* define to uppercase filters only if the matching rule requires it 362 * (currently broken) */ 363/* #define BACKSQL_UPPERCASE_FILTER */ 364 365#define BACKSQL_AT_CANUPPERCASE(at) ( !BER_BVISNULL( &(at)->bam_sel_expr_u ) ) 366 367/* defines to support bitmasks above */ 368#define BACKSQL_ADD 0x1 369#define BACKSQL_DEL 0x2 370 371#define BACKSQL_IS_ADD(x) ( ( BACKSQL_ADD & (x) ) == BACKSQL_ADD ) 372#define BACKSQL_IS_DEL(x) ( ( BACKSQL_DEL & (x) ) == BACKSQL_DEL ) 373 374#define BACKSQL_NCMP(v1,v2) ber_bvcmp((v1),(v2)) 375 376#define BACKSQL_CONCAT 377/* 378 * berbuf structure: a berval with a buffer size associated 379 */ 380typedef struct berbuf { 381 struct berval bb_val; 382 ber_len_t bb_len; 383} BerBuffer; 384 385#define BB_NULL { BER_BVNULL, 0 } 386 387/* 388 * Entry ID structure 389 */ 390typedef struct backsql_entryID { 391 /* #define BACKSQL_ARBITRARY_KEY to allow a non-numeric key. 392 * It is required by some special applications that use 393 * strings as keys for the main table. 394 * In this case, #define BACKSQL_MAX_KEY_LEN consistently 395 * with the key size definition */ 396#ifdef BACKSQL_ARBITRARY_KEY 397 struct berval eid_id; 398 struct berval eid_keyval; 399#define BACKSQL_MAX_KEY_LEN 64 400#else /* ! BACKSQL_ARBITRARY_KEY */ 401 /* The original numeric key is maintained as default. */ 402 backsql_key_t eid_id; 403 backsql_key_t eid_keyval; 404#endif /* ! BACKSQL_ARBITRARY_KEY */ 405 406 backsql_key_t eid_oc_id; 407 backsql_oc_map_rec *eid_oc; 408 struct berval eid_dn; 409 struct berval eid_ndn; 410 struct backsql_entryID *eid_next; 411} backsql_entryID; 412 413#ifdef BACKSQL_ARBITRARY_KEY 414#define BACKSQL_ENTRYID_INIT { BER_BVNULL, BER_BVNULL, 0, NULL, BER_BVNULL, BER_BVNULL, NULL } 415#else /* ! BACKSQL_ARBITRARY_KEY */ 416#define BACKSQL_ENTRYID_INIT { 0, 0, 0, NULL, BER_BVNULL, BER_BVNULL, NULL } 417#endif /* BACKSQL_ARBITRARY_KEY */ 418 419/* the function must collect the entry associated to nbase */ 420#define BACKSQL_ISF_GET_ID 0x1U 421#define BACKSQL_ISF_GET_ENTRY ( 0x2U | BACKSQL_ISF_GET_ID ) 422#define BACKSQL_ISF_GET_OC ( 0x4U | BACKSQL_ISF_GET_ID ) 423#define BACKSQL_ISF_MATCHED 0x8U 424#define BACKSQL_IS_GET_ID(f) \ 425 ( ( (f) & BACKSQL_ISF_GET_ID ) == BACKSQL_ISF_GET_ID ) 426#define BACKSQL_IS_GET_ENTRY(f) \ 427 ( ( (f) & BACKSQL_ISF_GET_ENTRY ) == BACKSQL_ISF_GET_ENTRY ) 428#define BACKSQL_IS_GET_OC(f) \ 429 ( ( (f) & BACKSQL_ISF_GET_OC ) == BACKSQL_ISF_GET_OC ) 430#define BACKSQL_IS_MATCHED(f) \ 431 ( ( (f) & BACKSQL_ISF_MATCHED ) == BACKSQL_ISF_MATCHED ) 432typedef struct backsql_srch_info { 433 Operation *bsi_op; 434 SlapReply *bsi_rs; 435 436 unsigned bsi_flags; 437#define BSQL_SF_NONE 0x0000U 438#define BSQL_SF_ALL_USER 0x0001U 439#define BSQL_SF_ALL_OPER 0x0002U 440#define BSQL_SF_ALL_ATTRS (BSQL_SF_ALL_USER|BSQL_SF_ALL_OPER) 441#define BSQL_SF_FILTER_HASSUBORDINATE 0x0010U 442#define BSQL_SF_FILTER_ENTRYUUID 0x0020U 443#define BSQL_SF_FILTER_ENTRYCSN 0x0040U 444#define BSQL_SF_RETURN_ENTRYUUID (BSQL_SF_FILTER_ENTRYUUID << 8) 445#define BSQL_ISF(bsi, f) ( ( (bsi)->bsi_flags & f ) == f ) 446#define BSQL_ISF_ALL_USER(bsi) BSQL_ISF(bsi, BSQL_SF_ALL_USER) 447#define BSQL_ISF_ALL_OPER(bsi) BSQL_ISF(bsi, BSQL_SF_ALL_OPER) 448#define BSQL_ISF_ALL_ATTRS(bsi) BSQL_ISF(bsi, BSQL_SF_ALL_ATTRS) 449 450 struct berval *bsi_base_ndn; 451 int bsi_use_subtree_shortcut; 452 backsql_entryID bsi_base_id; 453 int bsi_scope; 454/* BACKSQL_SCOPE_BASE_LIKE can be set by API in ors_scope 455 * whenever the search base DN contains chars that cannot 456 * be mapped into the charset used in the RDBMS; so they're 457 * turned into '%' and an approximate ('LIKE') condition 458 * is used */ 459#define BACKSQL_SCOPE_BASE_LIKE ( LDAP_SCOPE_BASE | 0x1000 ) 460 Filter *bsi_filter; 461 time_t bsi_stoptime; 462 463 backsql_entryID *bsi_id_list, 464 **bsi_id_listtail, 465 *bsi_c_eid; 466 int bsi_n_candidates; 467 int bsi_status; 468 469 backsql_oc_map_rec *bsi_oc; 470 struct berbuf bsi_sel, 471 bsi_from, 472 bsi_join_where, 473 bsi_flt_where; 474 ObjectClass *bsi_filter_oc; 475 SQLHDBC bsi_dbh; 476 AttributeName *bsi_attrs; 477 478 Entry *bsi_e; 479} backsql_srch_info; 480 481/* 482 * Backend private data structure 483 */ 484typedef struct backsql_info { 485 char *sql_dbhost; 486 int sql_dbport; 487 char *sql_dbuser; 488 char *sql_dbpasswd; 489 char *sql_dbname; 490 491 /* 492 * SQL condition for subtree searches differs in syntax: 493 * "LIKE CONCAT('%',?)" or "LIKE '%'+?" or "LIKE '%'||?" 494 * or smtg else 495 */ 496 struct berval sql_subtree_cond; 497 struct berval sql_children_cond; 498 struct berval sql_dn_match_cond; 499 char *sql_oc_query; 500 char *sql_at_query; 501 char *sql_insentry_stmt; 502 char *sql_delentry_stmt; 503 char *sql_renentry_stmt; 504 char *sql_delobjclasses_stmt; 505 char *sql_id_query; 506 char *sql_has_children_query; 507 char *sql_list_children_query; 508 509 MatchingRule *sql_caseIgnoreMatch; 510 MatchingRule *sql_telephoneNumberMatch; 511 512 struct berval sql_upper_func; 513 struct berval sql_upper_func_open; 514 struct berval sql_upper_func_close; 515 struct berval sql_strcast_func; 516 BerVarray sql_concat_func; 517 char *sql_concat_patt; 518 519 struct berval sql_aliasing; 520 struct berval sql_aliasing_quote; 521 struct berval sql_dn_oc_aliasing; 522 523 AttributeName *sql_anlist; 524 525 unsigned int sql_flags; 526#define BSQLF_SCHEMA_LOADED 0x0001 527#define BSQLF_UPPER_NEEDS_CAST 0x0002 528#define BSQLF_CREATE_NEEDS_SELECT 0x0004 529#define BSQLF_FAIL_IF_NO_MAPPING 0x0008 530#define BSQLF_HAS_LDAPINFO_DN_RU 0x0010 531#define BSQLF_DONTCHECK_LDAPINFO_DN_RU 0x0020 532#define BSQLF_USE_REVERSE_DN 0x0040 533#define BSQLF_ALLOW_ORPHANS 0x0080 534#define BSQLF_USE_SUBTREE_SHORTCUT 0x0100 535#define BSQLF_FETCH_ALL_USERATTRS 0x0200 536#define BSQLF_FETCH_ALL_OPATTRS 0x0400 537#define BSQLF_FETCH_ALL_ATTRS (BSQLF_FETCH_ALL_USERATTRS|BSQLF_FETCH_ALL_OPATTRS) 538#define BSQLF_CHECK_SCHEMA 0x0800 539#define BSQLF_AUTOCOMMIT_ON 0x1000 540 541#define BACKSQL_ISF(si, f) \ 542 (((si)->sql_flags & f) == f) 543 544#define BACKSQL_SCHEMA_LOADED(si) \ 545 BACKSQL_ISF(si, BSQLF_SCHEMA_LOADED) 546#define BACKSQL_UPPER_NEEDS_CAST(si) \ 547 BACKSQL_ISF(si, BSQLF_UPPER_NEEDS_CAST) 548#define BACKSQL_CREATE_NEEDS_SELECT(si) \ 549 BACKSQL_ISF(si, BSQLF_CREATE_NEEDS_SELECT) 550#define BACKSQL_FAIL_IF_NO_MAPPING(si) \ 551 BACKSQL_ISF(si, BSQLF_FAIL_IF_NO_MAPPING) 552#define BACKSQL_HAS_LDAPINFO_DN_RU(si) \ 553 BACKSQL_ISF(si, BSQLF_HAS_LDAPINFO_DN_RU) 554#define BACKSQL_DONTCHECK_LDAPINFO_DN_RU(si) \ 555 BACKSQL_ISF(si, BSQLF_DONTCHECK_LDAPINFO_DN_RU) 556#define BACKSQL_USE_REVERSE_DN(si) \ 557 BACKSQL_ISF(si, BSQLF_USE_REVERSE_DN) 558#define BACKSQL_CANUPPERCASE(si) \ 559 (!BER_BVISNULL( &(si)->sql_upper_func )) 560#define BACKSQL_ALLOW_ORPHANS(si) \ 561 BACKSQL_ISF(si, BSQLF_ALLOW_ORPHANS) 562#define BACKSQL_USE_SUBTREE_SHORTCUT(si) \ 563 BACKSQL_ISF(si, BSQLF_USE_SUBTREE_SHORTCUT) 564#define BACKSQL_FETCH_ALL_USERATTRS(si) \ 565 BACKSQL_ISF(si, BSQLF_FETCH_ALL_USERATTRS) 566#define BACKSQL_FETCH_ALL_OPATTRS(si) \ 567 BACKSQL_ISF(si, BSQLF_FETCH_ALL_OPATTRS) 568#define BACKSQL_FETCH_ALL_ATTRS(si) \ 569 BACKSQL_ISF(si, BSQLF_FETCH_ALL_ATTRS) 570#define BACKSQL_CHECK_SCHEMA(si) \ 571 BACKSQL_ISF(si, BSQLF_CHECK_SCHEMA) 572#define BACKSQL_AUTOCOMMIT_ON(si) \ 573 BACKSQL_ISF(si, BSQLF_AUTOCOMMIT_ON) 574 575 Entry *sql_baseObject; 576 char *sql_base_ob_file; 577#ifdef BACKSQL_ARBITRARY_KEY 578#define BACKSQL_BASEOBJECT_IDSTR "baseObject" 579#define BACKSQL_BASEOBJECT_KEYVAL BACKSQL_BASEOBJECT_IDSTR 580#define BACKSQL_IS_BASEOBJECT_ID(id) (bvmatch((id), &backsql_baseObject_bv)) 581#else /* ! BACKSQL_ARBITRARY_KEY */ 582#define BACKSQL_BASEOBJECT_ID 0 583#define BACKSQL_BASEOBJECT_IDSTR LDAP_XSTRING(BACKSQL_BASEOBJECT_ID) 584#define BACKSQL_BASEOBJECT_KEYVAL 0 585#define BACKSQL_IS_BASEOBJECT_ID(id) (*(id) == BACKSQL_BASEOBJECT_ID) 586#endif /* ! BACKSQL_ARBITRARY_KEY */ 587#define BACKSQL_BASEOBJECT_OC 0 588 589 Avlnode *sql_db_conns; 590 SQLHDBC sql_dbh; 591 ldap_pvt_thread_mutex_t sql_dbconn_mutex; 592 Avlnode *sql_oc_by_oc; 593 Avlnode *sql_oc_by_id; 594 ldap_pvt_thread_mutex_t sql_schema_mutex; 595 SQLHENV sql_db_env; 596 597 backsql_api *sql_api; 598} backsql_info; 599 600#define BACKSQL_SUCCESS( rc ) \ 601 ( (rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO ) 602 603#define BACKSQL_AVL_STOP 0 604#define BACKSQL_AVL_CONTINUE 1 605 606/* see ldap.h for the meaning of the macros and of the values */ 607#define BACKSQL_LEGAL_ERROR( rc ) \ 608 ( LDAP_RANGE( (rc), 0x00, 0x0e ) \ 609 || LDAP_ATTR_ERROR( (rc) ) \ 610 || LDAP_NAME_ERROR( (rc) ) \ 611 || LDAP_SECURITY_ERROR( (rc) ) \ 612 || LDAP_SERVICE_ERROR( (rc) ) \ 613 || LDAP_UPDATE_ERROR( (rc) ) ) 614#define BACKSQL_SANITIZE_ERROR( rc ) \ 615 ( BACKSQL_LEGAL_ERROR( (rc) ) ? (rc) : LDAP_OTHER ) 616 617#define BACKSQL_IS_BINARY(ct) \ 618 ( (ct) == SQL_BINARY \ 619 || (ct) == SQL_VARBINARY \ 620 || (ct) == SQL_LONGVARBINARY) 621 622#ifdef BACKSQL_ARBITRARY_KEY 623#define BACKSQL_IDFMT "%s" 624#define BACKSQL_IDARG(arg) ((arg).bv_val) 625#else /* ! BACKSQL_ARBITRARY_KEY */ 626#define BACKSQL_IDFMT BACKSQL_IDNUMFMT 627#define BACKSQL_IDARG(arg) (arg) 628#endif /* ! BACKSQL_ARBITRARY_KEY */ 629 630#endif /* __BACKSQL_H__ */ 631 632