-#include "slap.h"
-#include "ldap_pvt.h"
-#include "back-sql.h"
-#include "sql-wrap.h"
-#include "schema-map.h"
-#include "entry-id.h"
-#include "util.h"
-
-/*
- * PostgreSQL 7.0 doesn't work without :(
- */
-#define BACKSQL_REALLOC_STMT
-
-/*
- * Skip:
- * - the first occurrence of objectClass, which is used
- * to determine how to build the SQL entry (FIXME ?!?)
- * - operational attributes
- * empty attributes (FIXME ?!?)
- */
-#define backsql_attr_skip(ad,vals) \
- ( \
- ( (ad) == slap_schema.si_ad_objectClass \
- && (vals)[ 1 ].bv_val == NULL ) \
- || is_at_operational( (ad)->ad_type ) \
- || ( (vals)[ 0 ].bv_val == NULL ) \
- )
-
-static int
-backsql_modify_internal(
- Operation *op,
- SlapReply *rs,
- SQLHDBC dbh,
- backsql_oc_map_rec *oc,
- backsql_entryID *e_id,
- Modifications *modlist )
-{
- backsql_info *bi = (backsql_info*)op->o_bd->be_private;
- RETCODE rc;
- SQLHSTMT sth;
- Modifications *ml;
-
- Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
- "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 ) {
- 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;
- ad = c_mod->sm_desc;
-
- Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
- "modifying attribute '%s'\n",
- ad->ad_cname.bv_val, 0, 0 );
-
- if ( backsql_attr_skip( ad, c_mod->sm_bvalues ) ) {
- continue;
- }
-
- at = backsql_ad2at( oc, ad );
- if ( at == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
- "attribute provided is not registered "
- "in objectClass '%s'\n",
- ad->ad_cname.bv_val, 0, 0 );
-
- if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
- rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
- rs->sr_text = "operation not permitted "
- "within namingContext";
- goto done;
- }
-
- continue;
- }
-
- switch( c_mod->sm_op ) {
- case LDAP_MOD_REPLACE: {
- SQLHSTMT asth;
- BACKSQL_ROW_NTS row;
-
- Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
- "replacing values for attribute '%s'\n",
- at->ad->ad_cname.bv_val, 0, 0 );
-
- if ( at->add_proc == NULL ) {
- Debug( LDAP_DEBUG_TRACE,
- "backsql_modify_internal(): "
- "add procedure is not defined "
- "for attribute '%s' "
- "- unable to perform replacements\n",
- at->ad->ad_cname.bv_val, 0, 0 );
-
- if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
- rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
- rs->sr_text = "operation not permitted "
- "within namingContext";
- goto done;
- }
-
- break;
- }
-
- if ( at->delete_proc == NULL ) {
- Debug( LDAP_DEBUG_TRACE,
- "backsql_modify_internal(): "
- "delete procedure is not defined "
- "for attribute '%s' "
- "- adding only\n",
- at->ad->ad_cname.bv_val, 0, 0 );
-
- if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
- rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
- rs->sr_text = "operation not permitted "
- "within namingContext";
- goto done;
- }
-
- goto add_only;
- }
-
-del_all:
- rc = backsql_Prepare( dbh, &asth, at->query, 0 );
- if ( rc != SQL_SUCCESS ) {
- Debug( LDAP_DEBUG_TRACE,
- "backsql_modify_internal(): "
- "error preparing query\n", 0, 0, 0 );
- backsql_PrintErrors( bi->db_env, dbh,
- asth, rc );
-
- if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
- rs->sr_err = LDAP_OTHER;
- rs->sr_text = "SQL-backend error";
- goto done;
- }
-
- break;
- }
-
- rc = backsql_BindParamID( asth, 1, &e_id->keyval );
- if ( rc != SQL_SUCCESS ) {
- Debug( LDAP_DEBUG_TRACE,
- "backsql_modify_internal(): "
- "error binding key value parameter\n",
- 0, 0, 0 );
- backsql_PrintErrors( bi->db_env, dbh,
- asth, rc );
- SQLFreeStmt( asth, SQL_DROP );
-
- if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
- rs->sr_err = LDAP_OTHER;
- rs->sr_text = "SQL-backend error";
- goto done;
- }
-
- break;
- }
-
- rc = SQLExecute( asth );
- if ( !BACKSQL_SUCCESS( rc ) ) {
- Debug( LDAP_DEBUG_TRACE,
- "backsql_modify_internal(): "
- "error executing attribute query\n",
- 0, 0, 0 );
- backsql_PrintErrors( bi->db_env, dbh,
- asth, rc );
- SQLFreeStmt( asth, SQL_DROP );
-
- if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
- rs->sr_err = LDAP_OTHER;
- rs->sr_text = "SQL-backend error";
- goto done;
- }
-
- break;
- }
-
- backsql_BindRowAsStrings( asth, &row );
- rc = SQLFetch( asth );
- for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( asth ) ) {
- for ( i = 0; i < row.ncols; i++ ) {
- if ( BACKSQL_IS_DEL( at->expect_return ) ) {
- pno = 1;
- SQLBindParameter(sth, 1,
- SQL_PARAM_OUTPUT,
- SQL_C_ULONG,
- SQL_INTEGER,
- 0, 0, &prc, 0, 0 );
- } else {
- pno = 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 );
-
- /*
- * check for syntax needed here
- * maybe need binary bind?
- */
- SQLBindParameter(sth, pno + 2 - po,
- SQL_PARAM_INPUT,
- SQL_C_CHAR, SQL_CHAR,
- 0, 0, row.cols[ i ],
- strlen( row.cols[ i ] ), 0 );
-
- Debug( LDAP_DEBUG_TRACE,
- "backsql_modify_internal(): "
- "executing '%s'\n",
- at->delete_proc, 0, 0 );
- rc = SQLExecDirect( sth,
- at->delete_proc, SQL_NTS );
- if ( rc != SQL_SUCCESS ) {
- Debug( LDAP_DEBUG_TRACE,
- "backsql_modify_internal(): "
- "delete_proc "
- "execution failed\n",
- 0, 0, 0 );
- backsql_PrintErrors( bi->db_env,
- dbh, sth, rc );
-
- if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
- rs->sr_err = LDAP_OTHER;
- rs->sr_text = "SQL-backend error";
- goto done;
- }
- }
-#ifdef BACKSQL_REALLOC_STMT
- SQLFreeStmt( sth, SQL_DROP );
- SQLAllocStmt( dbh, &sth );
-#endif /* BACKSQL_REALLOC_STMT */
- }
- }
- backsql_FreeRow( &row );
- SQLFreeStmt( asth, SQL_DROP );
- }
-
- /*
- * 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_internal(): "
- "add procedure is not defined "
- "for attribute '%s'\n",
- at->ad->ad_cname.bv_val, 0, 0 );