]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-sql/add.c
Merge remote branch 'origin/mdb.master'
[openldap] / servers / slapd / back-sql / add.c
index 96a9ef10df6ed6e72c510d474b9e8ad64aa53388..7fd485988bc71581d74f17d57d7b1784c65ef5c2 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1999-2005 The OpenLDAP Foundation.
+ * Copyright 1999-2012 The OpenLDAP Foundation.
  * Portions Copyright 1999 Dmitry Kovalev.
  * Portions Copyright 2002 Pierangelo Masarati.
  * Portions Copyright 2004 Mark Adamson.
  * - operational attributes
  * - empty attributes
  */
+#define backsql_opattr_skip(ad) \
+       (is_at_operational( (ad)->ad_type ) && (ad) != slap_schema.si_ad_ref )
 #define        backsql_attr_skip(ad, vals) \
        ( \
                ( (ad) == slap_schema.si_ad_objectClass \
                                && (vals) && BER_BVISNULL( &((vals)[ 1 ]) ) ) \
-               || is_at_operational( (ad)->ad_type ) \
+               || backsql_opattr_skip( (ad) ) \
                || ( (vals) && BER_BVISNULL( &((vals)[ 0 ]) ) ) \
        )
 
@@ -64,7 +66,7 @@ backsql_modify_delete_all_values(
        SQLHSTMT        asth = SQL_NULL_HSTMT;
        BACKSQL_ROW_NTS row;
 
-       assert( at );
+       assert( at != NULL );
        if ( at->bam_delete_proc == NULL ) {
                Debug( LDAP_DEBUG_TRACE,
                        "   backsql_modify_delete_all_values(): "
@@ -89,11 +91,8 @@ backsql_modify_delete_all_values(
                backsql_PrintErrors( bi->sql_db_env, dbh, 
                                asth, rc );
 
-               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                       rs->sr_text = "SQL-backend error";
-                       return rs->sr_err = LDAP_OTHER;
-               }
-               return LDAP_SUCCESS;
+               rs->sr_text = "SQL-backend error";
+               return rs->sr_err = LDAP_OTHER;
        }
 
        rc = backsql_BindParamID( asth, 1, SQL_PARAM_INPUT, &e_id->eid_keyval );
@@ -107,12 +106,8 @@ backsql_modify_delete_all_values(
                                asth, rc );
                SQLFreeStmt( asth, SQL_DROP );
 
-               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                       rs->sr_text = "SQL-backend error";
-                       return rs->sr_err = LDAP_OTHER;
-               }
-
-               return LDAP_SUCCESS;
+               rs->sr_text = "SQL-backend error";
+               return rs->sr_err = LDAP_OTHER;
        }
                        
        rc = SQLExecute( asth );
@@ -125,24 +120,21 @@ backsql_modify_delete_all_values(
                                asth, rc );
                SQLFreeStmt( asth, SQL_DROP );
 
-               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                       rs->sr_text = "SQL-backend error";
-                       return rs->sr_err = LDAP_OTHER;
-               }
-
-               return LDAP_SUCCESS;
+               rs->sr_text = "SQL-backend error";
+               return rs->sr_err = LDAP_OTHER;
        }
 
-       backsql_BindRowAsStrings( asth, &row );
+       backsql_BindRowAsStrings_x( asth, &row, op->o_tmpmemctx );
        for ( rc = SQLFetch( asth );
                        BACKSQL_SUCCESS( rc );
                        rc = SQLFetch( asth ) )
        {
-               int                     i;
+               int             i;
                /* first parameter no, parameter order */
-               SQLUSMALLINT            pno, po;
+               SQLUSMALLINT    pno = 0,
+                               po = 0;
                /* procedure return code */
-               int                     prc = LDAP_SUCCESS;
+               int             prc = LDAP_SUCCESS;
                
                for ( i = 0; i < row.ncols; i++ ) {
                        SQLHSTMT        sth = SQL_NULL_HSTMT;
@@ -159,12 +151,9 @@ backsql_modify_delete_all_values(
                                backsql_PrintErrors( bi->sql_db_env, dbh, 
                                                sth, rc );
 
-                               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                                       rs->sr_text = "SQL-backend error";
-                                       return rs->sr_err = LDAP_OTHER;
-                               }
-
-                               continue;
+                               rs->sr_text = "SQL-backend error";
+                               rs->sr_err = LDAP_OTHER;
+                               goto done;
                        }
 
                        if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
@@ -180,16 +169,10 @@ backsql_modify_delete_all_values(
                                                sth, rc );
                                        SQLFreeStmt( sth, SQL_DROP );
 
-                                       if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                                               rs->sr_text = "SQL-backend error";
-                                               return rs->sr_err = LDAP_OTHER;
-                                       }
-
-                                       continue;
+                                       rs->sr_text = "SQL-backend error";
+                                       rs->sr_err = LDAP_OTHER;
+                                       goto done;
                                }
-
-                       } else {
-                               pno = 0;
                        }
                        po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
                        rc = backsql_BindParamID( sth, pno + 1 + po,
@@ -203,24 +186,16 @@ backsql_modify_delete_all_values(
                                        sth, rc );
                                SQLFreeStmt( sth, SQL_DROP );
 
-                               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                                       rs->sr_text = "SQL-backend error";
-                                       return rs->sr_err = LDAP_OTHER;
-                               }
-
-                               continue;
+                               rs->sr_text = "SQL-backend error";
+                               rs->sr_err = LDAP_OTHER;
+                               goto done;
                        }
-#ifdef BACKSQL_ARBITRARY_KEY
-                       Debug( LDAP_DEBUG_TRACE,
-                               "   backsql_modify_delete_all_values() "
-                               "arg%d=%s\n",
-                               pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
-#else /* ! BACKSQL_ARBITRARY_KEY */
+
                        Debug( LDAP_DEBUG_TRACE,
                                "   backsql_modify_delete_all_values() "
-                               "arg%d=%lu\n",
-                               pno + 1 + po, e_id->eid_keyval, 0 );
-#endif /* ! BACKSQL_ARBITRARY_KEY */
+                               "arg(%d)=" BACKSQL_IDFMT "\n",
+                               pno + 1 + po,
+                               BACKSQL_IDARG(e_id->eid_keyval), 0 );
 
                        /*
                         * check for syntax needed here 
@@ -238,17 +213,14 @@ backsql_modify_delete_all_values(
                                        sth, rc );
                                SQLFreeStmt( sth, SQL_DROP );
 
-                               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                                       rs->sr_text = "SQL-backend error";
-                                       return rs->sr_err = LDAP_OTHER;
-                               }
-
-                               continue;
+                               rs->sr_text = "SQL-backend error";
+                               rs->sr_err = LDAP_OTHER;
+                               goto done;
                        }
         
                        Debug( LDAP_DEBUG_TRACE, 
                                "   backsql_modify_delete_all_values(): "
-                               "arg%d=%s; executing \"%s\"\n",
+                               "arg(%d)=%s; executing \"%s\"\n",
                                pno + 2 - po, row.cols[ i ],
                                at->bam_delete_proc );
                        rc = SQLExecute( sth );
@@ -265,29 +237,27 @@ backsql_modify_delete_all_values(
                                        /* SQL procedure executed fine 
                                         * but returned an error */
                                        rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
-                                       rs->sr_text = op->ora_e->e_name.bv_val;
-                                       SQLFreeStmt( sth, SQL_DROP );
-                                       return rs->sr_err;
 
                                } else {
                                        backsql_PrintErrors( bi->sql_db_env, dbh,
                                                        sth, rc );
-                                       if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) 
-                                       {
-                                               rs->sr_err = LDAP_OTHER;
-                                               rs->sr_text = op->ora_e->e_name.bv_val;
-                                               SQLFreeStmt( sth, SQL_DROP );
-                                               return rs->sr_err;
-                                       }
+                                       rs->sr_err = LDAP_OTHER;
                                }
+                               rs->sr_text = op->o_req_dn.bv_val;
+                               SQLFreeStmt( sth, SQL_DROP );
+                               goto done;
                        }
                        SQLFreeStmt( sth, SQL_DROP );
                }
        }
-       backsql_FreeRow( &row );
+
+       rs->sr_err = LDAP_SUCCESS;
+
+done:;
+       backsql_FreeRow_x( &row, op->o_tmpmemctx );
        SQLFreeStmt( asth, SQL_DROP );
 
-       return LDAP_SUCCESS;
+       return rs->sr_err;
 }
 
 int
@@ -299,9 +269,8 @@ backsql_modify_internal(
        backsql_entryID         *e_id,
        Modifications           *modlist )
 {
-       backsql_info    *bi = (backsql_info*)op->o_bd->be_private;
+       backsql_info    *bi = (backsql_info *)op->o_bd->be_private;
        RETCODE         rc;
-       SQLHSTMT        sth = SQL_NULL_HSTMT;
        Modifications   *ml;
 
        Debug( LDAP_DEBUG_TRACE, "==>backsql_modify_internal(): "
@@ -316,15 +285,11 @@ backsql_modify_internal(
 #if 0
                /* NOTE: some day we'll have to pass 
                 * the normalized values as well */
-               BerVarray               nvalues;
+               BerVarray               sm_nvalues;
 #endif
                backsql_at_map_rec      *at = NULL;
                struct berval           *at_val;
                int                     i;
-               /* first parameter position, parameter order */
-               SQLUSMALLINT            pno, po;
-               /* procedure return code */
-               int                     prc = LDAP_SUCCESS;
                
                ad = ml->sml_mod.sm_desc;
                sm_op = ( ml->sml_mod.sm_op & LDAP_MOD_OP );
@@ -406,7 +371,7 @@ backsql_modify_internal(
 
                                goto add_only;
                        }
-                       
+
 del_all:
                        rs->sr_err = backsql_modify_delete_all_values( op, rs, dbh, e_id, at );
                        if ( rs->sr_err != LDAP_SUCCESS ) {
@@ -424,6 +389,7 @@ del_all:
                 */
                case LDAP_MOD_ADD:
                /* case SLAP_MOD_SOFTADD: */
+               /* case SLAP_MOD_ADD_IF_NOT_PRESENT: */
 add_only:;
                        if ( at->bam_add_proc == NULL ) {
                                Debug( LDAP_DEBUG_TRACE,
@@ -453,6 +419,13 @@ add_only:;
                                        !BER_BVISNULL( at_val ); 
                                        i++, at_val++ )
                        {
+                               SQLHSTMT        sth = SQL_NULL_HSTMT;
+                               /* first parameter position, parameter order */
+                               SQLUSMALLINT    pno = 0,
+                                               po;
+                               /* procedure return code */
+                               int             prc = LDAP_SUCCESS;
+
                                rc = backsql_Prepare( dbh, &sth, at->bam_add_proc, 0 );
                                if ( rc != SQL_SUCCESS ) {
                                        Debug( LDAP_DEBUG_TRACE,
@@ -483,9 +456,6 @@ add_only:;
                                                rs->sr_err = LDAP_OTHER;
                                                goto done;
                                        }
-        
-                               } else {
-                                       pno = 0;
                                }
                                po = ( BACKSQL_IS_ADD( at->bam_param_order ) ) > 0;
                                rc = backsql_BindParamID( sth, pno + 1 + po,
@@ -503,17 +473,12 @@ add_only:;
                                        rs->sr_err = LDAP_OTHER;
                                        goto done;
                                }
-#ifdef BACKSQL_ARBITRARY_KEY
-                               Debug( LDAP_DEBUG_TRACE,
-                                       "   backsql_modify_internal(): "
-                                       "arg%d=\"%s\"\n", 
-                                       pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
-#else /* ! BACKSQL_ARBITRARY_KEY */
+
                                Debug( LDAP_DEBUG_TRACE,
                                        "   backsql_modify_internal(): "
-                                       "arg%d=\"%lu\"\n", 
-                                       pno + 1 + po, e_id->eid_keyval, 0 );
-#endif /* ! BACKSQL_ARBITRARY_KEY */
+                                       "arg(%d)=" BACKSQL_IDFMT "\n", 
+                                       pno + 1 + po,
+                                       BACKSQL_IDARG(e_id->eid_keyval), 0 );
 
                                /*
                                 * check for syntax needed here
@@ -536,24 +501,40 @@ add_only:;
                                }
                                Debug( LDAP_DEBUG_TRACE,
                                        "   backsql_modify_internal(): "
-                                       "arg%d=\"%s\"; executing \"%s\"\n", 
+                                       "arg(%d)=\"%s\"; executing \"%s\"\n", 
                                        pno + 2 - po, at_val->bv_val,
                                        at->bam_add_proc );
 
                                rc = SQLExecute( sth );
-                               if ( rc != SQL_SUCCESS ) {
+                               if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
+                                       rs->sr_err = LDAP_SUCCESS;
+
+                               } else {
                                        Debug( LDAP_DEBUG_TRACE,
                                                "   backsql_modify_internal(): "
-                                               "add_proc execution failed\n",
-                                               0, 0, 0 );
-                                       backsql_PrintErrors( bi->sql_db_env,
-                                                       dbh, sth, rc );
-
-                                       if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+                                               "add_proc execution failed "
+                                               "(rc=%d, prc=%d)\n",
+                                               rc, prc, 0 );
+                                       if ( prc != LDAP_SUCCESS ) {
+                                               /* SQL procedure executed fine 
+                                                * but returned an error */
                                                SQLFreeStmt( sth, SQL_DROP );
-                                               rs->sr_err = LDAP_OTHER;
-                                               rs->sr_text = "SQL-backend error";
-                                               goto done;
+
+                                               rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
+                                               rs->sr_text = at->bam_ad->ad_cname.bv_val;
+                                               return rs->sr_err;
+                                       
+                                       } else {
+                                               backsql_PrintErrors( bi->sql_db_env, dbh,
+                                                               sth, rc );
+                                               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) 
+                                               {
+                                                       SQLFreeStmt( sth, SQL_DROP );
+
+                                                       rs->sr_err = LDAP_OTHER;
+                                                       rs->sr_text = "SQL-backend error";
+                                                       goto done;
+                                               }
                                        }
                                }
                                SQLFreeStmt( sth, SQL_DROP );
@@ -561,6 +542,7 @@ add_only:;
                        break;
                        
                case LDAP_MOD_DELETE:
+               /* case SLAP_MOD_SOFTDEL: */
                        if ( at->bam_delete_proc == NULL ) {
                                Debug( LDAP_DEBUG_TRACE,
                                        "   backsql_modify_internal(): "
@@ -596,7 +578,13 @@ add_only:;
                                        !BER_BVISNULL( at_val );
                                        i++, at_val++ )
                        {
-                               prc = LDAP_SUCCESS;
+                               SQLHSTMT        sth = SQL_NULL_HSTMT;
+                               /* first parameter position, parameter order */
+                               SQLUSMALLINT    pno = 0,
+                                               po;
+                               /* procedure return code */
+                               int             prc = LDAP_SUCCESS;
+
                                rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
                                if ( rc != SQL_SUCCESS ) {
                                        Debug( LDAP_DEBUG_TRACE,
@@ -627,9 +615,6 @@ add_only:;
                                                rs->sr_err = LDAP_OTHER;
                                                goto done;
                                        }
-
-                               } else {
-                                       pno = 0;
                                }
                                po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
                                rc = backsql_BindParamID( sth, pno + 1 + po,
@@ -647,17 +632,12 @@ add_only:;
                                        rs->sr_err = LDAP_OTHER;
                                        goto done;
                                }
-#ifdef BACKSQL_ARBITRARY_KEY
-                               Debug( LDAP_DEBUG_TRACE,
-                                       "   backsql_modify_internal(): "
-                                       "arg%d=\"%s\"\n", 
-                                       pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
-#else /* ! BACKSQL_ARBITRARY_KEY */
+
                                Debug( LDAP_DEBUG_TRACE,
                                        "   backsql_modify_internal(): "
-                                       "arg%d=\"%lu\"\n", 
-                                       pno + 1 + po, e_id->eid_keyval, 0 );
-#endif /* ! BACKSQL_ARBITRARY_KEY */
+                                       "arg(%d)=" BACKSQL_IDFMT "\n", 
+                                       pno + 1 + po,
+                                       BACKSQL_IDARG(e_id->eid_keyval), 0 );
 
                                /*
                                 * check for syntax needed here 
@@ -674,11 +654,9 @@ add_only:;
                                                sth, rc );
                                        SQLFreeStmt( sth, SQL_DROP );
 
-                                       if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                                               rs->sr_text = "SQL-backend error";
-                                               rs->sr_err = LDAP_OTHER;
-                                               goto done;
-                                       }
+                                       rs->sr_text = "SQL-backend error";
+                                       rs->sr_err = LDAP_OTHER;
+                                       goto done;
                                }
 
                                Debug( LDAP_DEBUG_TRACE,
@@ -707,13 +685,10 @@ add_only:;
                                        } else {
                                                backsql_PrintErrors( bi->sql_db_env,
                                                                dbh, sth, rc );
-                                               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) )
-                                               {
-                                                       SQLFreeStmt( sth, SQL_DROP );
-                                                       rs->sr_err = LDAP_OTHER;
-                                                       rs->sr_text = at->bam_ad->ad_cname.bv_val;
-                                                       goto done;
-                                               }
+                                               SQLFreeStmt( sth, SQL_DROP );
+                                               rs->sr_err = LDAP_OTHER;
+                                               rs->sr_text = at->bam_ad->ad_cname.bv_val;
+                                               goto done;
                                        }
                                }
                                SQLFreeStmt( sth, SQL_DROP );
@@ -751,7 +726,7 @@ backsql_add_attr(
        SQLHDBC                 dbh,
        backsql_oc_map_rec      *oc,
        Attribute               *at,
-       unsigned long           new_keyval )
+       backsql_key_t           new_keyval )
 {
        backsql_info            *bi = (backsql_info*)op->o_bd->be_private;
        backsql_at_map_rec      *at_rec = NULL;
@@ -806,7 +781,7 @@ backsql_add_attr(
                int             prc = LDAP_SUCCESS;
                /* first parameter #, parameter order */
                SQLUSMALLINT    pno, po;
-               char            logbuf[] = "val[18446744073709551615UL], id=18446744073709551615UL";
+               char            logbuf[ STRLENOF("val[], id=") + 2*LDAP_PVT_INTTYPE_CHARS(unsigned long)];
                
                /*
                 * Do not deal with the objectClass that is used
@@ -821,13 +796,8 @@ backsql_add_attr(
 
                rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 );
                if ( rc != SQL_SUCCESS ) {
-
-                       if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                               rs->sr_text = "SQL-backend error";
-                               return rs->sr_err = LDAP_OTHER;
-                       }
-
-                       return LDAP_SUCCESS;
+                       rs->sr_text = "SQL-backend error";
+                       return rs->sr_err = LDAP_OTHER;
                }
 
                if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) {
@@ -836,18 +806,14 @@ backsql_add_attr(
                        if ( rc != SQL_SUCCESS ) {
                                Debug( LDAP_DEBUG_TRACE,
                                        "   backsql_add_attr(): "
-                                       "error binding output parameter for %s[%d]\n",
+                                       "error binding output parameter for %s[%lu]\n",
                                        at_rec->bam_ad->ad_cname.bv_val, i, 0 );
                                backsql_PrintErrors( bi->sql_db_env, dbh, 
                                        sth, rc );
                                SQLFreeStmt( sth, SQL_DROP );
 
-                               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                                       rs->sr_text = "SQL-backend error";
-                                       return rs->sr_err = LDAP_OTHER;
-                               }
-
-                               return LDAP_SUCCESS;
+                               rs->sr_text = "SQL-backend error";
+                               return rs->sr_err = LDAP_OTHER;
                        }
 
                } else {
@@ -856,23 +822,19 @@ backsql_add_attr(
 
                po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0;
                currpos = pno + 1 + po;
-               rc = backsql_BindParamInt( sth, currpos,
+               rc = backsql_BindParamNumID( sth, currpos,
                                SQL_PARAM_INPUT, &new_keyval );
                if ( rc != SQL_SUCCESS ) {
                        Debug( LDAP_DEBUG_TRACE,
                                "   backsql_add_attr(): "
-                               "error binding keyval parameter for %s[%d]\n",
+                               "error binding keyval parameter for %s[%lu]\n",
                                at_rec->bam_ad->ad_cname.bv_val, i, 0 );
                        backsql_PrintErrors( bi->sql_db_env, dbh, 
                                sth, rc );
                        SQLFreeStmt( sth, SQL_DROP );
 
-                       if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                               rs->sr_text = "SQL-backend error";
-                               return rs->sr_err = LDAP_OTHER;
-                       }
-
-                       return LDAP_SUCCESS;
+                       rs->sr_text = "SQL-backend error";
+                       return rs->sr_err = LDAP_OTHER;
                }
 
                currpos = pno + 2 - po;
@@ -886,27 +848,25 @@ backsql_add_attr(
                if ( rc != SQL_SUCCESS ) {
                        Debug( LDAP_DEBUG_TRACE,
                                "   backsql_add_attr(): "
-                               "error binding value parameter for %s[%d]\n",
+                               "error binding value parameter for %s[%lu]\n",
                                at_rec->bam_ad->ad_cname.bv_val, i, 0 );
                        backsql_PrintErrors( bi->sql_db_env, dbh, 
                                sth, rc );
                        SQLFreeStmt( sth, SQL_DROP );
 
-                       if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                               rs->sr_text = "SQL-backend error";
-                               return rs->sr_err = LDAP_OTHER;
-                       }
-
-                       return LDAP_SUCCESS;
+                       rs->sr_text = "SQL-backend error";
+                       return rs->sr_err = LDAP_OTHER;
                }
 
 #ifdef LDAP_DEBUG
-               snprintf( logbuf, sizeof( logbuf ), "val[%lu], id=%lu",
-                               i, new_keyval );
-               Debug( LDAP_DEBUG_TRACE, "   backsql_add_attr(\"%s\"): "
-                       "executing \"%s\" %s\n", 
-                       op->ora_e->e_name.bv_val,
-                       at_rec->bam_add_proc, logbuf );
+               if ( LogTest( LDAP_DEBUG_TRACE ) ) {
+                       snprintf( logbuf, sizeof( logbuf ), "val[%lu], id=" BACKSQL_IDNUMFMT,
+                                       i, new_keyval );
+                       Debug( LDAP_DEBUG_TRACE, "   backsql_add_attr(\"%s\"): "
+                               "executing \"%s\" %s\n", 
+                               op->ora_e->e_name.bv_val,
+                               at_rec->bam_add_proc, logbuf );
+               }
 #endif
                rc = SQLExecute( sth );
                if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
@@ -928,12 +888,10 @@ backsql_add_attr(
                        } else {
                                backsql_PrintErrors( bi->sql_db_env, dbh,
                                                sth, rc );
-                               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                                       rs->sr_err = LDAP_OTHER;
-                                       rs->sr_text = op->ora_e->e_name.bv_val;
-                                       SQLFreeStmt( sth, SQL_DROP );
-                                       return rs->sr_err;
-                               }
+                               rs->sr_err = LDAP_OTHER;
+                               rs->sr_text = op->ora_e->e_name.bv_val;
+                               SQLFreeStmt( sth, SQL_DROP );
+                               return rs->sr_err;
                        }
                }
                SQLFreeStmt( sth, SQL_DROP );
@@ -948,27 +906,34 @@ backsql_add( Operation *op, SlapReply *rs )
        backsql_info            *bi = (backsql_info*)op->o_bd->be_private;
        SQLHDBC                 dbh = SQL_NULL_HDBC;
        SQLHSTMT                sth = SQL_NULL_HSTMT;
-       unsigned long           new_keyval = 0;
+       backsql_key_t           new_keyval = 0;
        RETCODE                 rc;
        backsql_oc_map_rec      *oc = NULL;
-       backsql_srch_info       bsi;
+       backsql_srch_info       bsi = { 0 };
        Entry                   p = { 0 }, *e = NULL;
        Attribute               *at,
                                *at_objectClass = NULL;
+       ObjectClass             *soc = NULL;
+       struct berval           scname = BER_BVNULL;
        struct berval           pdn;
        struct berval           realdn = BER_BVNULL;
        int                     colnum;
        slap_mask_t             mask;
 
+       char                    textbuf[ SLAP_TEXT_BUFLEN ];
+       size_t                  textlen = sizeof( textbuf );
+
 #ifdef BACKSQL_SYNCPROV
        /*
         * NOTE: fake successful result to force contextCSN to be bumped up
         */
        if ( op->o_sync ) {
-               char            buf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
-               struct berval   csn = BER_BVNULL;
+               char            buf[ LDAP_PVT_CSNSTR_BUFSIZE ];
+               struct berval   csn;
 
-               slap_get_csn( op, buf, sizeof( buf ), &csn, 1 );
+               csn.bv_val = buf;
+               csn.bv_len = sizeof( buf );
+               slap_get_csn( op, &csn, 1 );
 
                rs->sr_err = LDAP_SUCCESS;
                send_ldap_result( op, rs );
@@ -983,12 +948,11 @@ backsql_add( Operation *op, SlapReply *rs )
                        op->ora_e->e_name.bv_val, 0, 0 );
 
        /* check schema */
-       if ( global_schemacheck ) {
+       if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
                char            textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
 
-               rs->sr_err = entry_schema_check( op->o_bd, op->ora_e,
-                               NULL,
-                               &rs->sr_text, textbuf, sizeof( textbuf ) );
+               rs->sr_err = entry_schema_check( op, op->ora_e, NULL, 0, 1, NULL,
+                       &rs->sr_text, textbuf, sizeof( textbuf ) );
                if ( rs->sr_err != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
                                "entry failed schema check -- aborting\n",
@@ -998,7 +962,20 @@ backsql_add( Operation *op, SlapReply *rs )
                }
        }
 
-       /* search structural objectClass */
+       slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
+
+       if ( get_assert( op ) &&
+               ( test_filter( op, op->ora_e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
+       {
+               Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
+                       "assertion control failed -- aborting\n",
+                       op->ora_e->e_name.bv_val, 0, 0 );
+               e = NULL;
+               rs->sr_err = LDAP_ASSERTION_FAILED;
+               goto done;
+       }
+
+       /* search structuralObjectClass */
        for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
                if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
                        break;
@@ -1006,16 +983,49 @@ backsql_add( Operation *op, SlapReply *rs )
        }
 
        /* there must exist */
-       assert( at != NULL );
+       if ( at == NULL ) {
+               char            buf[ SLAP_TEXT_BUFLEN ];
+               const char      *text;
+
+               /* search structuralObjectClass */
+               for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
+                       if ( at->a_desc == slap_schema.si_ad_objectClass ) {
+                               break;
+                       }
+               }
+
+               if ( at == NULL ) {
+                       Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
+                               "no objectClass\n",
+                               op->ora_e->e_name.bv_val, 0, 0 );
+                       rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
+                       e = NULL;
+                       goto done;
+               }
+
+               rs->sr_err = structural_class( at->a_vals, &soc, NULL,
+                               &text, buf, sizeof( buf ), op->o_tmpmemctx );
+               if ( rs->sr_err != LDAP_SUCCESS ) {
+                       Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
+                               "%s (%d)\n",
+                               op->ora_e->e_name.bv_val, text, rs->sr_err );
+                       e = NULL;
+                       goto done;
+               }
+               scname = soc->soc_cname;
+
+       } else {
+               scname = at->a_vals[0];
+       }
 
        /* I guess we should play with sub/supertypes to find a suitable oc */
-       oc = backsql_name2oc( bi, &at->a_vals[0] );
+       oc = backsql_name2oc( bi, &scname );
 
        if ( oc == NULL ) {
                Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
                        "cannot map structuralObjectClass \"%s\" -- aborting\n",
                        op->ora_e->e_name.bv_val,
-                       at->a_vals[0].bv_val, 0 );
+                       scname.bv_val, 0 );
                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                rs->sr_text = "operation not permitted within namingContext";
                e = NULL;
@@ -1027,7 +1037,7 @@ backsql_add( Operation *op, SlapReply *rs )
                        "create procedure is not defined "
                        "for structuralObjectClass \"%s\" - aborting\n",
                        op->ora_e->e_name.bv_val,
-                       at->a_vals[0].bv_val, 0 );
+                       scname.bv_val, 0 );
                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                rs->sr_text = "operation not permitted within namingContext";
                e = NULL;
@@ -1040,13 +1050,23 @@ backsql_add( Operation *op, SlapReply *rs )
                        "but none is defined for structuralObjectClass \"%s\" "
                        "- aborting\n",
                        op->ora_e->e_name.bv_val,
-                       at->a_vals[0].bv_val, 0 );
+                       scname.bv_val, 0 );
                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                rs->sr_text = "operation not permitted within namingContext";
                e = NULL;
                goto done;
        }
 
+       /* check write access */
+       if ( !access_allowed_mask( op, op->ora_e,
+                               slap_schema.si_ad_entry,
+                               NULL, ACL_WADD, NULL, &mask ) )
+       {
+               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+               e = op->ora_e;
+               goto done;
+       }
+
        rs->sr_err = backsql_get_db_conn( op, &dbh );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
@@ -1060,7 +1080,7 @@ backsql_add( Operation *op, SlapReply *rs )
 
        /*
         * Check if entry exists
-       *
+        *
         * NOTE: backsql_api_dn2odbc() is called explicitly because
         * we need the mucked DN to pass it to the create procedure.
         */
@@ -1093,53 +1113,34 @@ backsql_add( Operation *op, SlapReply *rs )
 
        } else {
                dnParent( &op->ora_e->e_nname, &pdn );
-       }
 
-       /*
-        * Get the parent
-        */
-       bsi.bsi_e = &p;
-       rs->sr_err = backsql_init_search( &bsi, &pdn,
-                       LDAP_SCOPE_BASE, 
-                       SLAP_NO_LIMIT, SLAP_NO_LIMIT,
-                       (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
-                       ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
-       if ( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
-                       "could not retrieve addDN parent "
-                       "\"%s\" ID - %s matched=\"%s\"\n", 
-                       pdn.bv_val,
-                       rs->sr_err == LDAP_REFERRAL ? "referral" : "no such entry",
-                       rs->sr_matched ? rs->sr_matched : "(null)" );
-               e = &p;
-               goto done;
-       }
-
-       /* check "children" pseudo-attribute access to parent */
-       if ( !access_allowed( op, &p, slap_schema.si_ad_children,
-                               NULL, ACL_WRITE, NULL ) )
-       {
-               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-               e = &p;
-               goto done;
-       }
-
-       if ( get_assert( op ) &&
-               ( test_filter( op, op->oq_add.rs_e, get_assertion( op ) )
-                       != LDAP_COMPARE_TRUE ) )
-       {
-               rs->sr_err = LDAP_ASSERTION_FAILED;
-               e = op->ora_e;
-               goto done;
-       }
+               /*
+                * Get the parent
+                */
+               bsi.bsi_e = &p;
+               rs->sr_err = backsql_init_search( &bsi, &pdn,
+                               LDAP_SCOPE_BASE, 
+                               (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
+                               ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
+               if ( rs->sr_err != LDAP_SUCCESS ) {
+                       Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+                               "could not retrieve addDN parent "
+                               "\"%s\" ID - %s matched=\"%s\"\n", 
+                               pdn.bv_val,
+                               rs->sr_err == LDAP_REFERRAL ? "referral" : "no such entry",
+                               rs->sr_matched ? rs->sr_matched : "(null)" );
+                       e = &p;
+                       goto done;
+               }
 
-       if ( !access_allowed_mask( op, op->ora_e,
-                               slap_schema.si_ad_entry,
-                               NULL, ACL_WRITE, NULL, &mask ) )
-       {
-               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
-               e = op->ora_e;
-               goto done;
+               /* check "children" pseudo-attribute access to parent */
+               if ( !access_allowed( op, &p, slap_schema.si_ad_children,
+                                       NULL, ACL_WADD, NULL ) )
+               {
+                       rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+                       e = &p;
+                       goto done;
+               }
        }
 
        /*
@@ -1158,7 +1159,7 @@ backsql_add( Operation *op, SlapReply *rs )
 
        colnum = 1;
        if ( BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
-               rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &new_keyval );
+               rc = backsql_BindParamNumID( sth, 1, SQL_PARAM_OUTPUT, &new_keyval );
                if ( rc != SQL_SUCCESS ) {
                        Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
                                "error binding keyval parameter "
@@ -1218,7 +1219,7 @@ backsql_add( Operation *op, SlapReply *rs )
 
        if ( !BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
                SWORD           ncols;
-               SQLINTEGER      value_len;
+               SQLLEN          value_len;
 
                if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
                        SQLFreeStmt( sth, SQL_DROP );
@@ -1309,37 +1310,9 @@ backsql_add( Operation *op, SlapReply *rs )
        SQLFreeStmt( sth, SQL_DROP );
 
        Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
-               "create_proc returned keyval=%ld\n",
+               "create_proc returned keyval=" BACKSQL_IDNUMFMT "\n",
                op->ora_e->e_name.bv_val, new_keyval, 0 );
 
-       for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
-               Debug( LDAP_DEBUG_TRACE, "   backsql_add(): "
-                       "adding attribute \"%s\"\n", 
-                       at->a_desc->ad_cname.bv_val, 0, 0 );
-
-               /*
-                * Skip:
-                * - the first occurrence of objectClass, which is used
-                *   to determine how to build the SQL entry (FIXME ?!?)
-                * - operational attributes
-                * - empty attributes (FIXME ?!?)
-                */
-               if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
-                       continue;
-               }
-
-               if ( at->a_desc == slap_schema.si_ad_objectClass ) {
-                       at_objectClass = at;
-                       continue;
-               }
-
-               rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at, new_keyval );
-               if ( rs->sr_err != LDAP_SUCCESS ) {
-                       e = op->ora_e;
-                       goto done;
-               }
-       }
-
        rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_stmt, 0 );
        if ( rc != SQL_SUCCESS ) {
                rs->sr_err = LDAP_OTHER;
@@ -1364,7 +1337,7 @@ backsql_add( Operation *op, SlapReply *rs )
                goto done;
        }
 
-       rc = backsql_BindParamInt( sth, 2, SQL_PARAM_INPUT, &oc->bom_id );
+       rc = backsql_BindParamNumID( sth, 2, SQL_PARAM_INPUT, &oc->bom_id );
        if ( rc != SQL_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
                        "error binding objectClass ID parameter "
@@ -1398,7 +1371,7 @@ backsql_add( Operation *op, SlapReply *rs )
                goto done;
        }
 
-       rc = backsql_BindParamInt( sth, 4, SQL_PARAM_INPUT, &new_keyval );
+       rc = backsql_BindParamNumID( sth, 4, SQL_PARAM_INPUT, &new_keyval );
        if ( rc != SQL_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
                        "error binding entry ID parameter "
@@ -1415,17 +1388,17 @@ backsql_add( Operation *op, SlapReply *rs )
                goto done;
        }
 
-       Debug( LDAP_DEBUG_TRACE, "   backsql_add(): executing \"%s\" for dn \"%s\"\n",
-                       bi->sql_insentry_stmt, op->ora_e->e_name.bv_val, 0 );
-#ifdef BACKSQL_ARBITRARY_KEY
-       Debug( LDAP_DEBUG_TRACE, "                  for oc_map_id=%ld, "
-                       "p_id=%s, keyval=%ld\n",
-                       oc->bom_id, bsi.bsi_base_id.eid_id.bv_val, new_keyval );
-#else /* ! BACKSQL_ARBITRARY_KEY */
-       Debug( LDAP_DEBUG_TRACE, "                  for oc_map_id=%ld, "
-                       "p_id=%ld, keyval=%ld\n",
-                       oc->bom_id, bsi.bsi_base_id.eid_id, new_keyval );
-#endif /* ! BACKSQL_ARBITRARY_KEY */
+       if ( LogTest( LDAP_DEBUG_TRACE ) ) {
+               char buf[ SLAP_TEXT_BUFLEN ];
+
+               snprintf( buf, sizeof(buf),
+                       "executing \"%s\" for dn=\"%s\"  oc_map_id=" BACKSQL_IDNUMFMT " p_id=" BACKSQL_IDFMT " keyval=" BACKSQL_IDNUMFMT,
+                       bi->sql_insentry_stmt, op->ora_e->e_name.bv_val,
+                       oc->bom_id, BACKSQL_IDARG(bsi.bsi_base_id.eid_id),
+                       new_keyval );
+               Debug( LDAP_DEBUG_TRACE, "   backsql_add(): %s\n", buf, 0, 0 );
+       }
+
        rc = SQLExecute( sth );
        if ( rc != SQL_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
@@ -1445,6 +1418,34 @@ backsql_add( Operation *op, SlapReply *rs )
 
        SQLFreeStmt( sth, SQL_DROP );
 
+       for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
+               Debug( LDAP_DEBUG_TRACE, "   backsql_add(): "
+                       "adding attribute \"%s\"\n", 
+                       at->a_desc->ad_cname.bv_val, 0, 0 );
+
+               /*
+                * Skip:
+                * - the first occurrence of objectClass, which is used
+                *   to determine how to build the SQL entry (FIXME ?!?)
+                * - operational attributes
+                * - empty attributes (FIXME ?!?)
+                */
+               if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
+                       continue;
+               }
+
+               if ( at->a_desc == slap_schema.si_ad_objectClass ) {
+                       at_objectClass = at;
+                       continue;
+               }
+
+               rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at, new_keyval );
+               if ( rs->sr_err != LDAP_SUCCESS ) {
+                       e = op->ora_e;
+                       goto done;
+               }
+       }
+
        if ( at_objectClass ) {
                rs->sr_err = backsql_add_attr( op, rs, dbh, oc,
                                at_objectClass, new_keyval );
@@ -1462,6 +1463,7 @@ done:;
                SQLUSMALLINT    CompletionType = SQL_ROLLBACK;
 
                if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
+                       assert( e == NULL );
                        CompletionType = SQL_COMMIT;
                }
 
@@ -1479,7 +1481,6 @@ done:;
         * in deleting that row.
         */
 
-#ifdef SLAP_ACL_HONOR_DISCLOSE
        if ( e != NULL ) {
                int     disclose = 1;
 
@@ -1504,9 +1505,13 @@ done:;
                        }
                }
        }
-#endif /* SLAP_ACL_HONOR_DISCLOSE */
+
+       if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) {
+               rs->sr_err = LDAP_X_NO_OPERATION;
+       }
 
        send_ldap_result( op, rs );
+       slap_graduate_commit_csn( op );
 
        if ( !BER_BVISNULL( &realdn )
                        && realdn.bv_val != op->ora_e->e_name.bv_val )
@@ -1515,11 +1520,11 @@ done:;
        }
 
        if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
-               (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
+               (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
        }
 
        if ( !BER_BVISNULL( &p.e_nname ) ) {
-               entry_clean( &p );
+               backsql_entry_clean( op, &p );
        }
 
        Debug( LDAP_DEBUG_TRACE, "<==backsql_add(\"%s\"): %d \"%s\"\n",