char *upper_func;
char *strcast_func;
Avlnode *db_conns;
- Avlnode *oc_by_name;
+ Avlnode *oc_by_oc;
Avlnode *oc_by_id;
int schema_loaded;
ldap_pvt_thread_mutex_t dbconn_mutex;
Entry *e, user_entry;
Attribute *a;
backsql_srch_info bsi;
+ int rc;
Debug( LDAP_DEBUG_TRACE, "==>backsql_bind()\n", 0, 0, 0 );
/*
* method = LDAP_AUTH_SIMPLE
*/
- dbh = backsql_get_db_conn( be, conn );
+ rc = backsql_get_db_conn( be, conn, &dbh );
if (!dbh) {
Debug( LDAP_DEBUG_TRACE, "backsql_bind(): "
"could not get connection handle - exiting\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OTHER, "",
- "SQL-backend error", NULL, NULL );
+ send_ldap_result( conn, op, rc, "",
+ rc == LDAP_OTHER ? "SQL-backend error" : "",
+ NULL, NULL );
return 1;
}
Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
"oc='%s' attr='%s' keyval=%ld\n",
- bsi->oc->name, at->name, bsi->c_eid->keyval );
+ bsi->oc->name.bv_val, at->name.bv_val, bsi->c_eid->keyval );
rc = backsql_Prepare( bsi->dbh, &sth, at->query, 0 );
if ( rc != SQL_SUCCESS ) {
for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
for ( i = 0; i < row.ncols; i++ ) {
if ( row.is_null[ i ] > 0 ) {
- backsql_entry_addattr( bsi->e,
- row.col_names[ i ],
- row.cols[ i ],
+ struct berval bv;
+
+ bv.bv_val = row.cols[ i ];
#if 0
- row.col_prec[ i ]
+ bv.bv_len = row.col_prec[ i ];
#else
- /*
- * FIXME: what if a binary
- * is fetched?
- */
- strlen( row.cols[ i ] )
+ /*
+ * FIXME: what if a binary
+ * is fetched?
+ */
+ bv.bv_len = strlen( row.cols[ i ] );
#endif
- );
+ backsql_entry_addattr( bsi->e,
+ &row.col_names[ i ], &bv );
+
#if 0
Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
(int)row.col_prec[ i ], 0, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "NULL value "
"in this row for attribute '%s'\n",
- row.col_names[ i ], 0, 0 );
+ row.col_names[ i ].bv_val, 0, 0 );
#endif
}
}
Entry *
backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
{
- char **c_at_name;
+ int i;
backsql_at_map_rec *at;
int rc;
return NULL;
}
- bsi->oc = backsql_oc_with_id( bsi->bi, eid->oc_id );
+ bsi->oc = backsql_id2oc( bsi->bi, eid->oc_id );
bsi->e = e;
bsi->c_eid = eid;
e->e_attrs = NULL;
if ( bsi->attrs != NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
"custom attribute list\n", 0, 0, 0 );
- for ( c_at_name = bsi->attrs; *c_at_name != NULL; c_at_name++ ) {
- if ( !strcasecmp( *c_at_name, "objectclass" )
- || !strcasecmp( *c_at_name, "0.10" ) ) {
+ for ( i = 0; bsi->attrs[ i ].an_name.bv_val; i++ ) {
+ AttributeName *attr = &bsi->attrs[ i ];
+
+ if ( attr->an_desc == slap_schema.si_ad_objectClass
+#if 0 /* FIXME: what is 0.10 ? */
+ || !BACKSQL_NCMP( &attr->an_name, &bv_n_0_10 )
+#endif
+ ) {
#if 0
- backsql_entry_addattr( bsi->e, "objectclass",
- bsi->oc->name,
- strlen( bsi->oc->name ) );
+ backsql_entry_addattr( bsi->e,
+ &bv_n_objectclass,
+ &bsi->oc->name );
#endif
continue;
}
- at = backsql_at_with_name( bsi->oc, *c_at_name );
+
+ at = backsql_ad2at( bsi->oc, attr->an_desc );
if ( at != NULL ) {
backsql_get_attr_vals( at, bsi );
} else {
Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
"attribute '%s' is not defined "
"for objectlass '%s'\n",
- *c_at_name, bsi->oc->name, 0 );
+ attr->an_name.bv_val,
+ bsi->oc->name.bv_val, 0 );
}
}
} else {
bsi, 0, AVL_INORDER );
}
- backsql_entry_addattr( bsi->e, "objectclass", bsi->oc->name,
- strlen( bsi->oc->name ) );
+ backsql_entry_addattr( bsi->e, &bv_n_objectclass, &bsi->oc->name );
Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
#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"
}
tmp.c_connid =- 1;
- dbh = backsql_get_db_conn( bd, &tmp );
- if ( !dbh ) {
+ 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;
#include <sys/types.h>
#include <string.h>
#include "slap.h"
+#include "ldap_pvt.h"
#include "back-sql.h"
#include "sql-wrap.h"
#include "schema-map.h"
*/
#define BACKSQL_REALLOC_STMT
-int
-backsql_modify(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- struct berval *dn,
- struct berval *ndn,
- Modifications *modlist )
+static int
+backsql_modify_internal(
+ backsql_info *bi,
+ SQLHDBC dbh,
+ backsql_oc_map_rec *oc,
+ backsql_entryID *e_id,
+ Modifications *modlist )
{
- backsql_info *bi = (backsql_info*)be->be_private;
- SQLHDBC dbh;
- SQLHSTMT sth;
- RETCODE rc;
- backsql_oc_map_rec *oc = NULL;
- backsql_entryID e_id;
- int res;
- Modification *c_mod;
- Modifications *ml;
- backsql_at_map_rec *at = NULL;
- struct berval *at_val;
- int i;
- /* first parameter no, parameter order */
- SQLUSMALLINT pno, po;
- /* procedure return code */
- int prc;
-
- Debug( LDAP_DEBUG_TRACE, "==>backsql_modify(): changing entry '%s'\n",
- ndn->bv_val, 0, 0 );
- dbh = backsql_get_db_conn( be, conn );
- if ( !dbh ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
- "could not get connection handle - exiting\n",
- 0, 0, 0 );
- /*
- * FIXME: we don't want to send back
- * excessively detailed messages
- */
- send_ldap_result( conn, op, LDAP_OTHER, "",
- "SQL-backend error", NULL, NULL );
- return 1;
- }
-
- res = backsql_dn2id( bi, &e_id, dbh, ndn );
- if ( res != LDAP_SUCCESS ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
- "could not lookup entry id\n", 0, 0, 0 );
- send_ldap_result( conn, op, res , "", NULL, NULL, NULL );
- return 1;
- }
+ RETCODE rc;
+ SQLHSTMT sth;
+ Modifications *ml;
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
- "modifying entry '%s' (id=%ld)\n",
- e_id.dn.bv_val, e_id.id, 0 );
-
- oc = backsql_oc_with_id( bi, e_id.oc_id );
- if ( oc == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
- "cannot determine objectclass of entry -- aborting\n",
- 0, 0, 0 );
- /*
- * FIXME: we don't want to send back
- * excessively detailed messages
- */
- send_ldap_result( conn, op, LDAP_OTHER, "",
- "SQL-backend error", NULL, NULL );
- return 1;
- }
-
- SQLAllocStmt( dbh, &sth );
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
"traversing modifications list\n", 0, 0, 0 );
+#ifndef BACKSQL_REALLOC_STMT
+ SQLAllocStmt( dbh, &sth );
+#endif /* BACKSQL_REALLOC_STMT */
for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
- char *attrname;
+ AttributeDescription *ad;
+ backsql_at_map_rec *at = NULL;
+ struct berval *at_val;
+ Modification *c_mod;
+ int i;
+ /* first parameter no, parameter order */
+ SQLUSMALLINT pno, po;
+ /* procedure return code */
+ int prc;
+
+#ifdef BACKSQL_REALLOC_STMT
+ SQLAllocStmt( dbh, &sth );
+#endif /* BACKSQL_REALLOC_STMT */
c_mod = &ml->sml_mod;
- attrname = c_mod->sm_desc->ad_cname.bv_val;
+ ad = c_mod->sm_desc;
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): attribute '%s'\n",
- attrname, 0, 0 );
- at = backsql_at_with_name( oc, attrname );
+ ad->ad_cname.bv_val, 0, 0 );
+ at = backsql_ad2at( oc, ad );
if ( at == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
"attribute provided is not registered "
"in objectclass '%s'\n",
- attrname, 0, 0 );
+ ad->ad_cname.bv_val, 0, 0 );
continue;
}
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
"replacing values for attribute '%s'\n",
- at->name, 0, 0 );
+ at->name.bv_val, 0, 0 );
if ( at->add_proc == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
"add procedure is not defined "
"for attribute '%s' "
"- unable to perform replacements\n",
- at->name, 0, 0 );
+ at->name.bv_val, 0, 0 );
break;
}
"delete procedure is not defined "
"for attribute '%s' "
"- adding only\n",
- at->name, 0, 0 );
+ at->name.bv_val, 0, 0 );
goto add_only;
}
break;
}
- rc = backsql_BindParamID( asth, 1, &e_id.keyval );
+ rc = backsql_BindParamID( asth, 1, &e_id->keyval );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
"error binding key value parameter\n",
rc = SQLFetch( asth );
for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( asth ) ) {
for ( i = 0; i < row.ncols; i++ ) {
- if ( at->expect_return & BACKSQL_DEL ) {
+ if ( BACKSQL_IS_DEL( at->expect_return ) ) {
pno = 1;
SQLBindParameter(sth, 1,
SQL_PARAM_OUTPUT,
} else {
pno = 0;
}
- po = ( at->param_order & BACKSQL_DEL ) > 0;
+ po = ( BACKSQL_IS_DEL( at->param_order ) ) > 0;
SQLBindParameter( sth, pno + 1 + po,
SQL_PARAM_INPUT,
SQL_C_ULONG, SQL_INTEGER,
- 0, 0, &e_id.keyval, 0, 0 );
+ 0, 0, &e_id->keyval, 0, 0 );
/*
* check for syntax needed here
backsql_PrintErrors( bi->db_env,
dbh, sth, rc );
}
+#ifdef BACKSQL_REALLOC_STMT
+ SQLFreeStmt( sth, SQL_DROP );
+ SQLAllocStmt( dbh, &sth );
+#endif /* BACKSQL_REALLOC_STMT */
}
}
backsql_FreeRow( &row );
* PASSTHROUGH - to add new attributes -- do NOT add break
*/
case LDAP_MOD_ADD:
+ case SLAP_MOD_SOFTADD:
add_only:;
if ( at->add_proc == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
"add procedure is not defined "
"for attribute '%s'\n",
- at->name, 0, 0 );
+ at->name.bv_val, 0, 0 );
break;
}
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
"no values given to add "
"for attribute '%s'\n",
- at->name, 0, 0 );
+ at->name.bv_val, 0, 0 );
break;
}
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
"adding new values for attribute '%s'\n",
- at->name, 0, 0 );
- for ( i = 0, at_val = &c_mod->sm_bvalues[ 0 ];
+ at->name.bv_val, 0, 0 );
+ for ( i = 0, at_val = c_mod->sm_bvalues;
at_val->bv_val != NULL;
- i++, at_val = &c_mod->sm_bvalues[ i ] ) {
- if ( at->expect_return & BACKSQL_ADD ) {
+ i++, at_val++ ) {
+ if ( BACKSQL_IS_ADD( at->expect_return ) ) {
pno = 1;
SQLBindParameter( sth, 1,
SQL_PARAM_OUTPUT,
} else {
pno = 0;
}
- po = ( at->param_order & BACKSQL_ADD ) > 0;
+ po = ( BACKSQL_IS_ADD( at->param_order ) ) > 0;
SQLBindParameter( sth, pno + 1 + po,
SQL_PARAM_INPUT,
SQL_C_ULONG, SQL_INTEGER,
- 0, 0, &e_id.keyval, 0, 0 );
+ 0, 0, &e_id->keyval, 0, 0 );
/*
* check for syntax needed here
backsql_PrintErrors( bi->db_env,
dbh, sth, rc );
}
+#ifdef BACKSQL_REALLOC_STMT
+ SQLFreeStmt( sth, SQL_DROP );
+ SQLAllocStmt( dbh, &sth );
+#endif /* BACKSQL_REALLOC_STMT */
}
break;
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
"delete procedure is not defined "
"for attribute '%s'\n",
- at->name, 0, 0 );
+ at->name.bv_val, 0, 0 );
break;
}
"no values given to delete "
"for attribute '%s' "
"-- deleting all values\n",
- at->name, 0, 0 );
+ at->name.bv_val, 0, 0 );
goto del_all;
}
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
"deleting values for attribute '%s'\n",
- at->name, 0, 0 );
- for( i = 0, at_val = &c_mod->sm_bvalues[ 0 ];
+ at->name.bv_val, 0, 0 );
+ for ( i = 0, at_val = c_mod->sm_bvalues;
at_val->bv_val != NULL;
- i++, at_val = &c_mod->sm_bvalues[ i ] ) {
- if ( at->expect_return & BACKSQL_DEL ) {
+ i++, at_val++ ) {
+ if ( BACKSQL_IS_DEL( at->expect_return ) ) {
pno = 1;
SQLBindParameter( sth, 1,
SQL_PARAM_OUTPUT,
} else {
pno = 0;
}
- po = ( at->param_order & BACKSQL_DEL ) > 0;
+ po = ( BACKSQL_IS_DEL( at->param_order ) ) > 0;
SQLBindParameter( sth, pno + 1 + po,
SQL_PARAM_INPUT,
SQL_C_ULONG, SQL_INTEGER,
- 0, 0, &e_id.keyval, 0, 0 );
+ 0, 0, &e_id->keyval, 0, 0 );
/*
* check for syntax needed here
backsql_PrintErrors( bi->db_env,
dbh, sth, rc );
}
+#ifdef BACKSQL_REALLOC_STMT
+ SQLFreeStmt( sth, SQL_DROP );
+ SQLAllocStmt( dbh, &sth );
+#endif /* BACKSQL_REALLOC_STMT */
}
break;
}
-
+#ifndef BACKSQL_REALLOC_STMT
SQLFreeStmt( sth, SQL_RESET_PARAMS );
+#else /* BACKSQL_REALLOC_STMT */
+ SQLFreeStmt( sth, SQL_DROP );
+#endif /* BACKSQL_REALLOC_STMT */
}
+#ifndef BACKSQL_REALLOC_STMT
SQLFreeStmt( sth, SQL_DROP );
- send_ldap_result( conn, op, LDAP_SUCCESS, "", NULL, NULL, NULL );
+#endif /* BACKSQL_REALLOC_STMT */
+
+ /*
+ * FIXME: should fail in case one change fails?
+ */
+ return LDAP_SUCCESS;
+}
+
+int
+backsql_modify(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ struct berval *dn,
+ struct berval *ndn,
+ Modifications *modlist )
+{
+ backsql_info *bi = (backsql_info*)be->be_private;
+ SQLHDBC dbh;
+ backsql_oc_map_rec *oc = NULL;
+ backsql_entryID e_id;
+ int res;
+
+ /*
+ * FIXME: in case part of the operation cannot be performed
+ * (missing mapping, SQL write fails or so) the entire operation
+ * should be rolled-back
+ */
+
+ Debug( LDAP_DEBUG_TRACE, "==>backsql_modify(): changing entry '%s'\n",
+ ndn->bv_val, 0, 0 );
+ res = backsql_get_db_conn( be, conn, &dbh );
+ if ( res != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ "could not get connection handle - exiting\n",
+ 0, 0, 0 );
+ /*
+ * FIXME: we don't want to send back
+ * excessively detailed messages
+ */
+ send_ldap_result( conn, op, res, "",
+ res == LDAP_OTHER ? "SQL-backend error" : "",
+ NULL, NULL );
+ return 1;
+ }
+
+ res = backsql_dn2id( bi, &e_id, dbh, ndn );
+ if ( res != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ "could not lookup entry id\n", 0, 0, 0 );
+ send_ldap_result( conn, op, res , "",
+ res == LDAP_OTHER ? "SQL-backend error" : "",
+ NULL, NULL );
+ return 1;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ "modifying entry '%s' (id=%ld)\n",
+ e_id.dn.bv_val, e_id.id, 0 );
+
+ oc = backsql_id2oc( bi, e_id.oc_id );
+ if ( oc == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ "cannot determine objectclass of entry -- aborting\n",
+ 0, 0, 0 );
+ /*
+ * FIXME: should never occur, since the entry was built!!!
+ */
+
+ /*
+ * FIXME: we don't want to send back
+ * excessively detailed messages
+ */
+ send_ldap_result( conn, op, LDAP_OTHER, "",
+ "SQL-backend error", NULL, NULL );
+ return 1;
+ }
+
+ res = backsql_modify_internal( bi, dbh, oc, &e_id, modlist );
+ if ( res == LDAP_SUCCESS ) {
+ /*
+ * Commit only if all operations succeed
+ *
+ * FIXME: backsql_modify_internal() does not fail
+ * if add/delete operations are not available, or
+ * if a multiple value add actually results in a replace,
+ * or if a single operation on an attribute fails
+ * for any reason
+ */
+ SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
+ }
+ send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n", 0, 0, 0 );
return 0;
SQLHSTMT sth;
RETCODE rc;
backsql_entryID e_id, pe_id, new_pid;
+ backsql_oc_map_rec *oc = NULL;
int res;
struct berval p_dn, p_ndn,
*new_pdn = NULL, *new_npdn = NULL,
new_dn, new_ndn;
+ const char *text = NULL;
+ LDAPRDN *new_rdn = NULL;
+ LDAPRDN *old_rdn = NULL;
+ Modifications *mod;
Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry '%s', "
"newrdn='%s', newSuperior='%s'\n",
- dn->bv_val, newrdn->bv_val, newSuperior->bv_val );
- dbh = backsql_get_db_conn( be, conn );
- if ( !dbh ) {
+ dn->bv_val, newrdn->bv_val,
+ newSuperior ? newSuperior->bv_val : "(NULL)" );
+ res = backsql_get_db_conn( be, conn, &dbh );
+ if ( res != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
"could not get connection handle - exiting\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OTHER, "",
- "SQL-backend error", NULL, NULL );
+ send_ldap_result( conn, op, res, "",
+ res == LDAP_OTHER ? "SQL-backend error" : "",
+ NULL, NULL );
return 1;
}
if ( res != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
"could not lookup entry id\n", 0, 0, 0 );
- send_ldap_result( conn, op, res , "", NULL, NULL, NULL );
+ send_ldap_result( conn, op, res, "",
+ res == LDAP_OTHER ? "SQL-backend error" : "",
+ NULL, NULL );
return 1;
}
+ /*
+ * FIXME: check whether entry has children
+ */
+
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): entry id is %ld\n",
e_id.id, 0, 0 );
dnParent( ndn, &p_ndn );
if ( newSuperior ) {
+ /*
+ * namingContext "" is not supported
+ */
+ if ( newSuperior->bv_len == 0 ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+ "newSuperior is \"\" - aborting\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
+ "", "not allowed within namingContext",
+ NULL, NULL );
+ goto modrdn_return;
+ }
+
new_pdn = newSuperior;
new_npdn = nnewSuperior;
+
} else {
new_pdn = &p_dn;
new_npdn = &p_ndn;
}
- SQLAllocStmt( dbh, &sth );
-
if ( newSuperior && dn_match( &p_ndn, new_npdn ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
- "newSuperior is equal to old parent - aborting\n",
+ "newSuperior is equal to old parent - ignored\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "",
- NULL, NULL, NULL );
- goto modrdn_return;
+ newSuperior = NULL;
}
if ( newSuperior && dn_match( ndn, new_npdn ) ) {
if ( res != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
"could not lookup old parent entry id\n", 0, 0, 0 );
- send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
+ send_ldap_result( conn, op, res, "",
+ res == LDAP_OTHER ? "SQL-backend error" : "",
+ NULL, NULL );
goto modrdn_return;
}
if ( res != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
"could not lookup new parent entry id\n", 0, 0, 0 );
- send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
+ send_ldap_result( conn, op, res, "",
+ res == LDAP_OTHER ? "SQL-backend error" : "",
+ NULL, NULL );
goto modrdn_return;
}
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
"executing delentry_query\n", 0, 0, 0 );
+ SQLAllocStmt( dbh, &sth );
SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
0, 0, &e_id.id, 0, 0 );
rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
goto modrdn_return;
}
- /*
- * FIXME: should process deleteoldrdn here...
+ /* Get attribute type and attribute value of our new rdn, we will
+ * need to add that to our new entry
*/
+ if ( ldap_bv2rdn( newrdn, &new_rdn, (char **)&text,
+ LDAP_DN_FORMAT_LDAP ) ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, ERR,
+ "backsql_modrdn: can't figure out "
+ "type(s)/values(s) of newrdn\n",
+ 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modrdn: can't figure out "
+ "type(s)/values(s) of newrdn\n",
+ 0, 0, 0 );
+#endif
+ rc = LDAP_INVALID_DN_SYNTAX;
+ goto modrdn_return;
+ }
- send_ldap_result( conn, op, LDAP_SUCCESS, "", NULL, NULL, NULL );
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, RESULTS,
+ "backsql_modrdn: new_rdn_type=\"%s\", "
+ "new_rdn_val=\"%s\"\n",
+ new_rdn[ 0 ][ 0 ]->la_attr.bv_val,
+ new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modrdn: new_rdn_type=\"%s\", "
+ "new_rdn_val=\"%s\"\n",
+ new_rdn[ 0 ][ 0 ]->la_attr.bv_val,
+ new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
+#endif
+
+ if ( deleteoldrdn ) {
+ if ( ldap_bv2rdn( dn, &old_rdn, (char **)&text,
+ LDAP_DN_FORMAT_LDAP ) ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG ( OPERATION, ERR,
+ "backsql_modrdn: can't figure out "
+ "type(s)/values(s) of old_rdn\n",
+ 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modrdn: can't figure out "
+ "the old_rdn type(s)/value(s)\n",
+ 0, 0, 0 );
+#endif
+ rc = LDAP_OTHER;
+ goto modrdn_return;
+ }
+ }
+
+ res = slap_modrdn2mods( NULL, NULL, NULL, NULL, old_rdn, new_rdn,
+ deleteoldrdn, &mod );
+ if ( res != LDAP_SUCCESS ) {
+ goto modrdn_return;
+ }
+
+ oc = backsql_id2oc( bi, e_id.oc_id );
+ res = backsql_modify_internal( bi, dbh, oc, &e_id, mod );
+
+ if ( res != LDAP_SUCCESS ) {
+ goto modrdn_return;
+ }
+
+ /*
+ * Commit only if all operations succeed
+ *
+ * FIXME: backsql_modify_internal() does not fail
+ * if add/delete operations are not available, or
+ * if a multiple value add actually results in a replace,
+ * or if a single operation on an attribute fails for any
+ * reason
+ */
+ SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
modrdn_return:
SQLFreeStmt( sth, SQL_DROP );
ch_free( new_ndn.bv_val );
}
+ /* LDAP v2 supporting correct attribute handling. */
+ if ( new_rdn != NULL ) {
+ ldap_rdnfree( new_rdn );
+ }
+ if ( old_rdn != NULL ) {
+ ldap_rdnfree( old_rdn );
+ }
+ if( mod != NULL ) {
+ Modifications *tmp;
+ for (; mod; mod=tmp ) {
+ tmp = mod->sml_next;
+ free( mod );
+ }
+ }
+
+ send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
+
Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );
return 0;
}
RETCODE rc;
backsql_oc_map_rec *oc = NULL;
backsql_at_map_rec *at_rec = NULL;
- backsql_entryID parent_id;
+ backsql_entryID e_id, parent_id;
int res;
Attribute *at;
struct berval *at_val;
e->e_dn, 0, 0 );
for ( at = e->e_attrs; at != NULL; at = at->a_next ) {
-#if 0
- Debug( LDAP_DEBUG_TRACE, "backsql_add(): scanning entry "
- "-- %s\n", at->a_type, 0, 0 );
-#endif
- if ( !strcasecmp( at->a_desc->ad_cname.bv_val, "objectclass" ) ) {
- oc = backsql_oc_with_name( bi, at->a_vals[ 0 ].bv_val );
+ if ( at->a_desc == slap_schema.si_ad_objectClass ) {
+ /*
+ * FIXME: only the objectClass provided first
+ * is considered when creating a new entry
+ */
+ oc = backsql_name2oc( bi, &at->a_vals[ 0 ] );
break;
}
}
Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
"cannot determine objectclass of entry -- aborting\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OTHER, "",
- "SQL-backend error", NULL, NULL );
+ send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
+ "operation not permitted within namingContext",
+ NULL, NULL );
return 1;
}
Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
"create procedure is not defined for this objectclass "
"- aborting\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OTHER, "",
- "SQL-backend error", NULL, NULL );
+ send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
+ "operation not permitted within namingContext",
+ NULL, NULL );
return 1;
}
- dbh = backsql_get_db_conn( be, conn );
- if ( !dbh ) {
+ prc = backsql_get_db_conn( be, conn, &dbh );
+ if ( prc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
"could not get connection handle - exiting\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OTHER, "",
- "SQL-backend error", NULL, NULL );
+ send_ldap_result( conn, op, prc, "",
+ prc == LDAP_OTHER ? "SQL-backend error" : "",
+ NULL, NULL );
return 1;
}
+ /*
+ * Check if entry exists
+ */
+ res = backsql_dn2id( bi, &e_id, dbh, &e->e_name );
+ if ( res == LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+ "entry '%s' exists\n",
+ e->e_name.bv_val, 0, 0 );
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "",
+ NULL, NULL, NULL );
+ return 1;
+ }
+
+ /*
+ * Check if parent exists
+ */
+ dnParent( &e->e_name, &pdn );
+ res = backsql_dn2id( bi, &parent_id, dbh, &pdn );
+ if ( res != LDAP_SUCCESS ) {
+
+ /*
+ * NO SUCH OBJECT seems more appropriate
+ */
+ Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+ "could not lookup parent entry for new record '%s'\n",
+ pdn.bv_val, 0, 0 );
+
+ if ( res != LDAP_NO_SUCH_OBJECT ) {
+ send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
+ return 1;
+ }
+
+ /*
+ * Look for matched
+ */
+ while ( 1 ) {
+ struct berval dn;
+ char *matched = "";
+
+ dn = pdn;
+ dnParent( &dn, &pdn );
+
+ /*
+ * Empty DN ("") defaults to LDAP_SUCCESS
+ */
+ res = backsql_dn2id( bi, &parent_id, dbh, &pdn );
+ switch ( res ) {
+ case LDAP_NO_SUCH_OBJECT:
+ if ( pdn.bv_len > 0 ) {
+ break;
+ }
+ /* fail over to next case */
+
+ case LDAP_SUCCESS:
+ matched = pdn.bv_val;
+ /* fail over to next case */
+
+ default:
+ send_ldap_result( conn, op, res, matched,
+ NULL, NULL, NULL );
+ return 1;
+ }
+ }
+ }
+
+ /*
+ * create_proc is executed; if expect_return is set, then
+ * an output parameter is bound, which should contain
+ * the id of the added row; otherwise the procedure
+ * is expected to return the id as the first column of a select
+ */
+
#ifndef BACKSQL_REALLOC_STMT
- SQLAllocStmt( dbh, &sth );
+ rc = SQLAllocStmt( dbh, &sth );
#else /* BACKSQL_REALLOC_STMT */
rc = backsql_Prepare( dbh, &sth, oc->create_proc, 0 );
+#endif /* BACKSQL_REALLOC_STMT */
if ( rc != SQL_SUCCESS ) {
send_ldap_result( conn, op, LDAP_OTHER, "",
"SQL-backend error", NULL, NULL );
return 1;
}
-#endif /* BACKSQL_REALLOC_STMT */
- if ( oc->expect_return ) {
+ if ( BACKSQL_IS_ADD( oc->expect_return ) ) {
SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
}
return 1;
}
- if ( !oc->expect_return ) {
+ if ( !BACKSQL_IS_ADD( oc->expect_return ) ) {
+ SWORD ncols;
+ SQLINTEGER is_null;
+
/*
- * FIXME: need query to know the id of the inserted entry
+ * the query to know the id of the inserted entry
+ * must be embedded in the create procedure
*/
+ rc = SQLNumResultCols( sth, &ncols );
+ if ( rc != SQL_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+ "create_proc result evaluation failed\n",
+ 0, 0, 0 );
+ backsql_PrintErrors( bi->db_env, dbh, sth, rc);
+ SQLFreeStmt( sth, SQL_DROP );
+ send_ldap_result( conn, op, LDAP_OTHER, "",
+ "SQL-backend error", NULL, NULL );
+ return 1;
+
+ } else if ( ncols != 1 ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+ "create_proc result is bogus\n",
+ 0, 0, 0 );
+ backsql_PrintErrors( bi->db_env, dbh, sth, rc);
+ SQLFreeStmt( sth, SQL_DROP );
+ send_ldap_result( conn, op, LDAP_OTHER, "",
+ "SQL-backend error", NULL, NULL );
+ return 1;
+ }
+
+#if 0
+ {
+ SQLCHAR colname[ 64 ];
+ SQLSMALLINT name_len, col_type, col_scale, col_null;
+ UDWORD col_prec;
+
+ /*
+ * FIXME: check whether col_type is compatible,
+ * if it can be null and so on ...
+ */
+ rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
+ &colname[ 0 ],
+ (SQLUINTEGER)( sizeof( colname ) - 1 ),
+ &name_len, &col_type,
+ &col_prec, &col_scale, &col_null );
+ }
+#endif
+
+ rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
+ (SQLPOINTER)&new_keyval,
+ (SQLINTEGER)sizeof( new_keyval ),
+ &is_null );
+
+ rc = SQLFetch( sth );
+
+#if 0
+ /*
+ * FIXME: what does is_null mean?
+ */
+ if ( is_null ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+ "create_proc result is null\n",
+ 0, 0, 0 );
+ backsql_PrintErrors( bi->db_env, dbh, sth, rc);
+ SQLFreeStmt( sth, SQL_DROP );
+ send_ldap_result( conn, op, LDAP_OTHER, "",
+ "SQL-backend error", NULL, NULL );
+ return 1;
+ }
+#endif
}
#ifndef BACKSQL_REALLOC_STMT
#else /* BACKSQL_REALLOC_STMT */
SQLFreeStmt( sth, SQL_DROP );
#endif /* BACKSQL_REALLOC_STMT */
+
Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
"create_proc returned keyval=%ld\n", new_keyval, 0, 0 );
continue;
}
- at_rec = backsql_at_with_name( oc,
- at->a_desc->ad_cname.bv_val );
+ at_rec = backsql_ad2at( oc, at->a_desc );
if ( at_rec == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
"attribute '%s' is not registered "
"in objectclass '%s'\n",
- at->a_desc->ad_cname.bv_val, oc->name, 0 );
+ at->a_desc->ad_cname.bv_val,
+ oc->name.bv_val, 0 );
continue;
}
}
#endif /* BACKSQL_REALLOC_STMT */
- if ( at_rec->expect_return & BACKSQL_ADD ) {
+ if ( BACKSQL_IS_ADD( at_rec->expect_return ) ) {
pno = 1;
SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT,
SQL_C_ULONG, SQL_INTEGER,
pno = 0;
}
- po = ( at_rec->param_order & BACKSQL_ADD ) > 0;
+ po = ( BACKSQL_IS_ADD( at_rec->param_order ) ) > 0;
currpos = pno + 1 + po;
SQLBindParameter( sth, currpos,
SQL_PARAM_INPUT, SQL_C_ULONG,
backsql_BindParamStr( sth, currpos,
at_val->bv_val, at_val->bv_len + 1 );
-
+#ifdef SECURITY_PARANOID
+ Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+ "executing '%s', id=%ld\n",
+ at_rec->add_proc, new_keyval, 0 );
+#else
Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
"executing '%s' with val='%s', id=%ld\n",
at_rec->add_proc, at_val->bv_val, new_keyval );
+#endif
#ifndef BACKSQL_REALLOC_STMT
rc = SQLExecDirect( sth, at_rec->add_proc, SQL_NTS );
#else /* BACKSQL_REALLOC_STMT */
#endif /* BACKSQL_REALLOC_STMT */
}
- dnParent( &e->e_name, &pdn );
- res = backsql_dn2id( bi, &parent_id, dbh, &pdn );
- if ( res != LDAP_SUCCESS ) {
- /*
- * NO SUCH OBJECT seems more appropriate
- */
- Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
- "could not lookup parent entry for new record '%s'\n",
- pdn.bv_val, 0, 0 );
- send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
- return 1;
- }
#ifdef BACKSQL_REALLOC_STMT
rc = backsql_Prepare( dbh, &sth, bi->insentry_query, 0 );
if ( rc != SQL_SUCCESS ) {
}
SQLFreeStmt( sth, SQL_DROP );
+
+ /*
+ * Commit only if all operations succeed
+ *
+ * FIXME: backsql_add() does not fail if add operations
+ * are not available for some attributes, or if
+ * a multiple value add actually results in a replace,
+ * or if a single operation on an attribute fails
+ * for any reason
+ */
+ SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
+
send_ldap_result( conn, op, LDAP_SUCCESS, "",
NULL, NULL, NULL );
return 0;
Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry '%s'\n",
ndn->bv_val, 0, 0 );
- dbh = backsql_get_db_conn( be, conn );
- if ( !dbh ) {
+ res = backsql_get_db_conn( be, conn, &dbh );
+ if ( res != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
"could not get connection handle - exiting\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OTHER, "",
- "SQL-backend error", NULL, NULL );
+ send_ldap_result( conn, op, res, "",
+ res == LDAP_OTHER ? "SQL-backend error" : "",
+ NULL, NULL );
return 1;
}
return 1;
}
- oc = backsql_oc_with_id( bi, e_id.oc_id );
+ oc = backsql_id2oc( bi, e_id.oc_id );
if ( oc == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
"cannot determine objectclass of entry "
Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
"delete procedure is not defined "
"for this objectclass - aborting\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OTHER, "",
- "SQL-backend error", NULL, NULL );
+ send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
+ "operation not supported for required DN",
+ NULL, NULL );
return 1;
}
SQLAllocStmt( dbh, &sth );
- if ( oc->expect_return ) {
+ if ( BACKSQL_IS_DEL( oc->expect_return ) ) {
pno = 1;
SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
SQL_INTEGER, 0, 0, &rc, 0, 0 );
SQLBindParameter( sth, pno + 1, SQL_PARAM_INPUT,
SQL_C_ULONG, SQL_INTEGER, 0, 0, &e_id.keyval, 0, 0 );
-#if 0
- SQLBindParameter( sth, 2, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER,
- 0, 0, &retcode, 0, 0 );
-#endif
Debug( LDAP_DEBUG_TRACE, "backsql_delete(): executing '%s'\n",
oc->delete_proc, 0, 0 );
"SQL-backend error", NULL, NULL );
return 1;
}
+#ifndef BACKSQL_REALLOC_STMT
SQLFreeStmt( sth, SQL_RESET_PARAMS );
+#else /* BACKSQL_REALLOC_STMT */
+ SQLFreeStmt( sth, SQL_DROP );
+ SQLAllocStmt( dbh, &sth );
+#endif /* BACKSQL_REALLOC_STMT */
SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
0, 0, &e_id.id, 0, 0 );
}
SQLFreeStmt( sth, SQL_DROP );
+
+ /*
+ * Commit only if all operations succeed
+ *
+ * FIXME: backsql_add() does not fail if add operations
+ * are not available for some attributes, or if
+ * a multiple value add actually results in a replace,
+ * or if a single operation on an attribute fails
+ * for any reason
+ */
+ SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
+
send_ldap_result( conn, op, LDAP_SUCCESS, "", NULL, NULL, NULL );
Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );
return 0;
#include "back-sql.h"
#include "sql-wrap.h"
-int
-backsql_dummy( void )
-{
- return 0;
-}
-
int
backsql_compare(
BackendDB *bd,
drop table ldap_oc_mappings;
+drop sequence ldap_oc_mappings_id_seq;
create table ldap_oc_mappings
(
- id integer not null primary key,
+ id serial not null primary key,
name varchar(64) not null,
keytbl varchar(64) not null,
keycol varchar(64) not null,
);
drop table ldap_attr_mappings;
+drop sequence ldap_attr_mappings_id_seq;
create table ldap_attr_mappings
(
- id integer not null primary key,
+ id serial not null primary key,
oc_map_id integer not null references ldap_oc_mappings(id),
name varchar(255) not null,
sel_expr varchar(255) not null,
);
drop table ldap_entries;
+drop sequence ldap_entries_id_seq;
create table ldap_entries
(
- id integer not null primary key,
+ id serial not null primary key,
dn varchar(255) not null,
oc_map_id integer not null references ldap_oc_mappings(id),
parent int NOT NULL,
oc_name varchar(64)
);
------ Apparently PostgreSQL 7.0 does not know concat(); however,
------ back-sql can be configured to use '||' for string concatenation.
------ Those who can't live without concat() can uncomment this:
--- drop function concat(text, text);
--- create function concat(text, text) returns text as 'select $1 || $2;' language 'sql';
-
drop table persons;
-CREATE TABLE persons (
- id int NOT NULL,
- name varchar(255) NOT NULL,
- PRIMARY KEY ( id )
+drop sequence persons_id_seq;
+create table persons (
+ id serial not null primary key,
+ name varchar(255) not null,
+ surname varchar(255) not null
);
drop table institutes;
-CREATE TABLE institutes (
- id int NOT NULL,
- name varchar(255),
- PRIMARY KEY ( id )
+drop sequence institutes_id_seq;
+create table institutes (
+ id serial not null primary key,
+ name varchar(255)
);
drop table documents;
-CREATE TABLE documents (
- id int NOT NULL,
- title varchar(255) NOT NULL,
- abstract varchar(255),
- PRIMARY KEY ( id )
+drop sequence documents_id_seq;
+create table documents (
+ id serial not null primary key,
+ title varchar(255) not null,
+ abstract varchar(255)
);
drop table authors_docs;
-CREATE TABLE authors_docs (
- pers_id int NOT NULL,
- doc_id int NOT NULL,
- PRIMARY KEY ( pers_id, doc_id )
+create table authors_docs (
+ pers_id int not null,
+ doc_id int not null,
+ primary key ( pers_id, doc_id )
);
drop table phones;
-CREATE TABLE phones (
- id int NOT NULL ,
- phone varchar(255) NOT NULL ,
- pers_id int NOT NULL,
- PRIMARY KEY ( id )
+drop sequence phones_id_seq;
+create table phones (
+ id serial not null primary key,
+ phone varchar(255) not null ,
+ pers_id int not null
);
insert into institutes (id,name) values (1,'sql');
-insert into persons (id,name) values (1,'Mitya Kovalev');
-insert into persons (id,name) values (2,'Torvlobnor Puzdoy');
-insert into persons (id,name) values (3,'Akakiy Zinberstein');
+insert into persons (id,name,surname) values (1,'Mitya','Kovalev');
+insert into persons (id,name,surname) values (2,'Torvlobnor','Puzdoy');
+insert into persons (id,name,surname) values (3,'Akakiy','Zinberstein');
insert into phones (id,phone,pers_id) values (1,'332-2334',1);
insert into phones (id,phone,pers_id) values (2,'222-3234',1);
insert into authors_docs (pers_id,doc_id) values (1,1);
insert into authors_docs (pers_id,doc_id) values (1,2);
insert into authors_docs (pers_id,doc_id) values (2,1);
+
--mappings
-insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return) values (1,'inetOrgPerson','persons','id','select create_person()',NULL,0);
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return) values (1,'inetOrgPerson','persons','id','select create_person()','select delete_person(?)',0);
insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return) values (2,'document','documents','id',NULL,NULL,0);
insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return) values (3,'organization','institutes','id',NULL,NULL,0);
-insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (1,1,'cn','persons.name','persons',NULL,'update persons set name=? where id=?',NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (1,1,'cn','text(persons.name||'' ''||persons.surname)','persons',NULL,'select update_person_cn(?,?)',NULL,3,0);
-insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (2,1,'telephoneNumber','phones.phone','persons,phones','phones.pers_id=persons.id',NULL,NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (2,1,'telephoneNumber','phones.phone','persons,phones','phones.pers_id=persons.id','select add_phone(?,?)','select delete_phone(?,?)',3,0);
-insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (3,1,'sn','persons.name','persons',NULL,NULL,NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (3,1,'givenName','persons.name','persons',NULL,'update persons set name=? where id=?',NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (6,1,'sn','persons.surname','persons',NULL,'update persons set surname=? where id=?',NULL,3,0);
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (4,2,'description','documents.abstract','documents',NULL,NULL,NULL,3,0);
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (7,3,'o','institutes.name','institutes',NULL,NULL,NULL,3,0);
-insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (8,1,'documentDN','ldap_entries.dn','ldap_entries,documents,authors_docs,persons','ldap_entries.keyval=documents.id AND ldap_entries.oc_map_id=2 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',NULL,NULL,3,0);
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (8,1,'documentIdentifier','ldap_entries.dn','ldap_entries,documents,authors_docs,persons','ldap_entries.keyval=documents.id AND ldap_entries.oc_map_id=2 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',NULL,NULL,3,0);
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return) values (9,2,'documentAuthor','ldap_entries.dn','ldap_entries,documents,authors_docs,persons','ldap_entries.keyval=persons.id AND ldap_entries.oc_map_id=1 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',NULL,NULL,3,0);
-- procedures
create function create_person () returns int
- as 'insert into persons (id,name) values ((select max(id)+1 from persons),'''');
- select max(id) from persons'
-language 'sql';
+as '
+ select setval (''persons_id_seq'', (select max(id) from persons));
+ insert into persons (id,name,surname)
+ values (nextval(''persons_id_seq''),'''','''');
+ select max(id) from persons
+' language 'sql';
+
+create function update_person_cn (varchar, int) returns int
+as '
+ update persons set name = (
+ select case
+ when position('' '' in $1) = 0 then $1
+ else substr($1, 1, position('' '' in $1) - 1)
+ end
+ ),surname = (
+ select case
+ when position('' '' in $1) = 0 then ''''
+ else substr($1, position('' '' in $1) + 1)
+ end
+ ) where id = $2;
+ select $2 as return
+' language 'sql';
+
+create function delete_person (int) returns int
+as '
+ delete from phones where pers_id = $1;
+ delete from authors_docs where pers_id = $1;
+ delete from persons where id = $1;
+ select $1 as return
+' language 'sql';
+
+create function add_phone (varchar, int) returns int
+as '
+ select setval (''phones_id_seq'', (select max(id) from phones));
+ insert into phones (id,phone,pers_id)
+ values (nextval(''phones_id_seq''),$1,$2);
+ select max(id) from phones
+' language 'sql';
+
+create function delete_phone (varchar, int) returns int
+as '
+ delete from phones where phone = $1 and pers_id = $2;
+ select $2 as result
+' language 'sql';
#include <sys/types.h>
#include <string.h>
#include "slap.h"
+#include "ldap_pvt.h"
#include "back-sql.h"
#include "sql-wrap.h"
#include "schema-map.h"
#include "util.h"
-int backsql_dummy( void *, void * );
-
-int
+/*
+ * Deprecated
+ */
+#if 0
+static int
backsql_cmp_oc_name( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
{
- return strcasecmp( m1->name, m2->name );
+ return BACKSQL_NCMP( &m1->name, &m2->name );
}
+#endif
-int
+/*
+ * Uses the pointer to the ObjectClass structure
+ */
+static int
+backsql_cmp_oc( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
+{
+ return ( m1->oc < m2->oc ? -1 : ( m1->oc > m2->oc ? 1 : 0 ) );
+}
+
+static int
backsql_cmp_oc_id( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
{
- if ( m1->id < m2->id ) {
- return -1;
- }
- if ( m1->id > m2->id ) {
- return 1;
- }
- return 0;
+ return ( m1->id < m2->id ? -1 : ( m1->id > m2->id ? 1 : 0 ) );
}
-int
-backsql_cmp_attr(
- backsql_at_map_rec *m1,
- backsql_at_map_rec *m2 )
+/*
+ * Deprecated
+ */
+#if 0
+static int
+backsql_cmp_attr_name( backsql_at_map_rec *m1, backsql_at_map_rec *m2 )
{
- return strcasecmp( m1->name, m2->name );
+ return BACKSQL_NCMP( &m1->name, &m2->name );
}
+#endif
-char *
+/*
+ * Uses the pointer to the AttributeDescription structure
+ */
+static int
+backsql_cmp_attr( backsql_at_map_rec *m1, backsql_at_map_rec *m2 )
+{
+ return ( m1->ad < m2->ad ? -1 : ( m1->ad > m2->ad ? 1 : 0 ) );
+}
+
+static int
backsql_make_attr_query(
backsql_oc_map_rec *oc_map,
backsql_at_map_rec *at_map )
int tmpslen = 0;
backsql_strcat( &tmps, &tmpslen, "SELECT ", at_map->sel_expr,
- " AS ", at_map->name, " FROM ", at_map->from_tbls,
+ " AS ", at_map->name.bv_val,
+ " FROM ", at_map->from_tbls,
" WHERE ", oc_map->keytbl,".", oc_map->keycol,
"=?", NULL );
if ( at_map->join_where != NULL ) {
at_map->query = tmps.bv_val;
- return at_map->query;
+ return 0;
}
-int
+static int
backsql_add_sysmaps( backsql_oc_map_rec *oc_map )
{
backsql_at_map_rec *at_map;
at_map = (backsql_at_map_rec *)ch_calloc(1,
sizeof( backsql_at_map_rec ) );
- at_map->name = ch_strdup( "objectClass" );
+ at_map->ad = slap_schema.si_ad_objectClass;
+ ber_dupbv( &at_map->name, &at_map->ad->ad_cname );
at_map->sel_expr = ch_strdup( "ldap_entry_objclasses.oc_name" );
at_map->from_tbls = ch_strdup( "ldap_entry_objclasses,ldap_entries" );
len = strlen( at_map->from_tbls );
backsql_merge_from_clause( &at_map->from_tbls, &len, oc_map->keytbl );
+
len = 0;
bv.bv_val = NULL;
bv.bv_len = 0;
oc_map->keytbl, ".", oc_map->keycol,
" and ldap_entries.oc_map_id=", s, NULL );
at_map->join_where = bv.bv_val;
+
at_map->add_proc = NULL;
at_map->delete_proc = NULL;
at_map->param_order = 0;
at_map->expect_return = 0;
backsql_make_attr_query( oc_map, at_map );
avl_insert( &oc_map->attrs, at_map,
- (AVL_CMP)backsql_cmp_attr, backsql_dummy );
+ (AVL_CMP)backsql_cmp_attr, NULL );
at_map = (backsql_at_map_rec *)ch_calloc( 1,
sizeof( backsql_at_map_rec ) );
- at_map->name = ch_strdup( "ref" );
+ at_map->ad = slap_schema.si_ad_ref;
+ ber_dupbv( &at_map->name, &at_map->ad->ad_cname );
at_map->sel_expr = ch_strdup( "ldap_referrals.url" );
at_map->from_tbls = ch_strdup( "ldap_referrals,ldap_entries" );
len = strlen( at_map->from_tbls );
backsql_merge_from_clause( &at_map->from_tbls, &len,oc_map->keytbl );
- /* FIXME: no free? */
- at_map->join_where = NULL;
-
len = 0;
bv.bv_val = NULL;
bv.bv_len = 0;
oc_map->keytbl, ".", oc_map->keycol,
" and ldap_entries.oc_map_id=", s, NULL );
at_map->join_where = bv.bv_val;
+
at_map->add_proc = NULL;
at_map->delete_proc = NULL;
at_map->param_order = 0;
at_map->expect_return = 0;
backsql_make_attr_query( oc_map, at_map );
avl_insert( &oc_map->attrs, at_map,
- (AVL_CMP)backsql_cmp_attr, backsql_dummy );
+ (AVL_CMP)backsql_cmp_attr, NULL );
return 1;
}
"error preparing oc_query: '%s'\n",
si->oc_query, 0, 0 );
backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
- return -1;
+ return LDAP_OTHER;
}
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): at_query '%s'\n",
si->at_query, 0, 0 );
"error preparing at_query: '%s'\n",
si->at_query, 0, 0 );
backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
- return -1;
+ return LDAP_OTHER;
}
rc = backsql_BindParamID( at_sth, 1, &oc_id );
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"error binding param for at_query: \n", 0, 0, 0 );
backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
- return -1;
+ return LDAP_OTHER;
}
rc = SQLExecute( oc_sth );
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"error executing oc_query: \n", 0, 0, 0 );
backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
- return -1;
+ return LDAP_OTHER;
}
backsql_BindRowAsStrings( oc_sth, &oc_row );
for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( oc_sth ) ) {
oc_map = (backsql_oc_map_rec *)ch_calloc( 1,
sizeof( backsql_oc_map_rec ) );
+
oc_map->id = atoi( oc_row.cols[ 0 ] );
- oc_map->name = ch_strdup( oc_row.cols[ 1 ] );
+
+ ber_str2bv( oc_row.cols[ 1 ], 0, 1, &oc_map->name );
+ oc_map->oc = oc_bvfind( &oc_map->name );
+ if ( oc_map->oc == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
+ "objectClass '%s' is not defined in schema\n",
+ oc_map->name.bv_val, 0, 0 );
+ return LDAP_OTHER; /* undefined objectClass ? */
+ }
+
oc_map->keytbl = ch_strdup( oc_row.cols[ 2 ] );
oc_map->keycol = ch_strdup( oc_row.cols[ 3 ] );
oc_map->create_proc = ( oc_row.is_null[ 4 ] < 0 ) ? NULL
*/
oc_map->attrs = NULL;
- avl_insert( &si->oc_by_name, oc_map,
- (AVL_CMP)backsql_cmp_oc_name, backsql_dummy );
+ avl_insert( &si->oc_by_oc, oc_map,
+ (AVL_CMP)backsql_cmp_oc, NULL );
avl_insert( &si->oc_by_id, oc_map,
- (AVL_CMP)backsql_cmp_oc_id, backsql_dummy );
+ (AVL_CMP)backsql_cmp_oc_id, NULL );
oc_id = oc_map->id;
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"objectClass '%s': keytbl='%s' keycol='%s'\n",
- oc_map->name, oc_map->keytbl, oc_map->keycol );
- if ( oc_map->delete_proc ) {
- Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n",
- oc_map->delete_proc, 0, 0 );
- }
+ oc_map->name.bv_val, oc_map->keytbl, oc_map->keycol );
if ( oc_map->create_proc ) {
Debug( LDAP_DEBUG_TRACE, "create_proc='%s'\n",
oc_map->create_proc, 0, 0 );
}
- Debug( LDAP_DEBUG_TRACE, "expect_return=%d; attributes:\n",
- oc_map->expect_return, 0, 0 );
+ if ( oc_map->delete_proc ) {
+ Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n",
+ oc_map->delete_proc, 0, 0 );
+ }
+ Debug( LDAP_DEBUG_TRACE, "expect_return: "
+ "add=%s, del=%s; attributes:\n",
+ BACKSQL_IS_ADD( oc_map->expect_return ),
+ BACKSQL_IS_DEL( oc_map->expect_return ), 0 );
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"autoadding 'objectClass' and 'ref' mappings\n",
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"error executing at_query: \n", 0, 0, 0 );
backsql_PrintErrors( SQL_NULL_HENV, dbh, at_sth, rc );
- return -1;
+ 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;
+
Debug( LDAP_DEBUG_TRACE, "********'%s'\n",
at_row.cols[ 0 ], 0, 0 );
Debug( LDAP_DEBUG_TRACE,
at_row.cols[ 8 ], 0, 0 );
at_map = (backsql_at_map_rec *)ch_calloc( 1,
sizeof( backsql_at_map_rec ) );
- at_map->name = ch_strdup( at_row.cols[ 0 ] );
+ ber_str2bv( at_row.cols[ 0 ], 0, 1, &at_map->name );
+ rc = slap_bv2ad( &at_map->name, &at_map->ad, &text );
+ if ( rc != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
+ "attribute '%s' for objectClass '%s' "
+ "is not defined in schema: %s\n",
+ at_map->name.bv_val,
+ oc_map->name.bv_val, text );
+ return LDAP_CONSTRAINT_VIOLATION;
+ }
+
at_map->sel_expr = ch_strdup( at_row.cols[ 1 ] );
at_map->sel_expr_u = ( at_row.is_null[ 8 ] < 0 ) ? NULL
: ch_strdup( at_row.cols[ 8 ] );
"preconstructed query '%s'\n",
at_map->query, 0, 0 );
avl_insert( &oc_map->attrs, at_map,
- (AVL_CMP)backsql_cmp_attr,
- backsql_dummy );
+ (AVL_CMP)backsql_cmp_attr, NULL );
}
backsql_FreeRow( &at_row );
SQLFreeStmt( at_sth, SQL_CLOSE );
SQLFreeStmt( oc_sth, SQL_DROP );
si->schema_loaded = 1;
Debug( LDAP_DEBUG_TRACE, "<==load_schema_map()\n", 0, 0, 0 );
- return 1;
+ return LDAP_SUCCESS;
}
backsql_oc_map_rec *
-backsql_oc_with_name( backsql_info *si, char *objclass )
+backsql_oc2oc( backsql_info *si, ObjectClass *oc )
+{
+ backsql_oc_map_rec tmp, *res;
+
+#if 0
+ Debug( LDAP_DEBUG_TRACE, "==>backsql_oc2oc(): "
+ "searching for objectclass with name='%s'\n",
+ objclass, 0, 0 );
+#endif
+
+ tmp.oc = oc;
+ res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp,
+ (AVL_CMP)backsql_cmp_oc );
+#if 0
+ if ( res != NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
+ "found name='%s', id=%d\n", res->name, res->id, 0 );
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
+ "not found\n", 0, 0, 0 );
+ }
+#endif
+
+ return res;
+}
+
+/*
+ * Deprecated
+ */
+backsql_oc_map_rec *
+backsql_name2oc( backsql_info *si, struct berval *oc_name )
{
backsql_oc_map_rec tmp, *res;
"searching for objectclass with name='%s'\n",
objclass, 0, 0 );
#endif
-
- tmp.name = objclass;
- res = (backsql_oc_map_rec *)avl_find( si->oc_by_name, &tmp,
- (AVL_CMP)backsql_cmp_oc_name );
+
+ tmp.oc = oc_bvfind( oc_name );
+ if ( tmp.oc == NULL ) {
+ return NULL;
+ }
+
+ res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp,
+ (AVL_CMP)backsql_cmp_oc );
#if 0
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
}
backsql_oc_map_rec *
-backsql_oc_with_id( backsql_info *si, unsigned long id )
+backsql_id2oc( backsql_info *si, unsigned long id )
{
backsql_oc_map_rec tmp, *res;
}
backsql_at_map_rec *
-backsql_at_with_name( backsql_oc_map_rec* objclass, char *attr )
+backsql_ad2at( backsql_oc_map_rec* objclass, AttributeDescription *ad )
{
backsql_at_map_rec tmp, *res;
#if 0
- Debug( LDAP_DEBUG_TRACE, "==>at_with_name(): "
+ Debug( LDAP_DEBUG_TRACE, "==>backsql_ad2at(): "
"searching for attribute '%s' for objectclass '%s'\n",
attr, objclass->name, 0 );
#endif
- tmp.name = attr;
+ tmp.ad = ad;
res = (backsql_at_map_rec *)avl_find( objclass->attrs, &tmp,
(AVL_CMP)backsql_cmp_attr );
#if 0
if ( res != NULL ) {
- Debug( LDAP_DEBUG_TRACE, "<==at_with_name(): "
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
"found name='%s', sel_expr='%s'\n",
res->name, res->sel_expr, 0 );
} else {
- Debug( LDAP_DEBUG_TRACE, "<==at_with_name(): "
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
"not found\n", 0, 0, 0 );
}
#endif
return res;
}
-int
+/*
+ * Deprecated
+ */
+backsql_at_map_rec *
+backsql_name2at( backsql_oc_map_rec* objclass, struct berval *attr )
+{
+ backsql_at_map_rec tmp, *res;
+ const char *text = NULL;
+
+#if 0
+ Debug( LDAP_DEBUG_TRACE, "==>backsql_name2at(): "
+ "searching for attribute '%s' for objectclass '%s'\n",
+ attr, objclass->name, 0 );
+#endif
+
+ if ( slap_bv2ad( attr, &tmp.ad, &text ) != LDAP_SUCCESS ) {
+ return NULL;
+ }
+
+ res = (backsql_at_map_rec *)avl_find( objclass->attrs, &tmp,
+ (AVL_CMP)backsql_cmp_attr );
+
+#if 0
+ if ( res != NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_name2at(): "
+ "found name='%s', sel_expr='%s'\n",
+ res->name, res->sel_expr, 0 );
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_name2at(): "
+ "not found\n", 0, 0, 0 );
+ }
+#endif
+
+ return res;
+}
+
+static void
backsql_free_attr( backsql_at_map_rec *at )
{
- Debug( LDAP_DEBUG_TRACE, "==>free_attr(): '%s'\n", at->name, 0, 0 );
- ch_free( at->name );
+ Debug( LDAP_DEBUG_TRACE, "==>free_attr(): '%s'\n",
+ at->name.bv_val, 0, 0 );
+ ch_free( at->name.bv_val );
ch_free( at->sel_expr );
if ( at->from_tbls != NULL ) {
ch_free( at->from_tbls );
if ( at->query ) {
ch_free( at->query );
}
- ch_free( at );
/* TimesTen */
if ( at->sel_expr_u ) {
ch_free( at->sel_expr_u );
}
- Debug( LDAP_DEBUG_TRACE, "<==free_attr()\n", 0, 0, 0 );
+ ch_free( at );
- return 1;
+ Debug( LDAP_DEBUG_TRACE, "<==free_attr()\n", 0, 0, 0 );
}
-int
+static void
backsql_free_oc( backsql_oc_map_rec *oc )
{
- Debug( LDAP_DEBUG_TRACE, "==>free_oc(): '%s'\n", oc->name, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "==>free_oc(): '%s'\n",
+ oc->name.bv_val, 0, 0 );
avl_free( oc->attrs, (AVL_FREE)backsql_free_attr );
- ch_free( oc->name );
+ ch_free( oc->name.bv_val );
ch_free( oc->keytbl );
ch_free( oc->keycol );
if ( oc->create_proc != NULL ) {
ch_free( oc );
Debug( LDAP_DEBUG_TRACE, "<==free_oc()\n", 0, 0, 0 );
- return 1;
}
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, NULL );
avl_free( si->oc_by_id, (AVL_FREE)backsql_free_oc );
- avl_free( si->oc_by_name, (AVL_FREE)backsql_dummy );
Debug( LDAP_DEBUG_TRACE, "<==destroy_schema_map()\n", 0, 0, 0 );
return 0;
}
typedef struct {
- char *name;
+ struct berval name;
+ ObjectClass *oc;
char *keytbl;
char *keycol;
/* expected to return keyval of newly created entry */
typedef struct {
/* literal name of corresponding LDAP attribute type */
- char *name;
+ struct berval name;
+ AttributeDescription *ad;
char *from_tbls;
char *join_where;
char *sel_expr;
} backsql_at_map_rec;
/* defines to support bitmasks above */
-#define BACKSQL_ADD 1
-#define BACKSQL_DEL 2
+#define BACKSQL_ADD 0x1
+#define BACKSQL_DEL 0x2
+
+#define BACKSQL_IS_ADD(x) ( BACKSQL_ADD & (x) )
+#define BACKSQL_IS_DEL(x) ( BACKSQL_DEL & (x) )
+
+#define BACKSQL_NCMP(v1,v2) ber_bvcmp((v1),(v2))
int backsql_load_schema_map( backsql_info *si, SQLHDBC dbh );
-backsql_oc_map_rec *backsql_oc_with_name( backsql_info *si, char *objclass );
-backsql_oc_map_rec *backsql_oc_with_id( backsql_info *si, unsigned long id );
-backsql_at_map_rec *backsql_at_with_name( backsql_oc_map_rec *objclass,
- char *attr );
+/* Deprecated */
+backsql_oc_map_rec *backsql_name2oc( backsql_info *si, struct berval *oc_name );
+backsql_oc_map_rec *backsql_oc2oc( backsql_info *si, ObjectClass *oc );
+backsql_oc_map_rec *backsql_id2oc( backsql_info *si, unsigned long id );
+/* Deprecated */
+backsql_at_map_rec *backsql_name2at( backsql_oc_map_rec *objclass,
+ struct berval *at_name );
+backsql_at_map_rec *backsql_ad2at( backsql_oc_map_rec *objclass,
+ AttributeDescription *ad );
int backsql_destroy_schema_map( backsql_info *si );
#endif /* __BACKSQL_SCHEMA_MAP_H__ */
static struct berval AllUser = BER_BVC( LDAP_ALL_USER_ATTRIBUTES );
static struct berval AllOper = BER_BVC( LDAP_ALL_OPERATIONAL_ATTRIBUTES );
+static struct berval NoAttrs = BER_BVC( LDAP_NO_ATTRS );
+
#if 0
static struct berval NoAttrs = BER_BVC( LDAP_NO_ATTRS );
#endif
static int
-backsql_attrlist_add( backsql_srch_info *bsi, struct berval *at_name )
+backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad )
{
- int n_attrs = 0;
- char **tmp;
+ int n_attrs = 0;
+ AttributeName *an = NULL;
if ( bsi->attrs == NULL ) {
return 1;
}
- for ( ; bsi->attrs[ n_attrs ]; n_attrs++ ) {
+ for ( ; bsi->attrs[ n_attrs ].an_name.bv_val; n_attrs++ ) {
+ an = &bsi->attrs[ n_attrs ];
+
Debug( LDAP_DEBUG_TRACE, "==>backsql_attrlist_add(): "
"attribute '%s' is in list\n",
- bsi->attrs[ n_attrs ], 0, 0 );
+ an->an_name.bv_val, 0, 0 );
/*
* We can live with strcmp because the attribute
* list has been normalized before calling be_search
*/
- if ( !strcmp( bsi->attrs[ n_attrs ], at_name->bv_val ) ) {
+ if ( !BACKSQL_NCMP( &an->an_name, &ad->ad_cname ) ) {
return 1;
}
}
Debug( LDAP_DEBUG_TRACE, "==>backsql_attrlist_add(): "
- "adding '%s' to list\n", at_name->bv_val, 0, 0 );
- tmp = (char **)ch_realloc( bsi->attrs, (n_attrs + 2)*sizeof( char * ) );
- if ( tmp == NULL ) {
+ "adding '%s' to list\n", ad->ad_cname.bv_val, 0, 0 );
+
+ an = (AttributeName *)ch_realloc( bsi->attrs,
+ sizeof( AttributeName ) * ( n_attrs + 2 ) );
+ if ( an == NULL ) {
return -1;
}
- bsi->attrs = tmp;
- bsi->attrs[ n_attrs ] = ch_strdup( at_name->bv_val );
- bsi->attrs[ n_attrs + 1 ] = NULL;
+
+ an[ n_attrs ].an_name = ad->ad_cname;
+ an[ n_attrs ].an_desc = ad;
+ an[ n_attrs + 1 ].an_name.bv_val = NULL;
+ an[ n_attrs + 1 ].an_name.bv_len = 0;
+
+ bsi->attrs = an;
+
return 1;
}
bsi->attrs = NULL;
} else {
- bsi->attrs = (char **)ch_calloc( 1, sizeof( char * ) );
- bsi->attrs[ 0 ] = NULL;
+ bsi->attrs = (AttributeName *)ch_calloc( 1,
+ sizeof( AttributeName ) );
+ bsi->attrs[ 0 ].an_name.bv_val = NULL;
+ bsi->attrs[ 0 ].an_name.bv_len = 0;
for ( p = attrs; p->an_name.bv_val; p++ ) {
/*
* ignore "+"
*/
- if ( strcmp( p->an_name.bv_val, AllOper.bv_val ) == 0 ) {
+ if ( BACKSQL_NCMP( &p->an_name, &AllOper ) == 0
+ || BACKSQL_NCMP( &p->an_name, &NoAttrs ) == 0 ) {
continue;
}
- backsql_attrlist_add( bsi, &p->an_name );
+
+ backsql_attrlist_add( bsi, p->an_desc );
}
}
return 0;
}
- at = backsql_at_with_name( bsi->oc, f->f_sub_desc->ad_cname.bv_val );
+ at = backsql_ad2at( bsi->oc, f->f_sub_desc );
+
+ /*
+ * When dealing with case-sensitive strings
+ * we may omit normalization; however, normalized
+ * SQL filters are more liberal.
+ */
backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, "(" /* ) */ , NULL );
backsql_process_filter( backsql_srch_info *bsi, Filter *f )
{
backsql_at_map_rec *at;
- backsql_at_map_rec oc_attr
- = { "objectClass", "", "", NULL, NULL, NULL, NULL };
+ backsql_at_map_rec oc_attr = { BER_BVC("objectClass"),
+ slap_schema.si_ad_objectClass, "", "", NULL, NULL, NULL, NULL };
AttributeDescription *ad = NULL;
int done = 0, len = 0;
/* TimesTen */
}
if ( strcasecmp( ad->ad_cname.bv_val, "objectclass" ) ) {
- at = backsql_at_with_name( bsi->oc, ad->ad_cname.bv_val );
+ at = backsql_ad2at( bsi->oc, ad );
} else {
struct berval bv;
*/
bv.bv_val = at->sel_expr;
bv.bv_len = at->sel_expr ? strlen( at->sel_expr ) : 0;
- backsql_strcat( &bv, &len, "'", bsi->oc->name, "'", NULL );
+ backsql_strcat( &bv, &len, "'", bsi->oc->name.bv_val,
+ "'", NULL );
at->sel_expr = bv.bv_val;
}
if ( at == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_process_filter(): "
"attribute '%s' is not defined for objectclass '%s'\n",
- ad->ad_cname.bv_val, bsi->oc->name, 0 );
+ ad->ad_cname.bv_val, bsi->oc->name.bv_val, 0 );
backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
" 1=0 ", NULL );
goto impossible;
* need to add this attribute to list of attrs to load,
* so that we could do test_filter() later
*/
- backsql_attrlist_add( bsi, &ad->ad_cname );
+ backsql_attrlist_add( bsi, ad );
if ( at->join_where != NULL && strstr( bsi->join_where.bv_val, at->join_where ) == NULL ) {
backsql_strcat( &bsi->join_where, &bsi->jwhere_len,
#if 0
if ( at != &oc_attr ) {
backsql_strcat( &bsi->sel, &bsi->sel_len,
- ",", at->sel_expr, " AS ", at->name, NULL );
+ ",", at->sel_expr, " AS ",
+ at->name.bv_val, NULL );
}
#endif
backsql_strcat( &bsi->sel, &bsi->sel_len,
"SELECT DISTINCT ldap_entries.id,",
bsi->oc->keytbl, ".", bsi->oc->keycol,
- ",'", bsi->oc->name, "' AS objectClass",
+ ",'", bsi->oc->name.bv_val, "' AS objectClass",
",ldap_entries.dn AS dn", NULL );
#endif
backsql_strcat( &bsi->sel, &bsi->sel_len,
if ( bi->strcast_func ) {
backsql_strcat( &bsi->sel, &bsi->sel_len,
bi->strcast_func,
- "('", bsi->oc->name, "')", NULL );
+ "('", bsi->oc->name.bv_val, "')", NULL );
} else {
backsql_strcat( &bsi->sel, &bsi->sel_len,
- "'", bsi->oc->name, "'", NULL );
+ "'", bsi->oc->name.bv_val, "'", NULL );
}
backsql_strcat( &bsi->sel, &bsi->sel_len,
" AS objectClass,ldap_entries.dn AS dn", NULL );
char temp_base_dn[ BACKSQL_MAX_DN_LEN + 1 ];
Debug( LDAP_DEBUG_TRACE, "==>backsql_oc_get_candidates(): oc='%s'\n",
- oc->name, 0, 0 );
+ oc->name.bv_val, 0, 0 );
bsi->oc = oc;
if ( backsql_srch_query( bsi, &query ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
e = (Entry *)ch_calloc( 1, sizeof( Entry ) );
for ( i = 1; i < row.ncols; i++ ) {
if ( row.is_null[ i ] > 0 ) {
- backsql_entry_addattr( e, row.col_names[ i ],
- row.cols[ i ],
- row.col_prec[ i ] );
+ struct berval bv;
+
+ ber_str2bv( row.cols[ i ],
+ row.col_prec[ i ], 0, &bv );
+
+ backsql_entry_addattr( e,
+ &row.col_names[ i ], &bv );
+
Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
(int)row.col_prec[ i ], 0, 0 );
} else {
Debug( LDAP_DEBUG_TRACE,
"NULL value in this row "
"for attribute '%s'\n",
- row.col_names[ i ], 0, 0 );
+ &row.col_names[ i ], 0, 0 );
}
}
#endif
Debug( LDAP_DEBUG_TRACE, " deref=%d, attrsonly=%d, "
"attributes to load: %s\n",
deref, attrsonly, attrs == NULL ? "all" : "custom list" );
- dbh = backsql_get_db_conn( be, conn );
- if ( !dbh ) {
+ sres = backsql_get_db_conn( be, conn, &dbh );
+ if ( sres != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
"could not get connection handle - exiting\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OTHER, "",
- "SQL-backend error", NULL, NULL );
+ send_ldap_result( conn, op, sres, "",
+ sres == LDAP_OTHER ? "SQL-backend error" : "",
+ NULL, NULL );
return 1;
}
* of entries matching LDAP query filter and scope (or at least
* candidates), and get the IDs
*/
- avl_apply( bi->oc_by_name, (AVL_APPLY)backsql_oc_get_candidates,
+ avl_apply( bi->oc_by_oc, (AVL_APPLY)backsql_oc_get_candidates,
&srch_info, 0, AVL_INORDER );
if ( !isroot && limit->lms_s_unchecked != -1 ) {
for ( eid = srch_info.id_list; eid != NULL;
eid = backsql_free_entryID( eid, 1 ) );
- charray_free( srch_info.attrs );
+ ch_free( srch_info.attrs );
Debug( LDAP_DEBUG_TRACE, "<==backsql_search()\n", 0, 0, 0 );
return 0;
typedef struct {
SWORD ncols;
- char **col_names;
+ BerVarray col_names;
UDWORD *col_prec;
char **cols;
SQLINTEGER *is_null;
#include <stdio.h>
#include "ac/string.h"
#include <sys/types.h>
-#include "ldap_pvt.h"
#include "slap.h"
+#include "ldap_pvt.h"
#include "back-sql.h"
#include "sql-types.h"
#include "sql-wrap.h"
SQLHDBC dbh;
} backsql_db_conn;
-int backsql_dummy( void *, void * );
-
void
backsql_PrintErrors( SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth, int rc )
{
Debug( LDAP_DEBUG_TRACE, "==>_SQLPrepare()\n", 0, 0, 0 );
#endif
- SQLGetInfo( dbh, SQL_DRIVER_NAME, drv_name, 30, &len );
+ SQLGetInfo( dbh, SQL_DRIVER_NAME, drv_name, sizeof( drv_name ), &len );
#if 0
Debug( LDAP_DEBUG_TRACE, "_SQLPrepare(): driver name='%s'\n",
drv_name, 0, 0 );
#endif
-
- if ( !strncmp( ldap_pvt_str2upper( drv_name ), "SQLSRV32.DLL", 30 ) ) {
+
+ ldap_pvt_str2upper( drv_name );
+ if ( !strncmp( drv_name, "SQLSRV32.DLL", sizeof( drv_name ) ) ) {
/*
* stupid default result set in MS SQL Server
* does not support multiple active statements
SQL_CONCUR_ROWVER );
if ( rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO ) {
Debug( LDAP_DEBUG_TRACE, "_SQLPrepare(): "
- "SQLSetStmtOption(SQL_CONCURRENCY,SQL_CONCUR_ROWVER) failed:\n",
+ "SQLSetStmtOption(SQL_CONCURRENCY,"
+ "SQL_CONCUR_ROWVER) failed:\n",
0, 0, 0 );
backsql_PrintErrors( SQL_NULL_HENV, dbh, *sth, rc );
}
}
#if 0
+/*
+ * Turned into macros --- see sql-wrap.h
+ */
RETCODE
backsql_BindParamStr( SQLHSTMT sth, int par_ind, char *str, int maxlen )
{
"ncols=%d\n", (int)row->ncols, 0, 0 );
#endif
- row->col_names = (char **)ch_calloc( row->ncols,
+ row->col_names = (BerVarray)ch_calloc( row->ncols + 1,
+ sizeof( struct berval ) );
+ row->cols = (char **)ch_calloc( row->ncols + 1,
sizeof( char * ) );
- row->cols = (char **)ch_calloc( row->ncols, sizeof( char * ) );
row->col_prec = (UDWORD *)ch_calloc( row->ncols,
sizeof( UDWORD ) );
row->is_null = (SQLINTEGER *)ch_calloc( row->ncols,
sizeof( SQLINTEGER ) );
for ( i = 1; i <= row->ncols; i++ ) {
rc = SQLDescribeCol( sth, (SQLSMALLINT)i, &colname[ 0 ],
- (SQLUINTEGER)sizeof( colname ) - 1,
+ (SQLUINTEGER)( sizeof( colname ) - 1 ),
&name_len, &col_type,
&col_prec, &col_scale, &col_null );
- row->col_names[ i - 1 ] = ch_strdup( colname );
+ ber_str2bv( colname, 0, 1, &row->col_names[ i - 1 ] );
#if 0
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"col_name=%s, col_prec[%d]=%d\n",
&row->is_null[ i - 1 ] );
}
}
+
+ row->col_names[ i - 1 ].bv_val = NULL;
+ row->col_names[ i - 1 ].bv_len = 0;
+ row->cols[ i - 1 ] = NULL;
}
#if 0
Debug( LDAP_DEBUG_TRACE, "<== backsql_BindRowAsStrings()\n", 0, 0, 0 );
RETCODE
backsql_FreeRow( BACKSQL_ROW_NTS *row )
{
- int i;
-
if ( row->cols == NULL ) {
return SQL_ERROR;
}
- for ( i = 0; i < row->ncols; i++ ) {
- /*
- * FIXME: we need to free the col_names as well, don't we?
- */
- free( row->cols[ i ] );
- }
-
- free( row->col_names );
+ ber_bvarray_free( row->col_names );
+ charray_free( row->cols );
free( row->col_prec );
- free( row->cols );
free( row->is_null );
return SQL_SUCCESS;
}
-int
+static int
backsql_cmp_connid( backsql_db_conn *c1, backsql_db_conn *c2 )
{
if ( c1->ldap_cid > c2->ldap_cid ) {
return 0;
}
-int
+static int
backsql_close_db_conn( backsql_db_conn *conn )
{
Debug( LDAP_DEBUG_TRACE, "==>backsql_close_db_conn()\n", 0, 0, 0 );
+ /*
+ * Default transact is SQL_ROLLBACK; commit is required only
+ * by write operations, and it is explicitly performed after
+ * each atomic operation succeeds.
+ */
+
/* TimesTen */
- SQLTransact( SQL_NULL_HENV, conn->dbh, SQL_COMMIT );
+ SQLTransact( SQL_NULL_HENV, conn->dbh, SQL_ROLLBACK );
SQLDisconnect( conn->dbh );
SQLFreeConnect( conn->dbh );
Debug( LDAP_DEBUG_TRACE, "<==backsql_close_db_conn()\n", 0, 0, 0 );
return SQL_SUCCESS;
}
-backsql_db_conn *
-backsql_open_db_conn( backsql_info *si, int ldap_cid )
+static int
+backsql_open_db_conn( backsql_info *si, int ldap_cid, backsql_db_conn **pdbc )
{
/* TimesTen */
char DBMSName[ 32 ];
backsql_db_conn *dbc;
int rc;
+
+ assert( pdbc );
+ *pdbc = NULL;
Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_conn()\n", 0, 0, 0 );
dbc = (backsql_db_conn *)ch_calloc( 1, sizeof( backsql_db_conn ) );
dbc->ldap_cid = ldap_cid;
rc = SQLAllocConnect( si->db_env, &dbc->dbh );
- if (!BACKSQL_SUCCESS( rc ) ) {
+ if ( !BACKSQL_SUCCESS( rc ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
"SQLAllocConnect() failed:\n", 0, 0, 0 );
backsql_PrintErrors( si->db_env, SQL_NULL_HDBC,
SQL_NULL_HENV, rc );
- return NULL;
+ return LDAP_UNAVAILABLE;
}
rc = SQLConnect( dbc->dbh, si->dbname, SQL_NTS, si->dbuser,
"succeeded with info" : "failed" );
backsql_PrintErrors( si->db_env, dbc->dbh, SQL_NULL_HENV, rc );
if ( rc != SQL_SUCCESS_WITH_INFO ) {
- return NULL;
+ return LDAP_UNAVAILABLE;
}
}
Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(): "
"connected, adding to tree\n", 0, 0, 0 );
ldap_pvt_thread_mutex_lock( &si->dbconn_mutex );
- avl_insert( &si->db_conns, dbc, (AVL_CMP)backsql_cmp_connid,
- backsql_dummy );
+ avl_insert( &si->db_conns, dbc, (AVL_CMP)backsql_cmp_connid, NULL );
ldap_pvt_thread_mutex_unlock( &si->dbconn_mutex );
Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_conn()\n", 0, 0, 0 );
- return dbc;
+ *pdbc = dbc;
+
+ return LDAP_SUCCESS;
}
int
return SQL_SUCCESS;
}
-SQLHDBC
-backsql_get_db_conn( Backend *be, Connection *ldapc )
+int
+backsql_get_db_conn( Backend *be, Connection *ldapc, SQLHDBC *dbh )
{
backsql_info *si = (backsql_info *)be->be_private;
backsql_db_conn *dbc;
backsql_db_conn tmp;
+ int rc = LDAP_SUCCESS;
Debug( LDAP_DEBUG_TRACE, "==>backsql_get_db_conn()\n", 0, 0, 0 );
+ assert( dbh );
+ *dbh = SQL_NULL_HDBC;
+
tmp.ldap_cid = ldapc->c_connid;
/*
dbc = (backsql_db_conn *)avl_find( si->db_conns, &tmp,
(AVL_CMP)backsql_cmp_connid );
if ( !dbc ) {
- dbc = backsql_open_db_conn( si, ldapc->c_connid );
- }
-
- if ( !dbc ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
- "could not get connection handle -- returning NULL\n",
- 0, 0, 0 );
- return SQL_NULL_HDBC;
+ rc = backsql_open_db_conn( si, ldapc->c_connid, &dbc );
+ if ( rc != LDAP_SUCCESS) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
+ "could not get connection handle "
+ "-- returning NULL\n", 0, 0, 0 );
+ return rc;
+ }
}
+
ldap_pvt_thread_mutex_lock( &si->schema_mutex );
if ( !si->schema_loaded ) {
Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
"first call -- reading schema map\n", 0, 0, 0 );
- backsql_load_schema_map( si, dbc->dbh );
+ rc = backsql_load_schema_map( si, dbc->dbh );
+ if ( rc != LDAP_SUCCESS ) {
+ backsql_free_db_conn( be, ldapc );
+ return rc;
+ }
}
ldap_pvt_thread_mutex_unlock( &si->schema_mutex );
+ *dbh = dbc->dbh;
+
Debug( LDAP_DEBUG_TRACE, "<==backsql_get_db_conn()\n", 0, 0, 0 );
- return dbc->dbh;
+
+ return LDAP_SUCCESS;
}
#endif /* SLAPD_SQL */
+
int backsql_init_db_env( backsql_info *si );
int backsql_free_db_env( backsql_info *si );
-SQLHDBC backsql_get_db_conn( Backend *be, Connection *ldapc );
+int backsql_get_db_conn( Backend *be, Connection *ldapc, SQLHDBC *dbh );
int backsql_free_db_conn( Backend *be, Connection *ldapc );
#endif /* __BACKSQL_SQL_WRAP_H__ */
#include "ac/ctype.h"
#include "ac/stdarg.h"
#include "slap.h"
+#include "lber_pvt.h"
+#include "ldap_pvt.h"
#include "back-sql.h"
#include "schema-map.h"
#include "util.h"
/* TimesTen */
char backsql_check_dn_ru_query[] = "SELECT dn_ru from ldap_entries";
+/*
+ * Frequently used constants
+ */
+struct berval
+ bv_n_objectclass = BER_BVC("objectclass"),
+ bv_n_0_10 = BER_BVC("0.10");
+
struct berval *
backsql_strcat( struct berval *dest, int *buflen, ... )
{
int
backsql_entry_addattr(
Entry *e,
- char *at_name,
- char *at_val,
- unsigned int at_val_len )
+ struct berval *at_name,
+ struct berval *at_val )
{
struct berval add_val[ 2 ];
AttributeDescription *ad;
const char *text;
Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(): "
- "at_name='%s', at_val='%s'\n", at_name, at_val, 0 );
- add_val[ 0 ].bv_val = at_val;
- add_val[ 0 ].bv_len = at_val_len;
+ "at_name='%s', at_val='%s'\n",
+ at_name->bv_val, at_val->bv_val, 0 );
+ add_val[ 0 ] = *at_val;
add_val[ 1 ].bv_val = NULL;
add_val[ 1 ].bv_len = 0;
ad = NULL;
- rc = slap_str2ad( at_name, &ad, &text );
+ rc = slap_bv2ad( at_name, &ad, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(): "
"failed to find AttributeDescription for '%s'\n",
- at_name, 0, 0 );
+ at_name->bv_val, 0, 0 );
return 0;
}
if ( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(): "
"failed to merge value '%s' for attribute '%s'\n",
- at_val, at_name, 0 );
+ at_val->bv_val, at_name->bv_val, 0 );
return 0;
}
#define BACKSQL_STR_GROW 64
+extern struct berval
+ bv_n_objectclass,
+ bv_n_0_10;
+
struct berval *backsql_strcat( struct berval *dest, int *buflen, ... );
-int backsql_entry_addattr( Entry *e, char *at_name, char *at_val,
- unsigned int at_val_len );
+int backsql_entry_addattr( Entry *e, struct berval *at_name,
+ struct berval *at_val );
typedef struct __backsql_srch_info {
struct berval *base_dn;
Backend *be;
Connection *conn;
Operation *op;
- char **attrs;
+ AttributeName *attrs;
Entry *e;
/* 1 if the db is TimesTen; 0 if it's not */
int isTimesTen;