mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-24 16:49:39 -05:00
for further mucking with data. This can be of use in ill situations where not all the required massaging can be done on data with SQL by means of stored procedures, but overlays are called too early and cannot be used to make data non LDAP compliant. - only support for bidirectional DN mucking is provided right now - support for other values mucking is planned - write is not completely tested yet - the API could change quite often; don't rely too much on it other cleanup has been added.
735 lines
20 KiB
C
735 lines
20 KiB
C
/* $OpenLDAP$ */
|
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
*
|
|
* Copyright 1999-2004 The OpenLDAP Foundation.
|
|
* Portions Copyright 1999 Dmitry Kovalev.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted only as authorized by the OpenLDAP
|
|
* Public License.
|
|
*
|
|
* A copy of this license is available in the file LICENSE in the
|
|
* top-level directory of the distribution or, alternatively, at
|
|
* <http://www.OpenLDAP.org/license.html>.
|
|
*/
|
|
/* ACKNOWLEDGEMENTS:
|
|
* This work was initially developed by Dmitry Kovalev for inclusion
|
|
* by OpenLDAP Software.
|
|
*/
|
|
|
|
#include "portable.h"
|
|
|
|
#ifdef SLAPD_SQL
|
|
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include "ac/string.h"
|
|
|
|
#include "slap.h"
|
|
#include "lber_pvt.h"
|
|
#include "ldap_pvt.h"
|
|
#include "proto-sql.h"
|
|
|
|
#define BACKSQL_DUPLICATE (-1)
|
|
|
|
/*
|
|
* Uses the pointer to the ObjectClass structure
|
|
*/
|
|
static int
|
|
backsql_cmp_oc( const void *v_m1, const void *v_m2 )
|
|
{
|
|
const backsql_oc_map_rec *m1 = v_m1, *m2 = v_m2;
|
|
|
|
return SLAP_PTRCMP( m1->bom_oc, m2->bom_oc );
|
|
}
|
|
|
|
static int
|
|
backsql_cmp_oc_id( const void *v_m1, const void *v_m2 )
|
|
{
|
|
const backsql_oc_map_rec *m1 = v_m1, *m2 = v_m2;
|
|
|
|
return ( m1->bom_id < m2->bom_id ? -1 : ( m1->bom_id > m2->bom_id ? 1 : 0 ) );
|
|
}
|
|
|
|
/*
|
|
* Uses the pointer to the AttributeDescription structure
|
|
*/
|
|
static int
|
|
backsql_cmp_attr( const void *v_m1, const void *v_m2 )
|
|
{
|
|
const backsql_at_map_rec *m1 = v_m1, *m2 = v_m2;
|
|
|
|
return SLAP_PTRCMP( m1->bam_ad, m2->bam_ad );
|
|
}
|
|
|
|
int
|
|
backsql_dup_attr( void *v_m1, void *v_m2 )
|
|
{
|
|
backsql_at_map_rec *m1 = v_m1, *m2 = v_m2;
|
|
|
|
assert( m1->bam_ad == m2->bam_ad );
|
|
|
|
for ( ; m1->bam_next ; m1 = m1->bam_next );
|
|
m1->bam_next = m2;
|
|
m2->bam_next = NULL;
|
|
|
|
return BACKSQL_DUPLICATE;
|
|
}
|
|
|
|
static int
|
|
backsql_make_attr_query(
|
|
backsql_oc_map_rec *oc_map,
|
|
backsql_at_map_rec *at_map )
|
|
{
|
|
struct berbuf bb = BB_NULL;
|
|
|
|
backsql_strfcat( &bb, "lblblblbcbl",
|
|
(ber_len_t)sizeof( "SELECT " ) - 1, "SELECT ",
|
|
&at_map->bam_sel_expr,
|
|
(ber_len_t)sizeof( " AS " ) - 1, " AS ",
|
|
&at_map->bam_ad->ad_cname,
|
|
(ber_len_t)sizeof( " FROM " ) - 1, " FROM ",
|
|
&at_map->bam_from_tbls,
|
|
(ber_len_t)sizeof( " WHERE " ) - 1, " WHERE ",
|
|
&oc_map->bom_keytbl,
|
|
'.',
|
|
&oc_map->bom_keycol,
|
|
(ber_len_t)sizeof( "=?" ) - 1, "=?" );
|
|
|
|
if ( at_map->bam_join_where.bv_val != NULL ) {
|
|
backsql_strfcat( &bb, "lb",
|
|
(ber_len_t)sizeof( " AND ") - 1, " AND ",
|
|
&at_map->bam_join_where );
|
|
}
|
|
|
|
at_map->bam_query = bb.bb_val.bv_val;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
backsql_add_sysmaps( backsql_oc_map_rec *oc_map )
|
|
{
|
|
backsql_at_map_rec *at_map;
|
|
char s[] = "+9223372036854775807L";
|
|
ber_len_t slen;
|
|
struct berbuf bb;
|
|
|
|
|
|
snprintf( s, sizeof( s ), "%ld", oc_map->bom_id );
|
|
slen = strlen( s );
|
|
|
|
at_map = (backsql_at_map_rec *)ch_calloc(1,
|
|
sizeof( backsql_at_map_rec ) );
|
|
at_map->bam_ad = slap_schema.si_ad_objectClass;
|
|
ber_str2bv( "ldap_entry_objclasses.oc_name", 0, 1,
|
|
&at_map->bam_sel_expr );
|
|
ber_str2bv( "ldap_entry_objclasses,ldap_entries", 0, 1,
|
|
&at_map->bam_from_tbls );
|
|
|
|
bb.bb_len = at_map->bam_from_tbls.bv_len + 1;
|
|
bb.bb_val = at_map->bam_from_tbls;
|
|
backsql_merge_from_clause( &bb, &oc_map->bom_keytbl );
|
|
at_map->bam_from_tbls = bb.bb_val;
|
|
|
|
bb.bb_val.bv_val = NULL;
|
|
bb.bb_val.bv_len = 0;
|
|
bb.bb_len = 0;
|
|
backsql_strfcat( &bb, "lbcbll",
|
|
(ber_len_t)sizeof( "ldap_entries.id=ldap_entry_objclasses.entry_id and ldap_entries.keyval=" ) - 1,
|
|
"ldap_entries.id=ldap_entry_objclasses.entry_id and ldap_entries.keyval=",
|
|
&oc_map->bom_keytbl,
|
|
'.',
|
|
&oc_map->bom_keycol,
|
|
(ber_len_t)sizeof( " and ldap_entries.oc_map_id=" ) - 1,
|
|
" and ldap_entries.oc_map_id=",
|
|
slen, s );
|
|
|
|
at_map->bam_oc = oc_map->bom_oc;
|
|
at_map->bam_join_where = bb.bb_val;
|
|
at_map->bam_add_proc = NULL;
|
|
at_map->bam_delete_proc = NULL;
|
|
at_map->bam_param_order = 0;
|
|
at_map->bam_expect_return = 0;
|
|
at_map->bam_next = NULL;
|
|
|
|
backsql_make_attr_query( oc_map, at_map );
|
|
if ( avl_insert( &oc_map->bom_attrs, at_map, backsql_cmp_attr, backsql_dup_attr ) == BACKSQL_DUPLICATE ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_add_sysmaps(): "
|
|
"duplicate attribute \"%s\" in objectClass \"%s\" map\n",
|
|
at_map->bam_ad->ad_cname.bv_val,
|
|
oc_map->bom_oc->soc_cname.bv_val, 0 );
|
|
}
|
|
|
|
at_map = (backsql_at_map_rec *)ch_calloc( 1,
|
|
sizeof( backsql_at_map_rec ) );
|
|
at_map->bam_ad = slap_schema.si_ad_ref;
|
|
ber_str2bv( "ldap_referrals.url", 0, 1, &at_map->bam_sel_expr );
|
|
ber_str2bv( "ldap_referrals,ldap_entries", 0, 1, &at_map->bam_from_tbls );
|
|
|
|
bb.bb_val.bv_val = NULL;
|
|
bb.bb_val.bv_len = 0;
|
|
bb.bb_len = at_map->bam_from_tbls.bv_len + 1;
|
|
backsql_merge_from_clause( &bb, &oc_map->bom_keytbl );
|
|
at_map->bam_from_tbls = bb.bb_val;
|
|
|
|
bb.bb_val.bv_val = NULL;
|
|
bb.bb_val.bv_len = 0;
|
|
bb.bb_len = 0;
|
|
backsql_strfcat( &bb, "lbcbll",
|
|
(ber_len_t)sizeof( "ldap_entries.id=ldap_referrals.entry_id and ldap_entries.keyval=" ) - 1,
|
|
"ldap_entries.id=ldap_referrals.entry_id and ldap_entries.keyval=",
|
|
&oc_map->bom_keytbl,
|
|
'.',
|
|
&oc_map->bom_keycol,
|
|
(ber_len_t)sizeof( " and ldap_entries.oc_map_id=" ) - 1,
|
|
" and ldap_entries.oc_map_id=",
|
|
slen, s );
|
|
|
|
at_map->bam_oc = NULL;
|
|
at_map->bam_join_where = bb.bb_val;
|
|
at_map->bam_add_proc = NULL;
|
|
at_map->bam_delete_proc = NULL;
|
|
at_map->bam_param_order = 0;
|
|
at_map->bam_expect_return = 0;
|
|
at_map->bam_next = NULL;
|
|
|
|
backsql_make_attr_query( oc_map, at_map );
|
|
if ( avl_insert( &oc_map->bom_attrs, at_map, backsql_cmp_attr, backsql_dup_attr ) == BACKSQL_DUPLICATE ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_add_sysmaps(): "
|
|
"duplicate attribute \"%s\" in objectClass \"%s\" map\n",
|
|
at_map->bam_ad->ad_cname.bv_val,
|
|
oc_map->bom_oc->soc_cname.bv_val, 0 );
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
|
|
{
|
|
SQLHSTMT oc_sth, at_sth;
|
|
RETCODE rc;
|
|
BACKSQL_ROW_NTS oc_row, at_row;
|
|
unsigned long oc_id;
|
|
backsql_oc_map_rec *oc_map;
|
|
backsql_at_map_rec *at_map;
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "==>backsql_load_schema_map()\n", 0, 0, 0 );
|
|
|
|
/*
|
|
* TimesTen : See if the ldap_entries.dn_ru field exists in the schema
|
|
*/
|
|
if ( !BACKSQL_DONTCHECK_LDAPINFO_DN_RU( si ) ) {
|
|
rc = backsql_Prepare( dbh, &oc_sth,
|
|
backsql_check_dn_ru_query, 0 );
|
|
if ( rc == SQL_SUCCESS ) {
|
|
/* Yes, the field exists */
|
|
si->bsql_flags |= BSQLF_HAS_LDAPINFO_DN_RU;
|
|
Debug( LDAP_DEBUG_TRACE, "ldapinfo.dn_ru field exists "
|
|
"in the schema\n", 0, 0, 0 );
|
|
} else {
|
|
/* No such field exists */
|
|
si->bsql_flags &= ~BSQLF_HAS_LDAPINFO_DN_RU;
|
|
}
|
|
|
|
SQLFreeStmt( oc_sth, SQL_DROP );
|
|
}
|
|
|
|
|
|
rc = backsql_Prepare( dbh, &oc_sth, si->oc_query, 0 );
|
|
if ( rc != SQL_SUCCESS ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"error preparing oc_query: \"%s\"\n",
|
|
si->oc_query, 0, 0 );
|
|
backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
|
|
return LDAP_OTHER;
|
|
}
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): at_query \"%s\"\n",
|
|
si->at_query, 0, 0 );
|
|
|
|
rc = backsql_Prepare( dbh, &at_sth, si->at_query, 0 );
|
|
if ( rc != SQL_SUCCESS ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"error preparing at_query: \"%s\"\n",
|
|
si->at_query, 0, 0 );
|
|
backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
|
|
return LDAP_OTHER;
|
|
}
|
|
|
|
rc = backsql_BindParamID( at_sth, 1, &oc_id );
|
|
if ( rc != SQL_SUCCESS ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"error binding param for at_query: \n", 0, 0, 0 );
|
|
backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
|
|
return LDAP_OTHER;
|
|
}
|
|
|
|
rc = SQLExecute( oc_sth );
|
|
if ( rc != SQL_SUCCESS ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"error executing oc_query: \n", 0, 0, 0 );
|
|
backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
|
|
return LDAP_OTHER;
|
|
}
|
|
|
|
backsql_BindRowAsStrings( oc_sth, &oc_row );
|
|
rc = SQLFetch( oc_sth );
|
|
for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( oc_sth ) ) {
|
|
int colnum;
|
|
|
|
oc_map = (backsql_oc_map_rec *)ch_calloc( 1,
|
|
sizeof( backsql_oc_map_rec ) );
|
|
|
|
oc_map->bom_id = strtol( oc_row.cols[ 0 ], NULL, 0 );
|
|
|
|
oc_map->bom_oc = oc_find( oc_row.cols[ 1 ] );
|
|
if ( oc_map->bom_oc == NULL ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"objectClass \"%s\" is not defined in schema\n",
|
|
oc_row.cols[ 1 ], 0, 0 );
|
|
return LDAP_OTHER; /* undefined objectClass ? */
|
|
}
|
|
|
|
ber_str2bv( oc_row.cols[ 2 ], 0, 1, &oc_map->bom_keytbl );
|
|
ber_str2bv( oc_row.cols[ 3 ], 0, 1, &oc_map->bom_keycol );
|
|
oc_map->bom_create_proc = ( oc_row.value_len[ 4 ] < 0 ) ? NULL
|
|
: ch_strdup( oc_row.cols[ 4 ] );
|
|
|
|
colnum = 5;
|
|
if ( BACKSQL_CREATE_NEEDS_SELECT( si ) ) {
|
|
colnum = 6;
|
|
oc_map->bom_create_keyval = ( oc_row.value_len[ 5 ] < 0 )
|
|
? NULL : ch_strdup( oc_row.cols[ 5 ] );
|
|
}
|
|
oc_map->bom_delete_proc = ( oc_row.value_len[ colnum ] < 0 ) ? NULL
|
|
: ch_strdup( oc_row.cols[ colnum ] );
|
|
oc_map->bom_expect_return = strtol( oc_row.cols[ colnum + 1 ],
|
|
NULL, 0 );
|
|
|
|
/*
|
|
* FIXME: first attempt to check for offending
|
|
* instructions in {create|delete}_proc
|
|
*/
|
|
|
|
oc_map->bom_attrs = NULL;
|
|
if ( avl_insert( &si->oc_by_oc, oc_map, backsql_cmp_oc, avl_dup_error ) == -1 ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"duplicate objectClass \"%s\" in objectClass map\n",
|
|
oc_map->bom_oc->soc_cname.bv_val, 0, 0 );
|
|
return LDAP_OTHER;
|
|
}
|
|
if ( avl_insert( &si->oc_by_id, oc_map, backsql_cmp_oc_id, avl_dup_error ) == -1 ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"duplicate objectClass \"%s\" in objectClass by ID map\n",
|
|
oc_map->bom_oc->soc_cname.bv_val, 0, 0 );
|
|
return LDAP_OTHER;
|
|
}
|
|
oc_id = oc_map->bom_id;
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"objectClass \"%s\": keytbl=\"%s\" keycol=\"%s\"\n",
|
|
BACKSQL_OC_NAME( oc_map ),
|
|
oc_map->bom_keytbl.bv_val, oc_map->bom_keycol.bv_val );
|
|
if ( oc_map->bom_create_proc ) {
|
|
Debug( LDAP_DEBUG_TRACE, "create_proc=\"%s\"\n",
|
|
oc_map->bom_create_proc, 0, 0 );
|
|
}
|
|
if ( oc_map->bom_create_keyval ) {
|
|
Debug( LDAP_DEBUG_TRACE, "create_keyval=\"%s\"\n",
|
|
oc_map->bom_create_keyval, 0, 0 );
|
|
}
|
|
if ( oc_map->bom_delete_proc ) {
|
|
Debug( LDAP_DEBUG_TRACE, "delete_proc=\"%s\"\n",
|
|
oc_map->bom_delete_proc, 0, 0 );
|
|
}
|
|
Debug( LDAP_DEBUG_TRACE, "expect_return: "
|
|
"add=%d, del=%d; attributes:\n",
|
|
BACKSQL_IS_ADD( oc_map->bom_expect_return ),
|
|
BACKSQL_IS_DEL( oc_map->bom_expect_return ), 0 );
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"autoadding 'objectClass' and 'ref' mappings\n",
|
|
0, 0, 0 );
|
|
backsql_add_sysmaps( oc_map );
|
|
rc = SQLExecute( at_sth );
|
|
if ( rc != SQL_SUCCESS ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"error executing at_query: \n", 0, 0, 0 );
|
|
backsql_PrintErrors( SQL_NULL_HENV, dbh, at_sth, rc );
|
|
return LDAP_OTHER;
|
|
}
|
|
|
|
backsql_BindRowAsStrings( at_sth, &at_row );
|
|
rc = SQLFetch( at_sth );
|
|
for ( ; BACKSQL_SUCCESS(rc); rc = SQLFetch( at_sth ) ) {
|
|
const char *text = NULL;
|
|
struct berval bv;
|
|
struct berbuf bb = BB_NULL;
|
|
|
|
Debug( LDAP_DEBUG_TRACE,
|
|
"attributeType:\n"
|
|
"\tname=\"%s\"\n"
|
|
"\tsel_expr=\"%s\"\n"
|
|
"\tfrom=\"%s\"\n",
|
|
at_row.cols[ 0 ], at_row.cols[ 1 ],
|
|
at_row.cols[ 2 ] );
|
|
Debug( LDAP_DEBUG_TRACE,
|
|
"\tjoin_where=\"%s\"\n"
|
|
"\tadd_proc=\"%s\"\n"
|
|
"\tdelete_proc=\"%s\"\n",
|
|
at_row.cols[ 3 ], at_row.cols[ 4 ],
|
|
at_row.cols[ 5 ]);
|
|
/* TimesTen */
|
|
Debug( LDAP_DEBUG_TRACE, "\tsel_expr_u=\"%s\"\n",
|
|
at_row.cols[ 8 ], 0, 0 );
|
|
at_map = (backsql_at_map_rec *)ch_calloc( 1,
|
|
sizeof( backsql_at_map_rec ) );
|
|
rc = slap_str2ad( at_row.cols[ 0 ],
|
|
&at_map->bam_ad, &text );
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"attribute \"%s\" for objectClass \"%s\" "
|
|
"is not defined in schema: %s\n",
|
|
at_row.cols[ 0 ],
|
|
BACKSQL_OC_NAME( oc_map ), text );
|
|
return LDAP_CONSTRAINT_VIOLATION;
|
|
}
|
|
|
|
ber_str2bv( at_row.cols[ 1 ], 0, 1, &at_map->bam_sel_expr );
|
|
if ( at_row.value_len[ 8 ] < 0 ) {
|
|
at_map->bam_sel_expr_u.bv_val = NULL;
|
|
at_map->bam_sel_expr_u.bv_len = 0;
|
|
} else {
|
|
ber_str2bv( at_row.cols[ 8 ], 0, 1,
|
|
&at_map->bam_sel_expr_u );
|
|
}
|
|
|
|
ber_str2bv( at_row.cols[ 2 ], 0, 0, &bv );
|
|
backsql_merge_from_clause( &bb, &bv );
|
|
at_map->bam_from_tbls = bb.bb_val;
|
|
if ( at_row.value_len[ 3 ] < 0 ) {
|
|
at_map->bam_join_where.bv_val = NULL;
|
|
at_map->bam_join_where.bv_len = 0;
|
|
} else {
|
|
ber_str2bv( at_row.cols[ 3 ], 0, 1,
|
|
&at_map->bam_join_where );
|
|
}
|
|
at_map->bam_add_proc = NULL;
|
|
if ( at_row.value_len[ 4 ] > 0 ) {
|
|
at_map->bam_add_proc = ch_strdup( at_row.cols[4] );
|
|
}
|
|
at_map->bam_delete_proc = NULL;
|
|
if ( at_row.value_len[ 5 ] > 0 ) {
|
|
at_map->bam_delete_proc = ch_strdup( at_row.cols[ 5 ] );
|
|
}
|
|
at_map->bam_param_order = strtol( at_row.cols[ 6 ],
|
|
NULL, 0 );
|
|
at_map->bam_expect_return = strtol( at_row.cols[ 7 ],
|
|
NULL, 0 );
|
|
backsql_make_attr_query( oc_map, at_map );
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"preconstructed query \"%s\"\n",
|
|
at_map->bam_query, 0, 0 );
|
|
at_map->bam_next = NULL;
|
|
if ( avl_insert( &oc_map->bom_attrs, at_map, backsql_cmp_attr, backsql_dup_attr ) == BACKSQL_DUPLICATE ) {
|
|
Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
|
|
"duplicate attribute \"%s\" "
|
|
"in objectClass \"%s\" map\n",
|
|
at_map->bam_ad->ad_cname.bv_val,
|
|
oc_map->bom_oc->soc_cname.bv_val, 0 );
|
|
}
|
|
|
|
if ( si->upper_func.bv_val && at_map->bam_sel_expr_u.bv_val == NULL ) {
|
|
struct berbuf bb = BB_NULL;
|
|
|
|
backsql_strfcat( &bb, "bcbc",
|
|
&si->upper_func,
|
|
'(' /* ) */ ,
|
|
&at_map->bam_sel_expr,
|
|
/* ( */ ')' );
|
|
at_map->bam_sel_expr_u = bb.bb_val;
|
|
}
|
|
}
|
|
backsql_FreeRow( &at_row );
|
|
SQLFreeStmt( at_sth, SQL_CLOSE );
|
|
}
|
|
backsql_FreeRow( &oc_row );
|
|
SQLFreeStmt( at_sth, SQL_DROP );
|
|
SQLFreeStmt( oc_sth, SQL_DROP );
|
|
si->bsql_flags |= BSQLF_SCHEMA_LOADED;
|
|
Debug( LDAP_DEBUG_TRACE, "<==backsql_load_schema_map()\n", 0, 0, 0 );
|
|
return LDAP_SUCCESS;
|
|
}
|
|
|
|
backsql_oc_map_rec *
|
|
backsql_oc2oc( backsql_info *si, ObjectClass *oc )
|
|
{
|
|
backsql_oc_map_rec tmp, *res;
|
|
|
|
#ifdef BACKSQL_TRACE
|
|
Debug( LDAP_DEBUG_TRACE, "==>backsql_oc2oc(): "
|
|
"searching for objectclass with name=\"%s\"\n",
|
|
objclass, 0, 0 );
|
|
#endif /* BACKSQL_TRACE */
|
|
|
|
tmp.bom_oc = oc;
|
|
res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp, backsql_cmp_oc );
|
|
#ifdef BACKSQL_TRACE
|
|
if ( res != NULL ) {
|
|
Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
|
|
"found name=\"%s\", id=%d\n",
|
|
BACKSQL_OC_NAME( res ), res->id, 0 );
|
|
} else {
|
|
Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
|
|
"not found\n", 0, 0, 0 );
|
|
}
|
|
#endif /* BACKSQL_TRACE */
|
|
|
|
return res;
|
|
}
|
|
|
|
backsql_oc_map_rec *
|
|
backsql_name2oc( backsql_info *si, struct berval *oc_name )
|
|
{
|
|
backsql_oc_map_rec tmp, *res;
|
|
|
|
#ifdef BACKSQL_TRACE
|
|
Debug( LDAP_DEBUG_TRACE, "==>oc_with_name(): "
|
|
"searching for objectclass with name=\"%s\"\n",
|
|
objclass, 0, 0 );
|
|
#endif /* BACKSQL_TRACE */
|
|
|
|
tmp.bom_oc = oc_bvfind( oc_name );
|
|
if ( tmp.bom_oc == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp, backsql_cmp_oc );
|
|
#ifdef BACKSQL_TRACE
|
|
if ( res != NULL ) {
|
|
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
|
|
"found name=\"%s\", id=%d\n",
|
|
BACKSQL_OC_NAME( res ), res->bom_id, 0 );
|
|
} else {
|
|
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
|
|
"not found\n", 0, 0, 0 );
|
|
}
|
|
#endif /* BACKSQL_TRACE */
|
|
|
|
return res;
|
|
}
|
|
|
|
backsql_oc_map_rec *
|
|
backsql_id2oc( backsql_info *si, unsigned long id )
|
|
{
|
|
backsql_oc_map_rec tmp, *res;
|
|
|
|
#ifdef BACKSQL_TRACE
|
|
Debug( LDAP_DEBUG_TRACE, "==>oc_with_id(): "
|
|
"searching for objectclass with id='%d'\n", id, 0, 0 );
|
|
#endif /* BACKSQL_TRACE */
|
|
|
|
tmp.bom_id = id;
|
|
res = (backsql_oc_map_rec *)avl_find( si->oc_by_id, &tmp,
|
|
backsql_cmp_oc_id );
|
|
|
|
#ifdef BACKSQL_TRACE
|
|
if ( res != NULL ) {
|
|
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
|
|
"found name=\"%s\", id=%d\n",
|
|
BACKSQL_OC_NAME( res ), res->bom_id, 0 );
|
|
} else {
|
|
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
|
|
"not found\n", 0, 0, 0 );
|
|
}
|
|
#endif /* BACKSQL_TRACE */
|
|
|
|
return res;
|
|
}
|
|
|
|
backsql_at_map_rec *
|
|
backsql_ad2at( backsql_oc_map_rec* objclass, AttributeDescription *ad )
|
|
{
|
|
backsql_at_map_rec tmp, *res;
|
|
|
|
#ifdef BACKSQL_TRACE
|
|
Debug( LDAP_DEBUG_TRACE, "==>backsql_ad2at(): "
|
|
"searching for attribute \"%s\" for objectclass \"%s\"\n",
|
|
attr, BACKSQL_OC_NAME( objclass ), 0 );
|
|
#endif /* BACKSQL_TRACE */
|
|
|
|
tmp.bam_ad = ad;
|
|
res = (backsql_at_map_rec *)avl_find( objclass->bom_attrs, &tmp,
|
|
backsql_cmp_attr );
|
|
|
|
#ifdef BACKSQL_TRACE
|
|
if ( res != NULL ) {
|
|
Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
|
|
"found name=\"%s\", sel_expr=\"%s\"\n",
|
|
res->bam_ad->ad_cname.bv_val,
|
|
res->bam_sel_expr.bv_val, 0 );
|
|
} else {
|
|
Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
|
|
"not found\n", 0, 0, 0 );
|
|
}
|
|
#endif /* BACKSQL_TRACE */
|
|
|
|
return res;
|
|
}
|
|
|
|
/* attributeType inheritance */
|
|
struct supad2at_t {
|
|
backsql_at_map_rec **ret;
|
|
AttributeDescription *ad;
|
|
unsigned n;
|
|
};
|
|
|
|
#define SUPAD2AT_STOP (-1)
|
|
|
|
static int
|
|
supad2at_f( void *v_at, void *v_arg )
|
|
{
|
|
backsql_at_map_rec *at = (backsql_at_map_rec *)v_at;
|
|
struct supad2at_t *va = (struct supad2at_t *)v_arg;
|
|
|
|
if ( is_at_subtype( at->bam_ad->ad_type, va->ad->ad_type ) ) {
|
|
backsql_at_map_rec **ret;
|
|
unsigned i;
|
|
|
|
/* if already listed, holler! (should never happen) */
|
|
if ( va->ret ) {
|
|
for ( i = 0; i < va->n; i++ ) {
|
|
if ( va->ret[ i ]->bam_ad == at->bam_ad ) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( i < va->n ) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
ret = ch_realloc( va->ret,
|
|
sizeof( backsql_at_map_rec *) * ( va->n + 2 ) );
|
|
if ( ret == NULL ) {
|
|
ch_free( va->ret );
|
|
return SUPAD2AT_STOP;
|
|
}
|
|
|
|
ret[ va->n ] = at;
|
|
va->n++;
|
|
ret[ va->n ] = NULL;
|
|
va->ret = ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* stores in *pret a NULL terminated array of pointers
|
|
* to backsql_at_map_rec whose attributeType is supad->ad_type
|
|
* or derived from it
|
|
*/
|
|
int
|
|
backsql_supad2at( backsql_oc_map_rec *objclass, AttributeDescription *supad,
|
|
backsql_at_map_rec ***pret )
|
|
{
|
|
struct supad2at_t va;
|
|
int rc;
|
|
|
|
assert( objclass );
|
|
assert( supad );
|
|
assert( pret );
|
|
|
|
*pret = NULL;
|
|
|
|
va.ret = NULL;
|
|
va.ad = supad;
|
|
va.n = 0;
|
|
|
|
rc = avl_apply( objclass->bom_attrs, supad2at_f, &va,
|
|
SUPAD2AT_STOP, AVL_INORDER );
|
|
if ( rc == SUPAD2AT_STOP ) {
|
|
return -1;
|
|
}
|
|
|
|
*pret = va.ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
backsql_free_attr( void *v_at )
|
|
{
|
|
backsql_at_map_rec *at = v_at;
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "==>free_attr(): \"%s\"\n",
|
|
at->bam_ad->ad_cname.bv_val, 0, 0 );
|
|
ch_free( at->bam_sel_expr.bv_val );
|
|
if ( at->bam_from_tbls.bv_val != NULL ) {
|
|
ch_free( at->bam_from_tbls.bv_val );
|
|
}
|
|
if ( at->bam_join_where.bv_val != NULL ) {
|
|
ch_free( at->bam_join_where.bv_val );
|
|
}
|
|
if ( at->bam_add_proc != NULL ) {
|
|
ch_free( at->bam_add_proc );
|
|
}
|
|
if ( at->bam_delete_proc != NULL ) {
|
|
ch_free( at->bam_delete_proc );
|
|
}
|
|
if ( at->bam_query ) {
|
|
ch_free( at->bam_query );
|
|
}
|
|
|
|
/* TimesTen */
|
|
if ( at->bam_sel_expr_u.bv_val ) {
|
|
ch_free( at->bam_sel_expr_u.bv_val );
|
|
}
|
|
|
|
if ( at->bam_next ) {
|
|
backsql_free_attr( at->bam_next );
|
|
}
|
|
|
|
ch_free( at );
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "<==free_attr()\n", 0, 0, 0 );
|
|
}
|
|
|
|
static void
|
|
backsql_free_oc( void *v_oc )
|
|
{
|
|
backsql_oc_map_rec *oc = v_oc;
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "==>free_oc(): \"%s\"\n",
|
|
BACKSQL_OC_NAME( oc ), 0, 0 );
|
|
avl_free( oc->bom_attrs, backsql_free_attr );
|
|
ch_free( oc->bom_keytbl.bv_val );
|
|
ch_free( oc->bom_keycol.bv_val );
|
|
if ( oc->bom_create_proc != NULL ) {
|
|
ch_free( oc->bom_create_proc );
|
|
}
|
|
if ( oc->bom_create_keyval != NULL ) {
|
|
ch_free( oc->bom_create_keyval );
|
|
}
|
|
if ( oc->bom_delete_proc != NULL ) {
|
|
ch_free( oc->bom_delete_proc );
|
|
}
|
|
ch_free( oc );
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "<==free_oc()\n", 0, 0, 0 );
|
|
}
|
|
|
|
int
|
|
backsql_destroy_schema_map( backsql_info *si )
|
|
{
|
|
Debug( LDAP_DEBUG_TRACE, "==>destroy_schema_map()\n", 0, 0, 0 );
|
|
avl_free( si->oc_by_oc, 0 );
|
|
avl_free( si->oc_by_id, backsql_free_oc );
|
|
Debug( LDAP_DEBUG_TRACE, "<==destroy_schema_map()\n", 0, 0, 0 );
|
|
return 0;
|
|
}
|
|
|
|
#endif /* SLAPD_SQL */
|
|
|