1/*	$NetBSD: init.c,v 1.3 2021/08/14 16:15:01 christos Exp $	*/
2
3/* $OpenLDAP$ */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1999-2021 The OpenLDAP Foundation.
7 * Portions Copyright 1999 Dmitry Kovalev.
8 * Portions Copyright 2002 Pierangelo Masarati.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted only as authorized by the OpenLDAP
13 * Public License.
14 *
15 * A copy of this license is available in the file LICENSE in the
16 * top-level directory of the distribution or, alternatively, at
17 * <http://www.OpenLDAP.org/license.html>.
18 */
19/* ACKNOWLEDGEMENTS:
20 * This work was initially developed by Dmitry Kovalev for inclusion
21 * by OpenLDAP Software.  Additional significant contributors include
22 * Pierangelo Masarati.
23 */
24
25#include <sys/cdefs.h>
26__RCSID("$NetBSD: init.c,v 1.3 2021/08/14 16:15:01 christos Exp $");
27
28#include "portable.h"
29
30#include <stdio.h>
31#include <sys/types.h>
32#include "ac/string.h"
33
34#include "slap.h"
35#include "slap-config.h"
36#include "proto-sql.h"
37
38int
39sql_back_initialize(
40	BackendInfo	*bi )
41{
42	static char *controls[] = {
43		LDAP_CONTROL_ASSERT,
44		LDAP_CONTROL_MANAGEDSAIT,
45		LDAP_CONTROL_NOOP,
46#ifdef SLAP_CONTROL_X_TREE_DELETE
47		SLAP_CONTROL_X_TREE_DELETE,
48#endif /* SLAP_CONTROL_X_TREE_DELETE */
49#ifndef BACKSQL_ARBITRARY_KEY
50		LDAP_CONTROL_PAGEDRESULTS,
51#endif /* ! BACKSQL_ARBITRARY_KEY */
52		NULL
53	};
54	int rc;
55
56	bi->bi_controls = controls;
57
58	bi->bi_flags |=
59#if 0
60		SLAP_BFLAG_INCREMENT |
61#endif
62		SLAP_BFLAG_REFERRALS;
63
64	Debug( LDAP_DEBUG_TRACE,"==>sql_back_initialize()\n" );
65
66	bi->bi_db_init = backsql_db_init;
67	bi->bi_db_config = config_generic_wrapper;
68	bi->bi_db_open = backsql_db_open;
69	bi->bi_db_close = backsql_db_close;
70	bi->bi_db_destroy = backsql_db_destroy;
71
72	bi->bi_op_abandon = 0;
73	bi->bi_op_compare = backsql_compare;
74	bi->bi_op_bind = backsql_bind;
75	bi->bi_op_unbind = 0;
76	bi->bi_op_search = backsql_search;
77	bi->bi_op_modify = backsql_modify;
78	bi->bi_op_modrdn = backsql_modrdn;
79	bi->bi_op_add = backsql_add;
80	bi->bi_op_delete = backsql_delete;
81
82	bi->bi_chk_referrals = 0;
83	bi->bi_operational = backsql_operational;
84	bi->bi_entry_get_rw = backsql_entry_get;
85	bi->bi_entry_release_rw = backsql_entry_release;
86
87	bi->bi_connection_init = 0;
88
89	rc = backsql_init_cf( bi );
90	Debug( LDAP_DEBUG_TRACE,"<==sql_back_initialize()\n" );
91	return rc;
92}
93
94int
95backsql_destroy(
96	BackendInfo 	*bi )
97{
98	Debug( LDAP_DEBUG_TRACE, "==>backsql_destroy()\n" );
99	Debug( LDAP_DEBUG_TRACE, "<==backsql_destroy()\n" );
100	return 0;
101}
102
103int
104backsql_db_init(
105	BackendDB 	*bd,
106	ConfigReply	*cr )
107{
108	backsql_info	*bi;
109	int		rc = 0;
110
111	Debug( LDAP_DEBUG_TRACE, "==>backsql_db_init()\n" );
112
113	bi = (backsql_info *)ch_calloc( 1, sizeof( backsql_info ) );
114	ldap_pvt_thread_mutex_init( &bi->sql_dbconn_mutex );
115	ldap_pvt_thread_mutex_init( &bi->sql_schema_mutex );
116
117	if ( backsql_init_db_env( bi ) != SQL_SUCCESS ) {
118		rc = -1;
119	}
120
121	bd->be_private = bi;
122	bd->be_cf_ocs = bd->bd_info->bi_cf_ocs;
123
124	Debug( LDAP_DEBUG_TRACE, "<==backsql_db_init()\n" );
125
126	return rc;
127}
128
129int
130backsql_db_destroy(
131	BackendDB 	*bd,
132	ConfigReply	*cr )
133{
134	backsql_info	*bi = (backsql_info*)bd->be_private;
135
136	Debug( LDAP_DEBUG_TRACE, "==>backsql_db_destroy()\n" );
137
138	backsql_free_db_env( bi );
139	ldap_pvt_thread_mutex_destroy( &bi->sql_dbconn_mutex );
140	backsql_destroy_schema_map( bi );
141	ldap_pvt_thread_mutex_destroy( &bi->sql_schema_mutex );
142
143	if ( bi->sql_dbname ) {
144		ch_free( bi->sql_dbname );
145	}
146	if ( bi->sql_dbuser ) {
147		ch_free( bi->sql_dbuser );
148	}
149	if ( bi->sql_dbpasswd ) {
150		ch_free( bi->sql_dbpasswd );
151	}
152	if ( bi->sql_dbhost ) {
153		ch_free( bi->sql_dbhost );
154	}
155	if ( bi->sql_upper_func.bv_val ) {
156		ch_free( bi->sql_upper_func.bv_val );
157		ch_free( bi->sql_upper_func_open.bv_val );
158		ch_free( bi->sql_upper_func_close.bv_val );
159	}
160	if ( bi->sql_concat_func ) {
161		ber_bvarray_free( bi->sql_concat_func );
162	}
163	if ( !BER_BVISNULL( &bi->sql_strcast_func ) ) {
164		ch_free( bi->sql_strcast_func.bv_val );
165	}
166	if ( !BER_BVISNULL( &bi->sql_children_cond ) ) {
167		ch_free( bi->sql_children_cond.bv_val );
168	}
169	if ( !BER_BVISNULL( &bi->sql_dn_match_cond ) ) {
170		ch_free( bi->sql_dn_match_cond.bv_val );
171	}
172	if ( !BER_BVISNULL( &bi->sql_subtree_cond ) ) {
173		ch_free( bi->sql_subtree_cond.bv_val );
174	}
175	if ( !BER_BVISNULL( &bi->sql_dn_oc_aliasing ) ) {
176		ch_free( bi->sql_dn_oc_aliasing.bv_val );
177	}
178	if ( bi->sql_oc_query ) {
179		ch_free( bi->sql_oc_query );
180	}
181	if ( bi->sql_at_query ) {
182		ch_free( bi->sql_at_query );
183	}
184	if ( bi->sql_id_query ) {
185		ch_free( bi->sql_id_query );
186	}
187	if ( bi->sql_has_children_query ) {
188		ch_free( bi->sql_has_children_query );
189	}
190	if ( bi->sql_insentry_stmt ) {
191		ch_free( bi->sql_insentry_stmt );
192	}
193	if ( bi->sql_delentry_stmt ) {
194		ch_free( bi->sql_delentry_stmt );
195	}
196	if ( bi->sql_renentry_stmt ) {
197		ch_free( bi->sql_renentry_stmt );
198	}
199	if ( bi->sql_delobjclasses_stmt ) {
200		ch_free( bi->sql_delobjclasses_stmt );
201	}
202	if ( !BER_BVISNULL( &bi->sql_aliasing ) ) {
203		ch_free( bi->sql_aliasing.bv_val );
204	}
205	if ( !BER_BVISNULL( &bi->sql_aliasing_quote ) ) {
206		ch_free( bi->sql_aliasing_quote.bv_val );
207	}
208
209	if ( bi->sql_anlist ) {
210		int	i;
211
212		for ( i = 0; !BER_BVISNULL( &bi->sql_anlist[ i ].an_name ); i++ )
213		{
214			ch_free( bi->sql_anlist[ i ].an_name.bv_val );
215		}
216		ch_free( bi->sql_anlist );
217	}
218
219	if ( bi->sql_baseObject ) {
220		entry_free( bi->sql_baseObject );
221	}
222
223	ch_free( bi );
224
225	Debug( LDAP_DEBUG_TRACE, "<==backsql_db_destroy()\n" );
226	return 0;
227}
228
229int
230backsql_db_open(
231	BackendDB 	*bd,
232	ConfigReply	*cr )
233{
234	backsql_info 	*bi = (backsql_info*)bd->be_private;
235	struct berbuf	bb = BB_NULL;
236
237	Connection	conn = { 0 };
238	OperationBuffer opbuf;
239	Operation*	op;
240	SQLHDBC		dbh = SQL_NULL_HDBC;
241	void		*thrctx = ldap_pvt_thread_pool_context();
242
243	Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): "
244		"testing RDBMS connection\n" );
245	if ( bi->sql_dbname == NULL ) {
246		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
247			"datasource name not specified "
248			"(use \"dbname\" directive in slapd.conf)\n" );
249		return 1;
250	}
251
252	if ( bi->sql_concat_func == NULL ) {
253		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
254			"concat func not specified (use \"concat_pattern\" "
255			"directive in slapd.conf)\n" );
256
257		if ( backsql_split_pattern( backsql_def_concat_func,
258				&bi->sql_concat_func, 2 ) ) {
259			Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
260				"unable to parse pattern \"%s\"",
261				backsql_def_concat_func );
262			return 1;
263		}
264	}
265
266	/*
267	 * see back-sql.h for default values
268	 */
269	if ( BER_BVISNULL( &bi->sql_aliasing ) ) {
270		ber_str2bv( BACKSQL_ALIASING,
271			STRLENOF( BACKSQL_ALIASING ),
272			1, &bi->sql_aliasing );
273	}
274
275	if ( BER_BVISNULL( &bi->sql_aliasing_quote ) ) {
276		ber_str2bv( BACKSQL_ALIASING_QUOTE,
277			STRLENOF( BACKSQL_ALIASING_QUOTE ),
278			1, &bi->sql_aliasing_quote );
279	}
280
281	/*
282	 * Prepare cast string as required
283	 */
284	if ( bi->sql_upper_func.bv_val ) {
285		char buf[1024];
286
287		if ( BACKSQL_UPPER_NEEDS_CAST( bi ) ) {
288			snprintf( buf, sizeof( buf ),
289				"%s(cast (" /* ? as varchar(%d))) */ ,
290				bi->sql_upper_func.bv_val );
291			ber_str2bv( buf, 0, 1, &bi->sql_upper_func_open );
292
293			snprintf( buf, sizeof( buf ),
294				/* (cast(? */ " as varchar(%d)))",
295				BACKSQL_MAX_DN_LEN );
296			ber_str2bv( buf, 0, 1, &bi->sql_upper_func_close );
297
298		} else {
299			snprintf( buf, sizeof( buf ), "%s(" /* ?) */ ,
300					bi->sql_upper_func.bv_val );
301			ber_str2bv( buf, 0, 1, &bi->sql_upper_func_open );
302
303			ber_str2bv( /* (? */ ")", 0, 1, &bi->sql_upper_func_close );
304		}
305	}
306
307	/* normalize filter values only if necessary */
308	bi->sql_caseIgnoreMatch = mr_find( "caseIgnoreMatch" );
309	assert( bi->sql_caseIgnoreMatch != NULL );
310
311	bi->sql_telephoneNumberMatch = mr_find( "telephoneNumberMatch" );
312	assert( bi->sql_telephoneNumberMatch != NULL );
313
314	if ( bi->sql_dbuser == NULL ) {
315		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
316			"user name not specified "
317			"(use \"dbuser\" directive in slapd.conf)\n" );
318		return 1;
319	}
320
321	if ( BER_BVISNULL( &bi->sql_subtree_cond ) ) {
322		/*
323		 * Prepare concat function for subtree search condition
324		 */
325		struct berval	concat;
326		struct berval	values[] = {
327			BER_BVC( "'%'" ),
328			BER_BVC( "?" ),
329			BER_BVNULL
330		};
331		struct berbuf	bb = BB_NULL;
332
333		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
334			"subtree search SQL condition not specified "
335			"(use \"subtree_cond\" directive in slapd.conf); "
336			"preparing default\n" );
337
338		if ( backsql_prepare_pattern( bi->sql_concat_func, values,
339				&concat ) ) {
340			Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
341				"unable to prepare CONCAT pattern for subtree search" );
342			return 1;
343		}
344
345		if ( bi->sql_upper_func.bv_val ) {
346
347			/*
348			 * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%',?))
349			 */
350
351			backsql_strfcat_x( &bb, NULL, "blbbb",
352					&bi->sql_upper_func,
353					(ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ),
354						"(ldap_entries.dn) LIKE ",
355					&bi->sql_upper_func_open,
356					&concat,
357					&bi->sql_upper_func_close );
358
359		} else {
360
361			/*
362			 * ldap_entries.dn LIKE CONCAT('%',?)
363			 */
364
365			backsql_strfcat_x( &bb, NULL, "lb",
366					(ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ),
367						"ldap_entries.dn LIKE ",
368					&concat );
369		}
370
371		ch_free( concat.bv_val );
372
373		bi->sql_subtree_cond = bb.bb_val;
374
375		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
376			"setting \"%s\" as default \"subtree_cond\"\n",
377			bi->sql_subtree_cond.bv_val );
378	}
379
380	if ( bi->sql_children_cond.bv_val == NULL ) {
381		/*
382		 * Prepare concat function for children search condition
383		 */
384		struct berval	concat;
385		struct berval	values[] = {
386			BER_BVC( "'%,'" ),
387			BER_BVC( "?" ),
388			BER_BVNULL
389		};
390		struct berbuf	bb = BB_NULL;
391
392		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
393			"children search SQL condition not specified "
394			"(use \"children_cond\" directive in slapd.conf); "
395			"preparing default\n" );
396
397		if ( backsql_prepare_pattern( bi->sql_concat_func, values,
398				&concat ) ) {
399			Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
400				"unable to prepare CONCAT pattern for children search" );
401			return 1;
402		}
403
404		if ( bi->sql_upper_func.bv_val ) {
405
406			/*
407			 * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?))
408			 */
409
410			backsql_strfcat_x( &bb, NULL, "blbbb",
411					&bi->sql_upper_func,
412					(ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ),
413						"(ldap_entries.dn) LIKE ",
414					&bi->sql_upper_func_open,
415					&concat,
416					&bi->sql_upper_func_close );
417
418		} else {
419
420			/*
421			 * ldap_entries.dn LIKE CONCAT('%,',?)
422			 */
423
424			backsql_strfcat_x( &bb, NULL, "lb",
425					(ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ),
426						"ldap_entries.dn LIKE ",
427					&concat );
428		}
429
430		ch_free( concat.bv_val );
431
432		bi->sql_children_cond = bb.bb_val;
433
434		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
435			"setting \"%s\" as default \"children_cond\"\n",
436			bi->sql_children_cond.bv_val );
437	}
438
439	if ( bi->sql_dn_match_cond.bv_val == NULL ) {
440		/*
441		 * Prepare concat function for dn match search condition
442		 */
443		struct berbuf	bb = BB_NULL;
444
445		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
446			"DN match search SQL condition not specified "
447			"(use \"dn_match_cond\" directive in slapd.conf); "
448			"preparing default\n" );
449
450		if ( bi->sql_upper_func.bv_val ) {
451
452			/*
453			 * UPPER(ldap_entries.dn)=?
454			 */
455
456			backsql_strfcat_x( &bb, NULL, "blbcb",
457					&bi->sql_upper_func,
458					(ber_len_t)STRLENOF( "(ldap_entries.dn)=" ),
459						"(ldap_entries.dn)=",
460					&bi->sql_upper_func_open,
461					'?',
462					&bi->sql_upper_func_close );
463
464		} else {
465
466			/*
467			 * ldap_entries.dn=?
468			 */
469
470			backsql_strfcat_x( &bb, NULL, "l",
471					(ber_len_t)STRLENOF( "ldap_entries.dn=?" ),
472						"ldap_entries.dn=?" );
473		}
474
475		bi->sql_dn_match_cond = bb.bb_val;
476
477		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
478			"setting \"%s\" as default \"dn_match_cond\"\n",
479			bi->sql_dn_match_cond.bv_val );
480	}
481
482	if ( bi->sql_oc_query == NULL ) {
483		if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
484			bi->sql_oc_query =
485				ch_strdup( backsql_def_needs_select_oc_query );
486
487		} else {
488			bi->sql_oc_query = ch_strdup( backsql_def_oc_query );
489		}
490
491		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
492			"objectclass mapping SQL statement not specified "
493			"(use \"oc_query\" directive in slapd.conf)\n" );
494		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
495			"setting \"%s\" by default\n", bi->sql_oc_query );
496	}
497
498	if ( bi->sql_at_query == NULL ) {
499		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
500			"attribute mapping SQL statement not specified "
501			"(use \"at_query\" directive in slapd.conf)\n" );
502		Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
503			"setting \"%s\" by default\n",
504			backsql_def_at_query );
505		bi->sql_at_query = ch_strdup( backsql_def_at_query );
506	}
507
508	if ( bi->sql_insentry_stmt == NULL ) {
509		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
510			"entry insertion SQL statement not specified "
511			"(use \"insentry_stmt\" directive in slapd.conf)\n" );
512		Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
513			"setting \"%s\" by default\n",
514			backsql_def_insentry_stmt );
515		bi->sql_insentry_stmt = ch_strdup( backsql_def_insentry_stmt );
516	}
517
518	if ( bi->sql_delentry_stmt == NULL ) {
519		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
520			"entry deletion SQL statement not specified "
521			"(use \"delentry_stmt\" directive in slapd.conf)\n" );
522		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
523			"setting \"%s\" by default\n",
524			backsql_def_delentry_stmt );
525		bi->sql_delentry_stmt = ch_strdup( backsql_def_delentry_stmt );
526	}
527
528	if ( bi->sql_renentry_stmt == NULL ) {
529		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
530			"entry deletion SQL statement not specified "
531			"(use \"renentry_stmt\" directive in slapd.conf)\n" );
532		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
533			"setting \"%s\" by default\n",
534			backsql_def_renentry_stmt );
535		bi->sql_renentry_stmt = ch_strdup( backsql_def_renentry_stmt );
536	}
537
538	if ( bi->sql_delobjclasses_stmt == NULL ) {
539		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
540			"objclasses deletion SQL statement not specified "
541			"(use \"delobjclasses_stmt\" directive in slapd.conf)\n" );
542		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
543			"setting \"%s\" by default\n",
544			backsql_def_delobjclasses_stmt );
545		bi->sql_delobjclasses_stmt = ch_strdup( backsql_def_delobjclasses_stmt );
546	}
547
548	/* This should just be to force schema loading */
549	connection_fake_init2( &conn, &opbuf, thrctx, 0 );
550	op = &opbuf.ob_op;
551	op->o_bd = bd;
552	if ( backsql_get_db_conn( op, &dbh ) != LDAP_SUCCESS ) {
553		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
554			"connection failed, exiting\n" );
555		return 1;
556	}
557	if ( backsql_load_schema_map( bi, dbh ) != LDAP_SUCCESS ) {
558		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
559			"schema mapping failed, exiting\n" );
560		return 1;
561	}
562	if ( backsql_free_db_conn( op, dbh ) != SQL_SUCCESS ) {
563		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
564			"connection free failed\n" );
565	}
566	if ( !BACKSQL_SCHEMA_LOADED( bi ) ) {
567		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
568			"test failed, schema map not loaded - exiting\n" );
569		return 1;
570	}
571
572	/*
573	 * Prepare ID selection query
574	 */
575	if ( bi->sql_id_query == NULL ) {
576		/* no custom id_query provided */
577		if ( bi->sql_upper_func.bv_val == NULL ) {
578			backsql_strcat_x( &bb, NULL, backsql_id_query, "dn=?", NULL );
579
580		} else {
581			if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
582				backsql_strcat_x( &bb, NULL, backsql_id_query,
583						"dn_ru=?", NULL );
584			} else {
585				if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
586					backsql_strfcat_x( &bb, NULL, "sbl",
587							backsql_id_query,
588							&bi->sql_upper_func,
589							(ber_len_t)STRLENOF( "(dn)=?" ), "(dn)=?" );
590				} else {
591					backsql_strfcat_x( &bb, NULL, "sblbcb",
592							backsql_id_query,
593							&bi->sql_upper_func,
594							(ber_len_t)STRLENOF( "(dn)=" ), "(dn)=",
595							&bi->sql_upper_func_open,
596							'?',
597							&bi->sql_upper_func_close );
598				}
599			}
600		}
601		bi->sql_id_query = bb.bb_val.bv_val;
602	}
603
604	/*
605	 * Prepare children count query
606	 */
607	BER_BVZERO( &bb.bb_val );
608	bb.bb_len = 0;
609	backsql_strfcat_x( &bb, NULL, "sbsb",
610			"SELECT COUNT(distinct subordinates.id) "
611			"FROM ldap_entries,ldap_entries ",
612			&bi->sql_aliasing, "subordinates "
613			"WHERE subordinates.parent=ldap_entries.id AND ",
614			&bi->sql_dn_match_cond );
615	bi->sql_has_children_query = bb.bb_val.bv_val;
616
617	/*
618	 * Prepare DN and objectClass aliasing bit of query
619	 */
620	BER_BVZERO( &bb.bb_val );
621	bb.bb_len = 0;
622	backsql_strfcat_x( &bb, NULL, "sbbsbsbbsb",
623			" ", &bi->sql_aliasing, &bi->sql_aliasing_quote,
624			"objectClass", &bi->sql_aliasing_quote,
625			",ldap_entries.dn ", &bi->sql_aliasing,
626			&bi->sql_aliasing_quote, "dn", &bi->sql_aliasing_quote );
627	bi->sql_dn_oc_aliasing = bb.bb_val;
628
629	/* should never happen! */
630	assert( bd->be_nsuffix != NULL );
631
632	if ( BER_BVISNULL( &bd->be_nsuffix[ 1 ] ) ) {
633		/* enable if only one suffix is defined */
634		bi->sql_flags |= BSQLF_USE_SUBTREE_SHORTCUT;
635	}
636
637	bi->sql_flags |= BSQLF_CHECK_SCHEMA;
638
639	Debug( LDAP_DEBUG_TRACE, "<==backsql_db_open(): "
640		"test succeeded, schema map loaded\n" );
641	return 0;
642}
643
644int
645backsql_db_close(
646	BackendDB	*bd,
647	ConfigReply	*cr )
648{
649	backsql_info 	*bi = (backsql_info*)bd->be_private;
650
651	Debug( LDAP_DEBUG_TRACE, "==>backsql_db_close()\n" );
652
653	backsql_conn_destroy( bi );
654
655	Debug( LDAP_DEBUG_TRACE, "<==backsql_db_close()\n" );
656
657	return 0;
658}
659
660#if SLAPD_SQL == SLAPD_MOD_DYNAMIC
661
662/* conditionally define the init_module() function */
663SLAP_BACKEND_INIT_MODULE( sql )
664
665#endif /* SLAPD_SQL == SLAPD_MOD_DYNAMIC */
666
667