openldap/servers/slapd/back-sql/init.c
Pierangelo Masarati fbc11bd16a - added the capability to filter based on hasSubordinate attribute
to back-bdb, back-ldbm and back-sql (the latter with limitations);
- added handling of ":dn" attributes to extended rfc2254 filters
  and to matched value filter
- altered the behavior of get_mra() when a matching rule is given:
  now it checks whether it is compatible with the attribute syntax
  and, in case it is, the given mr is used.  In case of no type,
  the check is delayed when filtering
2002-08-29 10:55:48 +00:00

488 lines
12 KiB
C

/*
* Copyright 1999, Dmitry Kovalev <mit@openldap.org>, All rights reserved.
*
* Redistribution and use in source and binary forms are permitted only
* as authorized by the OpenLDAP Public License. A copy of this
* license is available at http://www.OpenLDAP.org/license.html or
* in file LICENSE in the top-level directory of the distribution.
*/
#include "portable.h"
#ifdef SLAPD_SQL
#include <stdio.h>
#include <sys/types.h>
#include "slap.h"
#include "ldap_pvt.h"
#include "back-sql.h"
#include "sql-wrap.h"
#include "schema-map.h"
#include "util.h"
#ifdef SLAPD_SQL_DYNAMIC
int
backsql_LTX_init_module(
int argc,
char *argv[] )
{
BackendInfo bi;
memset( &bi, '\0', sizeof( bi ) );
bi.bi_type = "sql";
bi.bi_init = backbacksql_initialize;
backend_add( &bi );
return 0;
}
#endif /* SLAPD_SHELL_DYNAMIC */
int
sql_back_initialize(
BackendInfo *bi )
{
static char *controls[] = {
#ifdef LDAP_CONTROL_NOOP
LDAP_CONTROL_NOOP,
#endif
#ifdef LDAP_CONTROL_VALUESRETURNFILTER
LDAP_CONTROL_VALUESRETURNFILTER,
#endif
NULL
};
bi->bi_controls = controls;
Debug( LDAP_DEBUG_TRACE,"==>backsql_initialize()\n", 0, 0, 0 );
bi->bi_open = 0;
bi->bi_config = 0;
bi->bi_close = 0;
bi->bi_destroy = 0;
bi->bi_db_init = backsql_db_init;
bi->bi_db_config = backsql_db_config;
bi->bi_db_open = backsql_db_open;
bi->bi_db_close = backsql_db_close;
bi->bi_db_destroy = backsql_db_destroy;
#ifdef BACKSQL_ALL_DONE
bi->bi_op_abandon = backsql_abandon;
bi->bi_op_compare = backsql_compare;
#else
bi->bi_op_abandon = 0;
bi->bi_op_compare = 0;
#endif
bi->bi_op_bind = backsql_bind;
bi->bi_op_unbind = backsql_unbind;
bi->bi_op_search = backsql_search;
bi->bi_op_modify = backsql_modify;
bi->bi_op_modrdn = backsql_modrdn;
bi->bi_op_add = backsql_add;
bi->bi_op_delete = backsql_delete;
bi->bi_acl_group = 0;
bi->bi_acl_attribute = 0;
bi->bi_chk_referrals = 0;
bi->bi_operational = backsql_operational;
bi->bi_connection_init = 0;
bi->bi_connection_destroy = backsql_connection_destroy;
Debug( LDAP_DEBUG_TRACE,"<==backsql_initialize()\n", 0, 0, 0 );
return 0;
}
int
backsql_destroy(
BackendInfo *bi )
{
Debug( LDAP_DEBUG_TRACE, "==>backsql_destroy()\n", 0, 0, 0 );
Debug( LDAP_DEBUG_TRACE, "<==backsql_destroy()\n", 0, 0, 0 );
return 0;
}
int
backsql_db_init(
BackendDB *bd )
{
backsql_info *si;
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_init()\n", 0, 0, 0 );
si = (backsql_info *)ch_calloc( 1, sizeof( backsql_info ) );
memset( si, '\0', sizeof( backsql_info ) );
ldap_pvt_thread_mutex_init( &si->dbconn_mutex );
ldap_pvt_thread_mutex_init( &si->schema_mutex );
backsql_init_db_env( si );
bd->be_private = si;
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_init()\n", 0, 0, 0 );
return 0;
}
int
backsql_db_destroy(
BackendDB *bd )
{
backsql_info *si = (backsql_info*)bd->be_private;
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_destroy()\n", 0, 0, 0 );
ldap_pvt_thread_mutex_lock( &si->dbconn_mutex );
backsql_free_db_env( si );
ldap_pvt_thread_mutex_unlock( &si->dbconn_mutex );
ldap_pvt_thread_mutex_destroy( &si->dbconn_mutex );
ldap_pvt_thread_mutex_lock( &si->schema_mutex );
backsql_destroy_schema_map( si );
ldap_pvt_thread_mutex_unlock( &si->schema_mutex );
ldap_pvt_thread_mutex_destroy( &si->schema_mutex );
free( si->dbname );
free( si->dbuser );
if ( si->dbpasswd ) {
free( si->dbpasswd );
}
if ( si->dbhost ) {
free( si->dbhost );
}
if ( si->upper_func.bv_val ) {
free( si->upper_func.bv_val );
free( si->upper_func_open.bv_val );
free( si->upper_func_close.bv_val );
}
free( si->subtree_cond.bv_val );
free( si->oc_query );
free( si->at_query );
free( si->insentry_query );
free( si->delentry_query );
free( si );
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_destroy()\n", 0, 0, 0 );
return 0;
}
int
backsql_db_open(
BackendDB *bd )
{
backsql_info *si = (backsql_info*)bd->be_private;
Connection tmp;
SQLHDBC dbh;
ber_len_t idq_len;
struct berval bv;
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): "
"testing RDBMS connection\n", 0, 0, 0 );
if ( si->dbname == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"datasource name not specified "
"(use \"dbname\" directive in slapd.conf)\n", 0, 0, 0 );
return 1;
}
if ( si->concat_func == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"concat func not specified (use \"concat_pattern\" "
"directive in slapd.conf)\n", 0, 0, 0 );
if ( backsql_split_pattern( backsql_def_concat_func,
&si->concat_func, 2 ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"unable to parse pattern '%s'",
backsql_def_concat_func, 0, 0 );
return 1;
}
}
/*
* Prepare cast string as required
*/
if ( si->upper_func.bv_val ) {
char buf[1024];
if ( BACKSQL_UPPER_NEEDS_CAST( si ) ) {
snprintf( buf, sizeof( buf ),
"%s(cast (" /* ? as varchar(%d))) */ ,
si->upper_func.bv_val );
ber_str2bv( buf, 0, 1, &si->upper_func_open );
snprintf( buf, sizeof( buf ),
/* (cast(? */ " as varchar(%d)))",
BACKSQL_MAX_DN_LEN );
ber_str2bv( buf, 0, 1, &si->upper_func_close );
} else {
snprintf( buf, sizeof( buf ), "%s(" /* ?) */ ,
si->upper_func.bv_val );
ber_str2bv( buf, 0, 1, &si->upper_func_open );
ber_str2bv( /* (? */ ")", 0, 1, &si->upper_func_close );
}
}
if ( si->dbuser == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"user name not specified "
"(use \"dbuser\" directive in slapd.conf)\n", 0, 0, 0 );
return 1;
}
if ( si->subtree_cond.bv_val == NULL ) {
/*
* Prepare concat function for subtree search condition
*/
struct berval concat;
ber_len_t len = 0;
struct berval values[] = {
{ sizeof( "'%'" ) - 1, "'%'" },
{ sizeof( "?" ) - 1, "?" },
{ 0, NULL }
};
if ( backsql_prepare_pattern( si->concat_func, values,
&concat ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"unable to prepare CONCAT pattern", 0, 0, 0 );
return 1;
}
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"subtree search SQL condition not specified "
"(use \"subtree_cond\" directive in slapd.conf)\n",
0, 0, 0);
si->subtree_cond.bv_val = NULL;
si->subtree_cond.bv_len = 0;
if ( si->upper_func.bv_val ) {
/*
* UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%',?))
*/
backsql_strfcat( &si->subtree_cond, &len, "blbbb",
&si->upper_func,
(ber_len_t)sizeof( "(ldap_entries.dn) LIKE " ) - 1,
"(ldap_entries.dn) LIKE ",
&si->upper_func_open,
&concat,
&si->upper_func_close );
} else {
/*
* ldap_entries.dn LIKE CONCAT('%',?)
*/
backsql_strfcat( &si->subtree_cond, &len, "lb",
(ber_len_t)sizeof( "ldap_entries.dn LIKE " ) - 1,
"ldap_entries.dn LIKE ",
&concat );
}
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting '%s' as default\n",
si->subtree_cond.bv_val, 0, 0 );
}
if ( si->children_cond.bv_val == NULL ) {
/*
* Prepare concat function for children search condition
*/
struct berval concat;
ber_len_t len = 0;
struct berval values[] = {
{ sizeof( "'%,'" ) - 1, "'%,'" },
{ sizeof( "?" ) - 1, "?" },
{ 0, NULL }
};
if ( backsql_prepare_pattern( si->concat_func, values,
&concat ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"unable to prepare CONCAT pattern", 0, 0, 0 );
return 1;
}
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"children search SQL condition not specified "
"(use \"children_cond\" directive in slapd.conf)\n",
0, 0, 0);
si->children_cond.bv_val = NULL;
si->children_cond.bv_len = 0;
if ( si->upper_func.bv_val ) {
/*
* UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?))
*/
backsql_strfcat( &si->children_cond, &len, "blbbb",
&si->upper_func,
(ber_len_t)sizeof( "(ldap_entries.dn) LIKE " ) - 1,
"(ldap_entries.dn) LIKE ",
&si->upper_func_open,
&concat,
&si->upper_func_close );
} else {
/*
* ldap_entries.dn LIKE CONCAT('%,',?)
*/
backsql_strfcat( &si->children_cond, &len, "lb",
(ber_len_t)sizeof( "ldap_entries.dn LIKE " ) - 1,
"ldap_entries.dn LIKE ",
&concat );
}
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting '%s' as default\n",
si->children_cond.bv_val, 0, 0 );
}
if ( si->oc_query == NULL ) {
if ( BACKSQL_CREATE_NEEDS_SELECT( si ) ) {
si->oc_query =
ch_strdup( backsql_def_needs_select_oc_query );
} else {
si->oc_query = ch_strdup( backsql_def_oc_query );
}
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"objectclass mapping SQL statement not specified "
"(use \"oc_query\" directive in slapd.conf)\n",
0, 0, 0 );
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting '%s' by default\n", si->oc_query, 0, 0 );
}
if ( si->at_query == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"attribute mapping SQL statement not specified "
"(use \"at_query\" directive in slapd.conf)\n",
0, 0, 0 );
Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting '%s' by default\n",
backsql_def_at_query, 0, 0 );
si->at_query = ch_strdup( backsql_def_at_query );
}
if ( si->insentry_query == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"entry insertion SQL statement not specified "
"(use \"insentry_query\" directive in slapd.conf)\n",
0, 0, 0 );
Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting '%s' by default\n",
backsql_def_insentry_query, 0, 0 );
si->insentry_query = ch_strdup( backsql_def_insentry_query );
}
if ( si->delentry_query == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"entry deletion SQL statement not specified "
"(use \"delentry_query\" directive in slapd.conf)\n",
0, 0, 0 );
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting '%s' by default\n",
backsql_def_delentry_query, 0, 0 );
si->delentry_query = ch_strdup( backsql_def_delentry_query );
}
tmp.c_connid =- 1;
if ( backsql_get_db_conn( bd, &tmp, &dbh ) != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"connection failed, exiting\n", 0, 0, 0 );
return 1;
}
/*
* Prepare ID selection query
*/
si->id_query = NULL;
idq_len = 0;
bv.bv_val = NULL;
bv.bv_len = 0;
if ( si->upper_func.bv_val == NULL ) {
backsql_strcat( &bv, &idq_len, backsql_id_query,
"dn=?", NULL );
} else {
if ( BACKSQL_HAS_LDAPINFO_DN_RU( si ) ) {
backsql_strcat( &bv, &idq_len, backsql_id_query,
"dn_ru=?", NULL );
} else {
if ( BACKSQL_USE_REVERSE_DN( si ) ) {
backsql_strfcat( &bv, &idq_len, "sbl",
backsql_id_query,
&si->upper_func,
(ber_len_t)sizeof( "(dn)=?" ) - 1, "(dn)=?" );
} else {
backsql_strfcat( &bv, &idq_len, "sblbcb",
backsql_id_query,
&si->upper_func,
(ber_len_t)sizeof( "(dn)=" ) - 1, "(dn)=",
&si->upper_func_open,
'?',
&si->upper_func_close );
}
}
}
si->id_query = bv.bv_val;
/*
* Prepare children ID selection query
*/
si->has_children_query = NULL;
idq_len = 0;
bv.bv_val = NULL;
bv.bv_len = 0;
backsql_strfcat( &bv, &idq_len, "sb",
"select count(*) from ldap_entries where ",
&si->children_cond );
si->has_children_query = bv.bv_val;
backsql_free_db_conn( bd, &tmp );
if ( !BACKSQL_SCHEMA_LOADED( si ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"test failed, schema map not loaded - exiting\n",
0, 0, 0 );
return 1;
}
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_open(): "
"test succeeded, schema map loaded\n", 0, 0, 0 );
return 0;
}
int
backsql_db_close(
BackendDB *bd )
{
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_close()\n", 0, 0, 0 );
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_close()\n", 0, 0, 0 );
return 0;
}
int
backsql_connection_destroy(
BackendDB *be,
Connection *conn )
{
Debug( LDAP_DEBUG_TRACE, "==>backsql_connection_destroy()\n", 0, 0, 0 );
backsql_free_db_conn( be, conn );
Debug( LDAP_DEBUG_TRACE, "<==backsql_connection_destroy()\n", 0, 0, 0 );
return 0;
}
#endif /* SLAPD_SQL */