]> git.sur5r.net Git - openldap/commitdiff
apply patches 1,2,3,5,8 (with changes) from ITS#3432)
authorPierangelo Masarati <ando@openldap.org>
Sat, 1 Jan 2005 16:21:55 +0000 (16:21 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sat, 1 Jan 2005 16:21:55 +0000 (16:21 +0000)
14 files changed:
servers/slapd/back-sql/add.c
servers/slapd/back-sql/back-sql.h
servers/slapd/back-sql/bind.c
servers/slapd/back-sql/compare.c
servers/slapd/back-sql/config.c
servers/slapd/back-sql/delete.c
servers/slapd/back-sql/entry-id.c
servers/slapd/back-sql/init.c
servers/slapd/back-sql/modify.c
servers/slapd/back-sql/modrdn.c
servers/slapd/back-sql/operational.c
servers/slapd/back-sql/proto-sql.h
servers/slapd/back-sql/schema-map.c
servers/slapd/back-sql/search.c

index 75b3e0ecd01a6094425770e3bb0a0b5cf2e0e192..b782ba44ea72986972ea0cdaa774bb33fecf47d9 100644 (file)
@@ -57,7 +57,7 @@ backsql_modify_delete_all_values(
 {
        backsql_info    *bi = (backsql_info *)op->o_bd->be_private;
        RETCODE         rc;
-       SQLHSTMT        asth;
+       SQLHSTMT        asth = SQL_NULL_HSTMT;
        BACKSQL_ROW_NTS row;
 
        assert( at );
@@ -138,10 +138,10 @@ backsql_modify_delete_all_values(
                /* first parameter no, parameter order */
                SQLUSMALLINT            pno, po;
                /* procedure return code */
-               int                     prc;
+               int                     prc = LDAP_SUCCESS;
                
                for ( i = 0; i < row.ncols; i++ ) {
-                       SQLHSTMT        sth;
+                       SQLHSTMT        sth = SQL_NULL_HSTMT;
                        ber_len_t       col_len;
                        
                        rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
@@ -248,19 +248,33 @@ backsql_modify_delete_all_values(
                                pno + 2 - po, row.cols[ i ],
                                at->bam_delete_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_delete_all_values(): "
                                        "delete_proc "
-                                       "execution failed\n",
-                                       0, 0, 0 );
-                               backsql_PrintErrors( bi->sql_db_env,
-                                               dbh, sth, rc );
-
-                               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+                                       "execution failed (rc=%d, prc=%d)\n",
+                                       rc, prc, 0 );
+                               if ( prc != LDAP_SUCCESS ) {
+                                       /* SQL procedure executed fine 
+                                        * but returned an error */
+                                       rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
+                                       rs->sr_text = op->oq_add.rs_e->e_name.bv_val;
                                        SQLFreeStmt( sth, SQL_DROP );
-                                       rs->sr_text = "SQL-backend error";
-                                       return rs->sr_err = LDAP_OTHER;
+                                       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->oq_add.rs_e->e_name.bv_val;
+                                               SQLFreeStmt( sth, SQL_DROP );
+                                               return rs->sr_err;
+                                       }
                                }
                        }
                        SQLFreeStmt( sth, SQL_DROP );
@@ -283,7 +297,7 @@ backsql_modify_internal(
 {
        backsql_info    *bi = (backsql_info*)op->o_bd->be_private;
        RETCODE         rc;
-       SQLHSTMT        sth;
+       SQLHSTMT        sth = SQL_NULL_HSTMT;
        Modifications   *ml;
 
        Debug( LDAP_DEBUG_TRACE, "==>backsql_modify_internal(): "
@@ -306,7 +320,7 @@ backsql_modify_internal(
                /* first parameter position, parameter order */
                SQLUSMALLINT            pno, po;
                /* procedure return code */
-               int                     prc;
+               int                     prc = LDAP_SUCCESS;
                
                ad = ml->sml_mod.sm_desc;
                sm_op = ( ml->sml_mod.sm_op & LDAP_MOD_OP );
@@ -578,6 +592,7 @@ add_only:;
                                        !BER_BVISNULL( at_val );
                                        i++, at_val++ )
                        {
+                               prc = LDAP_SUCCESS;
                                rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
                                if ( rc != SQL_SUCCESS ) {
                                        Debug( LDAP_DEBUG_TRACE,
@@ -667,19 +682,34 @@ add_only:;
                                        "executing \"%s\"\n", 
                                        at->bam_delete_proc, 0, 0 );
                                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(): "
                                                "delete_proc execution "
-                                               "failed\n", 0, 0, 0 );
-                                       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";
+                                               "failed (rc=%d, prc=%d)\n",
+                                               rc, prc, 0 );
+
+                                       if ( prc != LDAP_SUCCESS ) {
+                                               /* SQL procedure executed fine
+                                                * but returned an error */
+                                               rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
+                                               rs->sr_text = at->bam_ad->ad_cname.bv_val;
                                                goto done;
+                                               
+                                       } 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 );
@@ -724,12 +754,8 @@ backsql_add_attr(
        struct berval           *at_val;
        unsigned long           i;
        RETCODE                 rc;
-       /* first parameter #, parameter order */
-       SQLUSMALLINT            pno, po;
-       /* procedure return code */
-       int                     prc;
        SQLUSMALLINT            currpos;
-       SQLHSTMT                sth;
+       SQLHSTMT                sth = SQL_NULL_HSTMT;
 
        at_rec = backsql_ad2at( oc, at->a_desc ); 
   
@@ -772,7 +798,11 @@ backsql_add_attr(
                        !BER_BVISNULL( at_val );
                        i++, at_val = &at->a_vals[ i ] )
        {
-               char logbuf[] = "val[18446744073709551615UL], id=18446744073709551615UL";
+               /* procedure return code */
+               int             prc = LDAP_SUCCESS;
+               /* first parameter #, parameter order */
+               SQLUSMALLINT    pno, po;
+               char            logbuf[] = "val[18446744073709551615UL], id=18446744073709551615UL";
                
                /*
                 * Do not deal with the objectClass that is used
@@ -875,17 +905,31 @@ backsql_add_attr(
                        at_rec->bam_add_proc, logbuf );
 #endif
                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_add_attr(\"%s\"): "
-                               "add_proc execution failed\n", 
-                               op->oq_add.rs_e->e_name.bv_val, 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", 
+                               op->oq_add.rs_e->e_name.bv_val, rc, prc );
+                       if ( prc != LDAP_SUCCESS ) {
+                               /* SQL procedure executed fine
+                                * but returned an error */
+                               rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
+                               rs->sr_text = op->oq_add.rs_e->e_name.bv_val;
                                SQLFreeStmt( sth, SQL_DROP );
-                               rs->sr_text = "SQL-backend error";
-                               return rs->sr_err = LDAP_OTHER;
+                               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->oq_add.rs_e->e_name.bv_val;
+                                       SQLFreeStmt( sth, SQL_DROP );
+                                       return rs->sr_err;
+                               }
                        }
                }
                SQLFreeStmt( sth, SQL_DROP );
@@ -898,8 +942,8 @@ int
 backsql_add( Operation *op, SlapReply *rs )
 {
        backsql_info            *bi = (backsql_info*)op->o_bd->be_private;
-       SQLHDBC                 dbh;
-       SQLHSTMT                sth;
+       SQLHDBC                 dbh = SQL_NULL_HDBC;
+       SQLHSTMT                sth = SQL_NULL_HSTMT;
        unsigned long           new_keyval = 0;
        RETCODE                 rc;
        backsql_oc_map_rec      *oc = NULL;
@@ -909,6 +953,7 @@ backsql_add( Operation *op, SlapReply *rs )
                                *at_objectClass = NULL;
        struct berval           pdn;
        struct berval           realdn = BER_BVNULL;
+       int                     colnum;
 
 #ifdef BACKSQL_SYNCPROV
        /*
@@ -1005,6 +1050,9 @@ 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.
         */
        realdn = op->oq_add.rs_e->e_name;
        if ( backsql_api_dn2odbc( op, rs, &realdn ) ) {
@@ -1122,6 +1170,7 @@ backsql_add( Operation *op, SlapReply *rs )
                goto done;
        }
 
+       colnum = 1;
        if ( BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
                rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &new_keyval );
                if ( rc != SQL_SUCCESS ) {
@@ -1137,6 +1186,27 @@ backsql_add( Operation *op, SlapReply *rs )
                        rs->sr_err = LDAP_OTHER;
                        goto done;
                }
+               colnum++;
+       }
+
+       if ( oc->bom_create_hint ) {
+               at = attr_find( op->oq_add.rs_e->e_attrs, oc->bom_create_hint );
+               if ( at && at->a_vals ) {
+                       backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
+                                       at->a_vals[0].bv_val,
+                                       at->a_vals[0].bv_len );
+                       Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+                                       "create_proc hint: param = '%s'\n",
+                                       at->a_vals[0].bv_val, 0, 0 );
+
+               } else {
+                       backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
+                                       "", 0 );
+                       Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+                                       "create_proc hint (%s) not avalable\n",
+                                       oc->bom_create_hint->ad_cname.bv_val,
+                                       0, 0 );
+               }
        }
 
        Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): executing \"%s\"\n",
index cb6250733c01c286a88fb61d683a2c5a12e89d3c..50b12efe4b60474ee4bb03d9211dae4a5c2cda9f 100644 (file)
 /* ACKNOWLEDGEMENTS:
  * This work was initially developed by Dmitry Kovalev for inclusion
  * by OpenLDAP Software.  Additional significant contributors include
- *    Pierangelo Mararati
+ * Pierangelo Mararati
+ */
+/*
+ * Original copyright notice by Mark Adamson (applies to portions
+ * of code submitted as ITS#3432, and reworked by Pierangelo Masarati):
+ *
+ * The patch files are derived from OpenLDAP Software. All of the
+ * modifications to OpenLDAP Software represented in the following
+ * patches were developed by Mark Adamson (adamson@cmu.edu). These
+ * modifications are not subject to any license of Carnegie Mellon.
+ *
+ * The attached modifications to OpenLDAP Software are subject to the
+ * following notice:
+ *
+ *   Copyright 2004 Mark Adamson
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted only as authorized by the OpenLDAP Public
+ *   License.
  */
-
 /*
  * The following changes have been addressed:
  *      
  *   - check how to allow multiple operations with one statement, to remove
  *     BACKSQL_REALLOC_STMT from modify.c (a more recent unixODBC lib?)
  */
+/*
+ * Improvements submitted by (ITS#)
+ *
+ * 1. id_query.patch           applied (with changes)
+ * 2. shortcut.patch           applied (reworked)
+ * 3. create_hint.patch                applied
+ * 4. count_query.patch                rejected (conflicts with other features)
+ * 5. returncodes.patch                applied (with sanity checks)
+ * 6. connpool.patch           under evaluation
+ * 7. modoc.patch              under evaluation
+ * 8. miscfixes.patch          applied (reworked; FIXME: other
+ *                             operations may need to load the
+ *                             entire entry for ACL purposes)
+ *
+ * original description:
+
+         Changes that were made to the SQL backend.
+
+The patches were made against 2.2.18 and can be applied individually,
+but would best be applied in the numerical order of the file names.
+A synopsis of each patch is given here:
+
+
+1. Added an option to set SQL query for the "id_query" operation.
+
+2. Added an option to the SQL backend called "use_subtree_shortcut".
+When a search is performed, the SQL query includes a WHERE clause
+which says the DN must be "LIKE %<searchbase>".  The LIKE operation
+can be slow in an RDBM. This shortcut option says that if the
+searchbase of the LDAP search is the root DN of the SQL backend,
+and thus all objects will match the LIKE operator, do not include
+the "LIKE %<searchbase>" clause in the SQL query (it is replaced
+instead by the always true "1=1" clause to keep the "AND"'s 
+working correctly).  This option is off by default, and should be
+turned on only if all objects to be found in the RDBM are under the
+same root DN. Multiple backends working within the same RDBM table
+space would encounter problems. LDAP searches whose searchbase are
+not at the root DN will bypass this shortcut and employ the LIKE 
+clause.
+
+3. Added a "create_hint" column to ldap_oc_mappings table. Allows
+taking the value of an attr named in "create_hint" and passing it to
+the create_proc procedure.  This is necessary for when an objectClass's
+table is partition indexed by some indexing column and thus the value
+in that indexing column cannot change after the row is created. The
+value for the indexed column is passed into the create_proc, which
+uses it to fill in the indexed column as the new row is created.
+
+4. When loading the values of an attribute, the count(*) of the number
+of values is fetched first and memory is allocated for the array of
+values and normalized values. The old system of loading the values one
+by one and running realloc() on the array of values and normalized
+values each time was badly fragmenting memory. The array of values and
+normalized values would be side by side in memory, and realloc()'ing
+them over and over would force them to leapfrog each other through all
+of available memory. Attrs with a large number of values could not be
+loaded without crashing the slapd daemon.
+
+5. Added code to interpret the value returned by stored procedures
+which have expect_return set. Returned value is interpreted as an LDAP
+return code. This allows the distinction between the SQL failing to
+execute and the SQL running to completion and returning an error code
+which can indicate a policy violation.
+
+6. Added RDBM connection pooling. Once an operation is finished the
+connection to the RDBM is returned to a pool rather than closing.
+Allows the next operation to skip the initialization and authentication
+phases of contacting the RDBM. Also, if licensing with ODBC places
+a limit on the number of connections, an LDAP thread can block waiting
+for another thread to finish, so that no LDAP errors are returned
+for having more LDAP connections than allowed RDBM connections. An
+RDBM connection which receives an SQL error is marked as "tainted"
+so that it will be closed rather than returned to the pool.
+  Also, RDBM connections must be bound to a given LDAP connection AND
+operation number, and NOT just the connection number.  Asynchronous
+LDAP clients can have multiple simultaneous LDAP operations which
+should not share the same RDBM connection.  A given LDAP operation can
+even make multiple SQL operations (e.g. a BIND operation which
+requires SASL to perform an LDAP search to convert the SASL ID to an
+LDAP DN), so each RDBM connection now has a refcount that must reach
+zero before the connection is returned to the free pool.
+
+7. Added ability to change the objectClass of an object. Required 
+considerable work to copy all attributes out of old object and into
+new object.  Does a schema check before proceeding.  Creates a new
+object, fills it in, deletes the old object, then changes the 
+oc_map_id and keyval of the entry in the "ldap_entries" table.
+
+8.  Generic fixes. Includes initializing pointers before they
+get used in error branch cases, pointer checks before dereferencing,
+resetting a return code to success after a COMPARE op, sealing
+memory leaks, and in search.c, changing some of the "1=1" tests to
+"2=2", "3=3", etc so that when reading slapd trace output, the 
+location in the source code where the x=x test was added to the SQL
+can be easily distinguished.
+ */
 
 #ifndef __BACKSQL_H__
 #define __BACKSQL_H__
@@ -175,24 +287,25 @@ typedef struct backsql_oc_map_rec {
        /*
         * Structure of corresponding LDAP objectClass definition
         */
-       ObjectClass     *bom_oc;
+       ObjectClass             *bom_oc;
 #define BACKSQL_OC_NAME(ocmap) ((ocmap)->bom_oc->soc_cname.bv_val)
        
-       struct berval   bom_keytbl;
-       struct berval   bom_keycol;
+       struct berval           bom_keytbl;
+       struct berval           bom_keycol;
        /* expected to return keyval of newly created entry */
-       char            *bom_create_proc;
+       char                    *bom_create_proc;
        /* in case create_proc does not return the keyval of the newly
         * created row */
-       char            *bom_create_keyval;
+       char                    *bom_create_keyval;
        /* supposed to expect keyval as parameter and delete 
         * all the attributes as well */
-       char            *bom_delete_proc;
+       char                    *bom_delete_proc;
        /* flags whether delete_proc is a function (whether back-sql 
         * should bind first parameter as output for return code) */
-       int             bom_expect_return;
-       unsigned long   bom_id;
-       Avlnode         *bom_attrs;
+       int                     bom_expect_return;
+       unsigned long           bom_id;
+       Avlnode                 *bom_attrs;
+       AttributeDescription    *bom_create_hint;
 } backsql_oc_map_rec;
 
 /*
@@ -278,6 +391,7 @@ typedef struct backsql_srch_info {
 #define BSQL_SF_RETURN_ENTRYUUID       (BSQL_SF_FILTER_ENTRYUUID << 8)
 
        struct berval           *bsi_base_ndn;
+       int                     bsi_use_subtree_shortcut;
        backsql_entryID         bsi_base_id;
        int                     bsi_scope;
 /* BACKSQL_SCOPE_BASE_LIKE can be set by API in ors_scope
@@ -355,6 +469,7 @@ typedef struct {
 #define BSQLF_DONTCHECK_LDAPINFO_DN_RU 0x0020
 #define BSQLF_USE_REVERSE_DN           0x0040
 #define BSQLF_ALLOW_ORPHANS            0x0080
+#define BSQLF_USE_SUBTREE_SHORTCUT     0x0100
 
 #define        BACKSQL_SCHEMA_LOADED(si) \
        ((si)->sql_flags & BSQLF_SCHEMA_LOADED)
@@ -374,6 +489,8 @@ typedef struct {
        (!BER_BVISNULL( &(si)->sql_upper_func ))
 #define BACKSQL_ALLOW_ORPHANS(si) \
        ((si)->sql_flags & BSQLF_ALLOW_ORPHANS)
+#define BACKSQL_USE_SUBTREE_SHORTCUT(si) \
+       ((si)->sql_flags & BSQLF_USE_SUBTREE_SHORTCUT)
 
        Entry           *sql_baseObject;
 #ifdef BACKSQL_ARBITRARY_KEY
@@ -404,7 +521,16 @@ typedef struct {
 #define BACKSQL_AVL_STOP               0
 #define BACKSQL_AVL_CONTINUE           1
 
-#endif /* __BACKSQL_H__ */
-
+/* see ldap.h for the meaning of the macros and of the values */
+#define BACKSQL_LEGAL_ERROR( rc ) \
+       ( LDAP_RANGE( (rc), 0x00, 0x0e ) \
+         || LDAP_ATTR_ERROR( (rc) ) \
+         || LDAP_NAME_ERROR( (rc) ) \
+         || LDAP_SECURITY_ERROR( (rc) ) \
+         || LDAP_SERVICE_ERROR( (rc) ) \
+         || LDAP_UPDATE_ERROR( (rc) ) )
+#define BACKSQL_SANITIZE_ERROR( rc ) \
+       ( BACKSQL_LEGAL_ERROR( (rc) ) ? (rc) : LDAP_OTHER )
 
+#endif /* __BACKSQL_H__ */
 
index c775280a9bf1a3ecb6983f35c686565e231d69b0..b8f26d8e99ff5cbdc1380de5cb6cb838b5c54557 100644 (file)
@@ -29,7 +29,7 @@
 int 
 backsql_bind( Operation *op, SlapReply *rs )
 {
-       SQLHDBC                 dbh;
+       SQLHDBC                 dbh = SQL_NULL_HDBC;
        AttributeDescription    *password = slap_schema.si_ad_userPassword;
        Entry                   *e, user_entry;
        Attribute               *a;
@@ -75,8 +75,9 @@ backsql_bind( Operation *op, SlapReply *rs )
        anlist[1].an_name.bv_val = NULL;
 
        rc = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE, 
-                       -1, -1, -1, NULL, dbh, op, rs, anlist,
-                       ( BACKSQL_ISF_GET_ID | BACKSQL_ISF_MUCK ) );
+                       SLAP_NO_LIMIT, SLAP_NO_LIMIT,
+                       (time_t)(-1), NULL, dbh, op, rs, anlist,
+                       BACKSQL_ISF_GET_ID );
        if ( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE, "backsql_bind(): "
                        "could not retrieve bindDN ID - no such entry\n", 
index d091def078deaa790054c9dee7ec04b73e93f80d..b8bd29b4998edaef15df5c4e08ec8a4ed05222f2 100644 (file)
@@ -29,7 +29,7 @@
 int
 backsql_compare( Operation *op, SlapReply *rs )
 {
-       SQLHDBC                 dbh;
+       SQLHDBC                 dbh = SQL_NULL_HDBC;
        Entry                   *e = NULL, user_entry;
        Attribute               *a = NULL;
        backsql_srch_info       bsi;
@@ -82,9 +82,11 @@ backsql_compare( Operation *op, SlapReply *rs )
                user_entry.e_attrs = nrs.sr_operational_attrs;
 
        } else {
-               rc = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE, 
-                               -1, -1, -1, NULL, dbh, op, rs, anlist,
-                               ( BACKSQL_ISF_GET_ID | BACKSQL_ISF_MUCK ) );
+               rc = backsql_init_search( &bsi, &op->o_req_ndn,
+                               LDAP_SCOPE_BASE, 
+                               SLAP_NO_LIMIT, SLAP_NO_LIMIT,
+                               (time_t)(-1), NULL, dbh, op, rs, anlist,
+                               BACKSQL_ISF_GET_ID );
                if ( rc != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_TRACE, "backsql_compare(): "
                                "could not retrieve compareDN ID - no such entry\n", 
index 0068e8269c91422e516214422c78d5b8890faa70..77e9d9310c3c94b44c562d90e01647ddef027828 100644 (file)
@@ -441,6 +441,48 @@ backsql_db_config(
                        return 1;
                }
 
+       } else if ( !strcasecmp( argv[ 0 ], "id_query" ) ) {
+               if ( argc < 2 ) {
+                       Debug( LDAP_DEBUG_TRACE, 
+                               "<==backsql_db_config (%s line %d): "
+                               "missing SQL condition "
+                               "in \"id_query\" directive\n",
+                               fname, lineno, 0 );
+                       return 1;
+               }
+               bi->sql_id_query = ch_strdup( argv[ 1 ] );
+               Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+                       "id_query=%s\n", bi->sql_id_query, 0, 0 );
+
+       } else if ( !strcasecmp( argv[ 0 ], "use_subtree_shortcut") ) {
+               if ( argc < 2 ) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "<==backsql_db_config (%s line %d): "
+                               "missing { yes | no }"
+                               "in \"use_subtree_shortcut\" directive\n",
+                               fname, lineno, 0 );
+                       return 1;
+               }
+
+               if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+                       bi->sql_flags |= BSQLF_USE_SUBTREE_SHORTCUT;
+
+               } else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+                       bi->sql_flags &= ~BSQLF_USE_SUBTREE_SHORTCUT;
+
+               } else {
+                       Debug( LDAP_DEBUG_TRACE,
+                               "<==backsql_db_config (%s line %d): "
+                               "\"use_subtree_shortcut\" directive arg "
+                               "must be \"yes\" or \"no\"\n",
+                               fname, lineno, 0 );
+                       return 1;
+
+               }
+               Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+                       "use_subtree_shortcut=%s\n", 
+                       BACKSQL_USE_SUBTREE_SHORTCUT( bi ) ? "yes" : "no", 0, 0 );
+
        } else {
                return SLAP_CONF_UNKNOWN;
        }
index c769783ca05584f3a8b5c9de9a37d0993b49c36e..5d11397d87d4e5da3b346b938d89ee7216a81293 100644 (file)
@@ -80,15 +80,16 @@ int
 backsql_delete( Operation *op, SlapReply *rs )
 {
        backsql_info            *bi = (backsql_info*)op->o_bd->be_private;
-       SQLHDBC                 dbh;
-       SQLHSTMT                sth;
+       SQLHDBC                 dbh = SQL_NULL_HDBC;
+       SQLHSTMT                sth = SQL_NULL_HSTMT;
        RETCODE                 rc;
-       int                     retval;
+       int                     prc = LDAP_SUCCESS;
        backsql_oc_map_rec      *oc = NULL;
        backsql_entryID         e_id = BACKSQL_ENTRYID_INIT;
        Entry                   e;
        /* first parameter no */
        SQLUSMALLINT            pno;
+       SQLUSMALLINT            CompletionType = SQL_ROLLBACK;
 
        Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry \"%s\"\n",
                        op->o_req_ndn.bv_val, 0, 0 );
@@ -127,16 +128,17 @@ backsql_delete( Operation *op, SlapReply *rs )
 
        rs->sr_err = backsql_has_children( bi, dbh, &op->o_req_ndn );
        switch ( rs->sr_err ) {
+       case LDAP_COMPARE_FALSE:
+               rs->sr_err = LDAP_SUCCESS;
+               break;
+
        case LDAP_COMPARE_TRUE:
                Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
                        "entry \"%s\" has children\n",
                        op->o_req_dn.bv_val, 0, 0 );
                rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
                rs->sr_text = "subtree delete not supported";
-               goto done;
-
-       case LDAP_COMPARE_FALSE:
-               break;
+               /* fallthru */
 
        default:
                goto done;
@@ -182,7 +184,7 @@ backsql_delete( Operation *op, SlapReply *rs )
 
        if ( BACKSQL_IS_DEL( oc->bom_expect_return ) ) {
                pno = 1;
-               rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &retval );
+               rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
                if ( rc != SQL_SUCCESS ) {
                        Debug( LDAP_DEBUG_TRACE,
                                "   backsql_delete(): "
@@ -217,13 +219,26 @@ backsql_delete( Operation *op, SlapReply *rs )
        }
 
        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_delete(): "
-                       "delete_proc execution failed\n", 0, 0, 0 );
-               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
+                       "delete_proc execution failed (rc=%d, prc=%d)\n",
+                       rc, prc, 0 );
+
+
+               if ( prc != LDAP_SUCCESS ) {
+                       /* SQL procedure executed fine 
+                        * but returned an error */
+                       rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
+
+               } else {
+                       backsql_PrintErrors( bi->sql_db_env, dbh,
+                                       sth, rc );
+                       rs->sr_err = LDAP_OTHER;
+               }
                SQLFreeStmt( sth, SQL_DROP );
-               rs->sr_err = LDAP_OTHER;
-               rs->sr_text = "SQL-backend error";
                goto done;
        }
        SQLFreeStmt( sth, SQL_DROP );
@@ -371,6 +386,10 @@ backsql_delete( Operation *op, SlapReply *rs )
        }
        SQLFreeStmt( sth, SQL_DROP );
 
+       rs->sr_err = LDAP_SUCCESS;
+
+done:;
+
        /*
         * Commit only if all operations succeed
         *
@@ -380,12 +399,11 @@ backsql_delete( Operation *op, SlapReply *rs )
         * or if a single operation on an attribute fails 
         * for any reason
         */
-       SQLTransact( SQL_NULL_HENV, dbh, 
-                       op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
-
-       rs->sr_err = LDAP_SUCCESS;
+       if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
+               CompletionType = SQL_COMMIT;
+       }
+       SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
 
-done:;
        send_ldap_result( op, rs );
 
        Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );
index 819da825d4571c537c6cd298a0bb9e95e9bd1791..87328df92b258dd7aecae8989d907513db921b75 100644 (file)
@@ -114,7 +114,10 @@ backsql_dn2id(
        }
 
        /* return baseObject if available and matches */
-       if ( bi->sql_baseObject != NULL && dn_match( ndn, &bi->sql_baseObject->e_nname ) ) {
+       /* FIXME: if ndn is already mucked, we cannot check this */
+       if ( bi->sql_baseObject != NULL &&
+                       dn_match( ndn, &bi->sql_baseObject->e_nname ) )
+       {
                if ( id != NULL ) {
 #ifdef BACKSQL_ARBITRARY_KEY
                        ber_dupbv( &id->eid_id, &backsql_baseObject_bv );
@@ -164,7 +167,8 @@ backsql_dn2id(
                 * that can be searched using indexes
                 */
 
-               for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--) {
+               for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--)
+               {
                        upperdn[ i ] = realndn.bv_val[ j ];
                }
                upperdn[ i ] = '\0';
@@ -288,7 +292,7 @@ backsql_count_children(
        struct berval           *dn,
        unsigned long           *nchildren )
 {
-       SQLHSTMT                sth
+       SQLHSTMT                sth = SQL_NULL_HSTMT;
        BACKSQL_ROW_NTS         row;
        RETCODE                 rc;
        int                     res = LDAP_SUCCESS;
@@ -391,7 +395,7 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
        backsql_srch_info       *bsi = v_bsi;
        backsql_info            *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
        RETCODE                 rc;
-       SQLHSTMT                sth;
+       SQLHSTMT                sth = SQL_NULL_HSTMT;
        BACKSQL_ROW_NTS         row;
        int                     i;
 
@@ -466,7 +470,7 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
                                 */
                                bv.bv_len = strlen( row.cols[ i ] );
 #endif
-                                       backsql_entry_addattr( bsi->bsi_e, 
+                               backsql_entry_addattr( bsi->bsi_e, 
                                                &row.col_names[ i ], &bv,
                                                bsi->bsi_op->o_tmpmemctx );
 
index 501dedaee65c57cd2a52fce62f78552bf93c104c..b96e3671255f3d97f8d42902cdcdaf16cf2fce4b 100644 (file)
@@ -153,8 +153,7 @@ backsql_db_open(
        BackendDB       *bd )
 {
        backsql_info    *bi = (backsql_info*)bd->be_private;
-       SQLHDBC         dbh;
-       ber_len_t       idq_len;
+       SQLHDBC         dbh = SQL_NULL_HDBC;
        struct berbuf   bb = BB_NULL;
 
        char            opbuf[ OPERATION_BUFFER_SIZE ];
@@ -398,34 +397,34 @@ backsql_db_open(
        /*
         * Prepare ID selection query
         */
-       bi->sql_id_query = NULL;
-       idq_len = 0;
+       if ( bi->sql_id_query == NULL ) {
+               /* no custom id_query provided */
+               if ( bi->sql_upper_func.bv_val == NULL ) {
+                       backsql_strcat( &bb, backsql_id_query, "dn=?", NULL );
 
-       if ( bi->sql_upper_func.bv_val == NULL ) {
-               backsql_strcat( &bb, backsql_id_query, "dn=?", NULL );
-
-       } else {
-               if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
-                       backsql_strcat( &bb, backsql_id_query,
-                                       "dn_ru=?", NULL );
                } else {
-                       if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
-                               backsql_strfcat( &bb, "sbl",
-                                               backsql_id_query,
-                                               &bi->sql_upper_func, 
-                                               (ber_len_t)STRLENOF( "(dn)=?" ), "(dn)=?" );
+                       if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
+                               backsql_strcat( &bb, backsql_id_query,
+                                               "dn_ru=?", NULL );
                        } else {
-                               backsql_strfcat( &bb, "sblbcb",
-                                               backsql_id_query,
-                                               &bi->sql_upper_func, 
-                                               (ber_len_t)STRLENOF( "(dn)=" ), "(dn)=",
-                                               &bi->sql_upper_func_open, 
-                                               '?', 
-                                               &bi->sql_upper_func_close );
+                               if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
+                                       backsql_strfcat( &bb, "sbl",
+                                                       backsql_id_query,
+                                                       &bi->sql_upper_func, 
+                                                       (ber_len_t)STRLENOF( "(dn)=?" ), "(dn)=?" );
+                               } else {
+                                       backsql_strfcat( &bb, "sblbcb",
+                                                       backsql_id_query,
+                                                       &bi->sql_upper_func, 
+                                                       (ber_len_t)STRLENOF( "(dn)=" ), "(dn)=",
+                                                       &bi->sql_upper_func_open, 
+                                                       '?', 
+                                                       &bi->sql_upper_func_close );
+                               }
                        }
                }
+               bi->sql_id_query = bb.bb_val.bv_val;
        }
-       bi->sql_id_query = bb.bb_val.bv_val;
 
                /*
         * Prepare children ID selection query
index e1434cdf65426823252112faba5208437dc59105..ffffbcd344e24f647ef13985d2e55fd0e1512a00 100644 (file)
@@ -31,10 +31,10 @@ int
 backsql_modify( Operation *op, SlapReply *rs )
 {
        backsql_info            *bi = (backsql_info*)op->o_bd->be_private;
-       SQLHDBC                 dbh;
+       SQLHDBC                 dbh = SQL_NULL_HDBC;
        backsql_oc_map_rec      *oc = NULL;
-       backsql_entryID         e_id = BACKSQL_ENTRYID_INIT;
-       Entry                   e;
+       backsql_srch_info       bsi = { 0 };
+       Entry                   e = { 0 };
 
        /*
         * FIXME: in case part of the operation cannot be performed
@@ -58,26 +58,42 @@ backsql_modify( Operation *op, SlapReply *rs )
                goto done;
        }
 
-       rs->sr_err = backsql_dn2id( op, rs, &e_id, dbh, &op->o_req_ndn, 1 );
+       /* FIXME: using all attributes because of access control later ... */
+       rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
+                       LDAP_SCOPE_BASE, 
+                       SLAP_NO_LIMIT, SLAP_NO_LIMIT,
+                       (time_t)(-1), NULL, dbh, op, rs,
+                       slap_anlist_all_attributes,
+                       BACKSQL_ISF_GET_ID );
        if ( rs->sr_err != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_TRACE, "   backsql_modify(): "
-                       "could not lookup entry id\n", 0, 0, 0 );
-               rs->sr_text = ( rs->sr_err == LDAP_OTHER )
-                       ? "SQL-backend error" : NULL;
+               Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+                       "could not retrieve modifyDN ID - no such entry\n", 
+                       0, 0, 0 );
+               rs->sr_err = LDAP_NO_SUCH_OBJECT;
+               goto done;
+       }
+
+       bsi.bsi_e = &e;
+       rs->sr_err = backsql_id2entry( &bsi, &bsi.bsi_base_id );
+       if ( rs->sr_err != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+                       "error %d in backsql_id2entry()\n",
+                       rs->sr_err, 0, 0 );
                goto done;
        }
 
 #ifdef BACKSQL_ARBITRARY_KEY
        Debug( LDAP_DEBUG_TRACE, "   backsql_modify(): "
                "modifying entry \"%s\" (id=%s)\n", 
-               e_id.eid_dn.bv_val, e_id.eid_id.bv_val, 0 );
+               bsi.bsi_base_id.eid_dn.bv_val,
+               bsi.bsi_base_id.eid_id.bv_val, 0 );
 #else /* ! BACKSQL_ARBITRARY_KEY */
        Debug( LDAP_DEBUG_TRACE, "   backsql_modify(): "
                "modifying entry \"%s\" (id=%ld)\n", 
-               e_id.eid_dn.bv_val, e_id.eid_id, 0 );
+               bsi.bsi_base_id.eid_dn.bv_val, bsi.bsi_base_id.eid_id, 0 );
 #endif /* ! BACKSQL_ARBITRARY_KEY */
 
-       oc = backsql_id2oc( bi, e_id.eid_oc_id );
+       oc = backsql_id2oc( bi, bsi.bsi_base_id.eid_oc_id );
        if ( oc == NULL ) {
                Debug( LDAP_DEBUG_TRACE, "   backsql_modify(): "
                        "cannot determine objectclass of entry -- aborting\n",
@@ -102,7 +118,8 @@ backsql_modify( Operation *op, SlapReply *rs )
                rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
 
        } else {
-               rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id,
+               rs->sr_err = backsql_modify_internal( op, rs, dbh, oc,
+                               &bsi.bsi_base_id,
                                op->oq_modify.rs_modlist );
        }
 
@@ -116,6 +133,15 @@ backsql_modify( Operation *op, SlapReply *rs )
 
 done:;
        send_ldap_result( op, rs );
+
+       if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
+               (void)backsql_free_entryID( &bsi.bsi_base_id, 0 );
+       }
+
+       if ( bsi.bsi_e != NULL ) {
+               entry_clean( bsi.bsi_e );
+       }
+
        Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n", 0, 0, 0 );
 
        return rs->sr_err != LDAP_SUCCESS ? rs->sr_err : op->o_noop;
index 4a9703c7ce4371dc9f64bcc51906a62c69d6ba16..145636ca43a59676550f26cf8df22036930cccf5 100644 (file)
@@ -31,8 +31,8 @@ int
 backsql_modrdn( Operation *op, SlapReply *rs )
 {
        backsql_info            *bi = (backsql_info*)op->o_bd->be_private;
-       SQLHDBC                 dbh;
-       SQLHSTMT                sth;
+       SQLHDBC                 dbh = SQL_NULL_HDBC;
+       SQLHSTMT                sth = SQL_NULL_HSTMT;
        RETCODE                 rc;
        backsql_entryID         e_id = BACKSQL_ENTRYID_INIT,
                                pe_id = BACKSQL_ENTRYID_INIT,
index c0c7ed2442f5012f84a023febd91ffc9a5841725..a0238bf47f3d3be8b7516b9eb5b8f6c815fe1b1f 100644 (file)
@@ -181,9 +181,10 @@ backsql_operational(
                backsql_srch_info       bsi;
 
                rc = backsql_init_search( &bsi, &rs->sr_entry->e_nname,
-                               LDAP_SCOPE_BASE, -1, -1, -1, NULL,
-                               dbh, op, rs, NULL,
-                               ( BACKSQL_ISF_GET_ID | BACKSQL_ISF_MUCK ) );
+                               LDAP_SCOPE_BASE,
+                               SLAP_NO_LIMIT, SLAP_NO_LIMIT,
+                               (time_t)(-1), NULL, dbh, op, rs, NULL,
+                               BACKSQL_ISF_GET_ID );
                if ( rc != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
                                "could not retrieve entry ID - no such entry\n", 
index 42162b9535fdcf9f347324ac052ed6f3f16abacf..2b6bcdd60f721ed55f5375cf2766dc724d3d6377 100644 (file)
@@ -160,8 +160,8 @@ int backsql_destroy_schema_map( backsql_info *si );
  * search.c
  */
 
+/* the function must collect the entry associated to nbase */
 #define BACKSQL_ISF_GET_ID     0x1U
-#define BACKSQL_ISF_MUCK       0x2U
 int backsql_init_search( backsql_srch_info *bsi, 
                struct berval *nbase, int scope, int slimit, int tlimit,
                time_t stoptime, Filter *filter, SQLHDBC dbh,
index 9022c451dc08942e2efd09097a2a410bb20d054f..f1465da527ec96df657830ac4930b0f9809adb86 100644 (file)
@@ -385,6 +385,7 @@ backsql_oc_get_attr_mapping( void *v_oc, void *v_bas )
        backsql_BindRowAsStrings( bas->bas_sth, &at_row );
        for ( ; rc = SQLFetch( bas->bas_sth ), BACKSQL_SUCCESS( rc ); ) {
                const char      *text = NULL;
+               char            *next = NULL;
                struct berval   bv;
                struct berbuf   bb = BB_NULL;
 
@@ -446,9 +447,15 @@ backsql_oc_get_attr_mapping( void *v_oc, void *v_bas )
                        at_map->bam_delete_proc = ch_strdup( at_row.cols[ 5 ] );
                }
                at_map->bam_param_order = strtol( at_row.cols[ 6 ], 
-                               NULL, 0 );
+                               &next, 0 );
+               if ( next == at_row.cols[ 6 ] || next[0] != '\0' ) {
+                       /* error */
+               }
                at_map->bam_expect_return = strtol( at_row.cols[ 7 ],
-                               NULL, 0 );
+                               &next, 0 );
+               if ( next == at_row.cols[ 7 ] || next[0] != '\0' ) {
+                       /* error */
+               }
                backsql_make_attr_query( oc_map, at_map );
                Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_attr_mapping(): "
                        "preconstructed query \"%s\"\n",
@@ -491,7 +498,7 @@ backsql_oc_get_attr_mapping( void *v_oc, void *v_bas )
 int
 backsql_load_schema_map( backsql_info *bi, SQLHDBC dbh )
 {
-       SQLHSTMT                        sth;
+       SQLHSTMT                        sth = SQL_NULL_HSTMT;
        RETCODE                         rc;
        BACKSQL_ROW_NTS                 oc_row;
        unsigned long                   oc_id;
@@ -573,6 +580,28 @@ backsql_load_schema_map( backsql_info *bi, SQLHDBC dbh )
                oc_map->bom_expect_return = strtol( oc_row.cols[ colnum + 1 ], 
                                NULL, 0 );
 
+               colnum += 2;
+               if ( ( oc_row.ncols > colnum ) &&
+                               ( oc_row.value_len[ colnum ] > 0 ) )
+               {
+                       const char      *text;
+
+                       oc_map->bom_create_hint = NULL;
+                       rc = slap_str2ad( oc_row.cols[ colnum ],
+                                       &oc_map->bom_create_hint, &text );
+                       if ( rc != SQL_SUCCESS ) {
+                               Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
+                                               "error matching "
+                                               "AttributeDescription %s "
+                                               "in create_hint: %s (%d)\n",
+                                               oc_row.cols[ colnum ],
+                                               text, rc );
+                               backsql_PrintErrors( bi->sql_db_env, dbh,
+                                               sth, rc );
+                               return LDAP_OTHER;
+                       }
+               }
+
                /*
                 * FIXME: first attempt to check for offending
                 * instructions in {create|delete}_proc
@@ -593,22 +622,27 @@ backsql_load_schema_map( backsql_info *bi, SQLHDBC dbh )
                }
                oc_id = oc_map->bom_id;
                Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): "
-                       "objectClass \"%s\": keytbl=\"%s\" keycol=\"%s\"\n",
+                       "objectClass \"%s\":\n    keytbl=\"%s\" keycol=\"%s\"\n",
                        BACKSQL_OC_NAME( oc_map ),
                        oc_map->bom_keytbl.bv_val, oc_map->bom_keycol.bv_val );
                if ( oc_map->bom_create_proc ) {
-                       Debug( LDAP_DEBUG_TRACE, "create_proc=\"%s\"\n",
+                       Debug( LDAP_DEBUG_TRACE, "    create_proc=\"%s\"\n",
                                oc_map->bom_create_proc, 0, 0 );
                }
                if ( oc_map->bom_create_keyval ) {
-                       Debug( LDAP_DEBUG_TRACE, "create_keyval=\"%s\"\n",
+                       Debug( LDAP_DEBUG_TRACE, "    create_keyval=\"%s\"\n",
                                oc_map->bom_create_keyval, 0, 0 );
                }
+               if ( oc_map->bom_create_hint ) {
+                       Debug( LDAP_DEBUG_TRACE, "    create_hint=\"%s\"\n", 
+                               oc_map->bom_create_hint->ad_cname.bv_val,
+                               0, 0 );
+               }
                if ( oc_map->bom_delete_proc ) {
-                       Debug( LDAP_DEBUG_TRACE, "delete_proc=\"%s\"\n", 
+                       Debug( LDAP_DEBUG_TRACE, "    delete_proc=\"%s\"\n", 
                                oc_map->bom_delete_proc, 0, 0 );
                }
-               Debug( LDAP_DEBUG_TRACE, "expect_return: "
+               Debug( LDAP_DEBUG_TRACE, "    expect_return: "
                        "add=%d, del=%d; attributes:\n",
                        BACKSQL_IS_ADD( oc_map->bom_expect_return ), 
                        BACKSQL_IS_DEL( oc_map->bom_expect_return ), 0 );
index c43abc2053a390c58c498f2505f052f9e9eab092..3d06c436d630c14daeb7c200771f4c096e063304 100644 (file)
@@ -119,6 +119,7 @@ backsql_init_search(
        int                     rc = LDAP_SUCCESS;
 
        bsi->bsi_base_ndn = nbase;
+       bsi->bsi_use_subtree_shortcut = 0;
        BER_BVZERO( &bsi->bsi_base_id.eid_dn );
        BER_BVZERO( &bsi->bsi_base_id.eid_ndn );
        bsi->bsi_scope = scope;
@@ -194,8 +195,7 @@ backsql_init_search(
        if ( flags & BACKSQL_ISF_GET_ID ) {
                assert( op->o_bd->be_private );
 
-               rc = backsql_dn2id( op, rs, &bsi->bsi_base_id, dbh, nbase,
-                               ( flags & BACKSQL_ISF_MUCK ) );
+               rc = backsql_dn2id( op, rs, &bsi->bsi_base_id, dbh, nbase, 1 );
        }
 
        return ( bsi->bsi_status = rc );
@@ -261,15 +261,17 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f,
 
        /* always uppercase strings by now */
 #ifdef BACKSQL_UPPERCASE_FILTER
-       if ( SLAP_MR_ASSOCIATED( f->f_sub_desc->ad_type->sat_substr,
-                       bi->sql_caseIgnoreMatch ) )
+       if ( f->f_sub_desc->ad_type->sat_substr &&
+                       SLAP_MR_ASSOCIATED( f->f_sub_desc->ad_type->sat_substr,
+                               bi->sql_caseIgnoreMatch ) )
 #endif /* BACKSQL_UPPERCASE_FILTER */
        {
                casefold = 1;
        }
 
-       if ( SLAP_MR_ASSOCIATED( f->f_sub_desc->ad_type->sat_substr,
-                       bi->sql_telephoneNumberMatch ) )
+       if ( f->f_sub_desc->ad_type->sat_substr &&
+                       SLAP_MR_ASSOCIATED( f->f_sub_desc->ad_type->sat_substr,
+                               bi->sql_telephoneNumberMatch ) )
        {
 
                struct berval   bv;
@@ -598,8 +600,8 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
                                backsql_merge_from_tbls( bsi, &ldap_entry_objclasses );
 
                                backsql_strfcat( &bsi->bsi_flt_where, "lbl",
-                                               (ber_len_t)STRLENOF( "1=1 OR (ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */ ),
-                                                       "1=1 OR (ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */,
+                                               (ber_len_t)STRLENOF( "2=2 OR (ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */ ),
+                                                       "2=2 OR (ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */,
                                                &bsi->bsi_oc->bom_oc->soc_cname,
                                                (ber_len_t)STRLENOF( /* (' */ "')" ),
                                                        /* (' */ "')" );
@@ -613,7 +615,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
 
                case LDAP_FILTER_PRESENT:
                        backsql_strfcat( &bsi->bsi_flt_where, "l",
-                                       (ber_len_t)STRLENOF( "1=1" ), "1=1" );
+                                       (ber_len_t)STRLENOF( "3=3" ), "3=3" );
                        bsi->bsi_status = LDAP_SUCCESS;
                        rc = 1;
                        goto done;
@@ -666,7 +668,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
 
                case LDAP_FILTER_PRESENT:
                        backsql_strfcat( &bsi->bsi_flt_where, "l",
-                                       (ber_len_t)STRLENOF( "1=1" ), "1=1" );
+                                       (ber_len_t)STRLENOF( "4=4" ), "4=4" );
                        break;
 
                default:
@@ -696,7 +698,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
                /* if doing a syncrepl, try to return as much as possible,
                 * and always match the filter */
                backsql_strfcat( &bsi->bsi_flt_where, "l",
-                               (ber_len_t)STRLENOF( "1=1" ), "1=1" );
+                               (ber_len_t)STRLENOF( "5=5" ), "5=5" );
 
                /* save for later use in operational attributes */
                /* FIXME: saves only the first occurrence, because 
@@ -730,7 +732,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
                 * candidate.
                 */
                backsql_strfcat( &bsi->bsi_flt_where, "l",
-                               (ber_len_t)STRLENOF( "1=1" ), "1=1" );
+                               (ber_len_t)STRLENOF( "6=6" ), "6=6" );
                if ( ad == slap_schema.si_ad_hasSubordinates ) {
                        /*
                         * instruct candidate selection algorithm
@@ -763,7 +765,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
                /* search anyway; other parts of the filter
                 * may succeeed */
                backsql_strfcat( &bsi->bsi_flt_where, "l",
-                               (ber_len_t)STRLENOF( "1=1" ), "1=1" );
+                               (ber_len_t)STRLENOF( "7=7" ), "7=7" );
                bsi->bsi_status = LDAP_SUCCESS;
                rc = 1;
                goto done;
@@ -1015,10 +1017,13 @@ equality_match:;
                /* fall thru to next case */
                
        case LDAP_FILTER_LE:
+               filter_value = &f->f_av_value;
+               
                /* always uppercase strings by now */
 #ifdef BACKSQL_UPPERCASE_FILTER
-               if ( SLAP_MR_ASSOCIATED( at->bam_ad->ad_type->sat_ordering,
-                               bi->sql_caseIgnoreMatch ) )
+               if ( at->bam_ad->ad_type->sat_ordering &&
+                               SLAP_MR_ASSOCIATED( at->bam_ad->ad_type->sat_ordering,
+                                       bi->sql_caseIgnoreMatch ) )
 #endif /* BACKSQL_UPPERCASE_FILTER */
                {
                        casefold = 1;
@@ -1086,7 +1091,7 @@ equality_match:;
                /* unhandled filter type; should not happen */
                assert( 0 );
                backsql_strfcat( &bsi->bsi_flt_where, "l",
-                               (ber_len_t)STRLENOF( "1=1" ), "1=1" );
+                               (ber_len_t)STRLENOF( "8=8" ), "8=8" );
                break;
 
        }
@@ -1106,6 +1111,8 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query )
        assert( query );
        BER_BVZERO( query );
 
+       bsi->bsi_use_subtree_shortcut = 0;
+
        Debug( LDAP_DEBUG_TRACE, "==>backsql_srch_query()\n", 0, 0, 0 );
        BER_BVZERO( &bsi->bsi_sel.bb_val );
        BER_BVZERO( &bsi->bsi_sel.bb_val );
@@ -1205,11 +1212,40 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query )
        case LDAP_SCOPE_SUBORDINATE:
 #endif /* LDAP_SCOPE_SUBORDINATE */
        case LDAP_SCOPE_SUBTREE:
-               if ( BACKSQL_CANUPPERCASE( bi ) ) {
+               if ( BACKSQL_USE_SUBTREE_SHORTCUT( bi ) ) {
+                       int             i;
+                       BackendDB       *bd = bsi->bsi_op->o_bd;
+
+                       assert( bd->be_nsuffix );
+
+                       for ( i = 0; !BER_BVISNULL( &bd->be_nsuffix[ i ] ); i++ )
+                       {
+                               if ( dn_match( &bd->be_nsuffix[ i ],
+                                                       bsi->bsi_base_ndn ) )
+                               {
+                                       /* pass this to the candidate selection
+                                        * routine so that the DN is not bound
+                                        * to the select statement */
+                                       bsi->bsi_use_subtree_shortcut = 1;
+                                       break;
+                               }
+                       }
+               }
+
+               if ( bsi->bsi_use_subtree_shortcut ) {
+                       /* Skip the base DN filter, as every entry will match it */
+                       backsql_strfcat( &bsi->bsi_join_where, "l",
+                                       (ber_len_t)STRLENOF( "9=9"), "9=9");
+
+               } else if ( !BER_BVISNULL( &bi->sql_subtree_cond ) ) {
+                       backsql_strfcat( &bsi->bsi_join_where, "b", &bi->sql_subtree_cond );
+
+               } else if ( BACKSQL_CANUPPERCASE( bi ) ) {
                        backsql_strfcat( &bsi->bsi_join_where, "bl",
                                        &bi->sql_upper_func,
                                        (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE ?" ),
                                                "(ldap_entries.dn) LIKE ?"  );
+
                } else {
                        backsql_strfcat( &bsi->bsi_join_where, "l",
                                        (ber_len_t)STRLENOF( "ldap_entries.dn LIKE ?" ),
@@ -1270,7 +1306,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
        backsql_srch_info       *bsi = v_bsi;
        backsql_info            *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
        struct berval           query;
-       SQLHSTMT                sth;
+       SQLHSTMT                sth = SQL_NULL_HSTMT;
        RETCODE                 rc;
        int                     res;
        BACKSQL_ROW_NTS         row;
@@ -1402,6 +1438,12 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
 #endif /* LDAP_SCOPE_SUBORDINATE */
        case LDAP_SCOPE_SUBTREE:
        {
+               /* if short-cutting the search base,
+                * don't bind any parameter */
+               if ( bsi->bsi_use_subtree_shortcut ) {
+                       break;
+               }
+               
                /*
                 * We do not accept DNs longer than BACKSQL_MAX_DN_LEN;
                 * however this should be handled earlier
@@ -1595,7 +1637,7 @@ int
 backsql_search( Operation *op, SlapReply *rs )
 {
        backsql_info            *bi = (backsql_info *)op->o_bd->be_private;
-       SQLHDBC                 dbh;
+       SQLHDBC                 dbh = SQL_NULL_HDBC;
        int                     sres;
        Entry                   user_entry = { 0 };
        int                     manageDSAit;
@@ -1610,7 +1652,7 @@ backsql_search( Operation *op, SlapReply *rs )
        Debug( LDAP_DEBUG_TRACE, "==>backsql_search(): "
                "base=\"%s\", filter=\"%s\", scope=%d,", 
                op->o_req_ndn.bv_val,
-               op->ors_filterstr.bv_val,
+               op->ors_filterstr.bv_val ? op->ors_filterstr.bv_val : "(no filter)",
                op->ors_scope );
        Debug( LDAP_DEBUG_TRACE, " deref=%d, attrsonly=%d, "
                "attributes to load: %s\n",
@@ -1663,7 +1705,7 @@ backsql_search( Operation *op, SlapReply *rs )
                        op->ors_slimit, op->ors_tlimit,
                        stoptime, op->ors_filter,
                        dbh, op, rs, op->ors_attrs,
-                       ( BACKSQL_ISF_GET_ID | BACKSQL_ISF_MUCK ) );
+                       BACKSQL_ISF_GET_ID );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                send_ldap_result( op, rs );
                goto done;
@@ -1831,9 +1873,9 @@ backsql_search( Operation *op, SlapReply *rs )
                                (void)backsql_init_search( &bsi2,
                                                &e->e_nname,
                                                LDAP_SCOPE_BASE, 
-                                               -1, -1, -1, NULL,
-                                               dbh, op, rs, NULL,
-                                               BACKSQL_ISF_MUCK );
+                                               SLAP_NO_LIMIT, SLAP_NO_LIMIT,
+                                               (time_t)(-1), NULL,
+                                               dbh, op, rs, NULL, 0 );
                                bsi2.bsi_e = &user_entry2;
                                rc = backsql_id2entry( &bsi2, eid );
                                if ( rc == LDAP_SUCCESS ) {
@@ -2054,7 +2096,7 @@ backsql_entry_get(
                Entry                   **ent )
 {
        backsql_srch_info       bsi;
-       SQLHDBC                 dbh;
+       SQLHDBC                 dbh = SQL_NULL_HDBC;
        int                     rc;
        SlapReply               rs = { 0 };
        AttributeName           anlist[ 2 ];
@@ -2073,9 +2115,10 @@ backsql_entry_get(
        rc = backsql_init_search( &bsi,
                        ndn,
                        LDAP_SCOPE_BASE, 
-                       SLAP_NO_LIMIT, SLAP_NO_LIMIT, -1, NULL,
+                       SLAP_NO_LIMIT, SLAP_NO_LIMIT,
+                       (time_t)(-1), NULL,
                        dbh, op, &rs, at ? anlist : NULL,
-                       ( BACKSQL_ISF_GET_ID | BACKSQL_ISF_MUCK ) );
+                       BACKSQL_ISF_GET_ID );
        if ( rc != LDAP_SUCCESS ) {
                return rc;
        }