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