]> git.sur5r.net Git - openldap/commitdiff
handle referrals correctly; allow to add suffix entry; fix multiple values add bug...
authorPierangelo Masarati <ando@openldap.org>
Sat, 21 Aug 2004 09:38:08 +0000 (09:38 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sat, 21 Aug 2004 09:38:08 +0000 (09:38 +0000)
servers/slapd/back-sql/add.c
servers/slapd/back-sql/back-sql.h
servers/slapd/back-sql/schema-map.c
servers/slapd/back-sql/search.c

index a938b1697815a30348b39a53f429294ddcc45dd4..b3e51aea4c17542ec9120a6040f7ae40ade1bfac 100644 (file)
@@ -76,7 +76,7 @@ backsql_modify_internal(
                SQLUSMALLINT            pno, po;
                /* procedure return code */
                int                     prc;
-
+               
 #ifdef BACKSQL_REALLOC_STMT
                SQLAllocStmt( dbh, &sth );
 #endif /* BACKSQL_REALLOC_STMT */
@@ -321,6 +321,20 @@ add_only:;
                        for ( i = 0, at_val = c_mod->sm_values;
                                        at_val->bv_val != NULL; 
                                        i++, at_val++ ) {
+
+                               rc = backsql_Prepare( dbh, &sth, at->bam_add_proc, 0 );
+                               if ( rc != SQL_SUCCESS ) {
+                                       Debug( LDAP_DEBUG_TRACE,
+                                               "   backsql_modify_internal(): "
+                                               "error preparing add query\n", 
+                                               0, 0, 0 );
+                                       backsql_PrintErrors( bi->db_env, dbh, sth, rc );
+
+                                       rs->sr_err = LDAP_OTHER;
+                                       rs->sr_text = "SQL-backend error";
+                                       goto done;
+                               }
+
                                if ( BACKSQL_IS_ADD( at->bam_expect_return ) ) {
                                        pno = 1;
                                        SQLBindParameter( sth, 1,
@@ -357,8 +371,7 @@ add_only:;
                                        "   backsql_modify_internal(): "
                                        "executing \"%s\"\n", 
                                        at->bam_add_proc, 0, 0 );
-                               rc = SQLExecDirect( sth, at->bam_add_proc, 
-                                               SQL_NTS );
+                               rc = SQLExecute( sth );
                                if ( rc != SQL_SUCCESS ) {
                                        Debug( LDAP_DEBUG_TRACE,
                                                "   backsql_modify_internal(): "
@@ -516,7 +529,8 @@ backsql_add( Operation *op, SlapReply *rs )
        SQLUSMALLINT            pno, po;
        /* procedure return code */
        int                     prc;
-       struct berval           realdn, realpdn;
+       struct berval           realdn = BER_BVNULL,
+                               realpdn = BER_BVNULL;
 
        Debug( LDAP_DEBUG_TRACE, "==>backsql_add(\"%s\")\n",
                        op->oq_add.rs_e->e_name.bv_val, 0, 0 );
@@ -616,9 +630,14 @@ backsql_add( Operation *op, SlapReply *rs )
        }
 
        /*
-        * Check if parent exists
+        * Get the parent dn and see if the corresponding entry exists.
         */
-       dnParent( &op->oq_add.rs_e->e_name, &pdn );
+       if ( be_issuffix( op->o_bd, &op->oq_add.rs_e->e_nname ) ) {
+               pdn = slap_empty_bv;
+       } else {
+               dnParent( &op->oq_add.rs_e->e_nname, &pdn );
+       }
+
        realpdn = pdn;
        if ( backsql_api_dn2odbc( op, rs, &realpdn ) ) {
                Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
@@ -640,60 +659,73 @@ backsql_add( Operation *op, SlapReply *rs )
                }
 
                /*
-                * Look for matched
+                * no parent!
+                *  if not attempting to add entry at suffix or with parent ""
                 */
-               while ( 1 ) {
-                       struct berval   dn;
-                       char            *matched = NULL;
-
-                       if ( realpdn.bv_val != pdn.bv_val ) {
-                               ch_free( realpdn.bv_val );
-                       }
-
-                       dn = pdn;
-                       dnParent( &dn, &pdn );
-
+               if ( ( ( !be_isroot( op ) && !be_shadow_update( op ) )
+                       || pdn.bv_len > 0 ) && !is_entry_glue( op->oq_add.rs_e ) )
+               {
+                       Debug( LDAP_DEBUG_TRACE, "   backsql_add: %s denied\n",
+                               pdn.bv_len == 0 ? "suffix" : "entry at root",
+                               0, 0 );
                        /*
-                        * Empty DN ("") defaults to LDAP_SUCCESS
+                        * Look for matched
                         */
-                       realpdn = pdn;
-                       if ( backsql_api_dn2odbc( op, rs, &realpdn ) ) {
-                               Debug( LDAP_DEBUG_TRACE,
-                                       "   backsql_add(\"%s\"): "
-                                       "backsql_api_dn2odbc failed\n", 
-                                       op->oq_add.rs_e->e_name.bv_val, 0, 0 );
-                               rs->sr_err = LDAP_OTHER;
-                               rs->sr_text = "SQL-backend error";
-                               goto done;
+                       while ( 1 ) {
+                               struct berval   dn;
+                               char            *matched = NULL;
+       
+                               if ( realpdn.bv_val != pdn.bv_val ) {
+                                       ch_free( realpdn.bv_val );
+                               }
+       
+                               dn = pdn;
+                               dnParent( &dn, &pdn );
+       
+                               /*
+                                * Empty DN ("") defaults to LDAP_SUCCESS
+                                */
+                               realpdn = pdn;
+                               if ( backsql_api_dn2odbc( op, rs, &realpdn ) ) {
+                                       Debug( LDAP_DEBUG_TRACE,
+                                               "   backsql_add(\"%s\"): "
+                                               "backsql_api_dn2odbc failed\n", 
+                                               op->oq_add.rs_e->e_name.bv_val, 0, 0 );
+                                       rs->sr_err = LDAP_OTHER;
+                                       rs->sr_text = "SQL-backend error";
+                                       goto done;
+                               }
+       
+                               rs->sr_err = backsql_dn2id( bi, NULL, dbh, &realpdn );
+                               switch ( rs->sr_err ) {
+                               case LDAP_NO_SUCH_OBJECT:
+                                       if ( pdn.bv_len > 0 ) {
+                                               break;
+                                       }
+                                       /* fail over to next case */
+                                       
+                               case LDAP_SUCCESS:
+                                       matched = pdn.bv_val;
+                                       /* fail over to next case */
+       
+                               default:
+                                       rs->sr_err = LDAP_NO_SUCH_OBJECT;
+                                       rs->sr_matched = matched;
+                                       goto done;
+                               } 
                        }
+               } else {
 
-                       rs->sr_err = backsql_dn2id( bi, NULL, dbh, &realpdn );
-                       switch ( rs->sr_err ) {
-                       case LDAP_NO_SUCH_OBJECT:
-                               if ( pdn.bv_len > 0 ) {
-                                       break;
-                               }
-                               /* fail over to next case */
-                               
-                       case LDAP_SUCCESS:
-                               matched = pdn.bv_val;
-                               /* fail over to next case */
-
-                       default:
-                               rs->sr_err = LDAP_NO_SUCH_OBJECT;
-                               rs->sr_matched = matched;
-                               goto done;
-                       } 
+#ifdef BACKSQL_ARBITRARY_KEY
+                       ber_str2bv( "SUFFIX", 0, 1, &parent_id.eid_id );
+#else /* ! BACKSQL_ARBITRARY_KEY */
+                       parent_id.eid_id = 0;
+#endif /* ! BACKSQL_ARBITRARY_KEY */
+                       rs->sr_err = LDAP_SUCCESS;
                }
        }
 
-       /*
-        * create_proc is executed; if expect_return is set, then
-        * an output parameter is bound, which should contain 
-        * the id of the added row; otherwise the procedure
-        * is expected to return the id as the first column of a select
-        */
-
+       /* check "children" pseudo-attribute access to parent */
        p.e_attrs = NULL;
        p.e_name = pdn;
        dnParent( &op->oq_add.rs_e->e_nname, &p.e_nname );
@@ -703,6 +735,13 @@ backsql_add( Operation *op, SlapReply *rs )
                goto done;
        }
 
+       /*
+        * create_proc is executed; if expect_return is set, then
+        * an output parameter is bound, which should contain 
+        * the id of the added row; otherwise the procedure
+        * is expected to return the id as the first column of a select
+        */
+
        rc = SQLAllocStmt( dbh, &sth );
        if ( rc != SQL_SUCCESS ) {
                rs->sr_err = LDAP_OTHER;
@@ -887,40 +926,41 @@ backsql_add( Operation *op, SlapReply *rs )
                        continue;
                }
 
+               for ( i = 0, at_val = &at->a_vals[ i ];
+                               at_val->bv_val != NULL;
+                               i++, at_val = &at->a_vals[ i ] )
+               {
+                       char logbuf[] = "val[18446744073709551615UL], id=18446744073709551615UL";
+                       
 #ifdef BACKSQL_REALLOC_STMT
-               rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 );
-               if ( rc != SQL_SUCCESS ) {
+                       rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 );
+                       if ( rc != SQL_SUCCESS ) {
 
-                       if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
-                               rs->sr_err = LDAP_OTHER;
-                               rs->sr_text = "SQL-backend error";
-                               goto done;
-                       }
+                               if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+                                       rs->sr_err = LDAP_OTHER;
+                                       rs->sr_text = "SQL-backend error";
+                                       goto done;
+                               }
 
-                       continue;
-               }
+                               goto next_attr;
+                       }
 #endif /* BACKSQL_REALLOC_STMT */
 
-               if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) {
-                       pno = 1;
-                       SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT,
-                                       SQL_C_ULONG, SQL_INTEGER,
-                                       0, 0, &prc, 0, 0 );
-               } else {
-                       pno = 0;
-               }
-
-               po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0;
-               currpos = pno + 1 + po;
-               SQLBindParameter( sth, currpos,
-                               SQL_PARAM_INPUT, SQL_C_ULONG,
-                               SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
-               currpos = pno + 2 - po;
+                       if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) {
+                               pno = 1;
+                               SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT,
+                                               SQL_C_ULONG, SQL_INTEGER,
+                                               0, 0, &prc, 0, 0 );
+                       } else {
+                               pno = 0;
+                       }
 
-               for ( i = 0, at_val = &at->a_vals[ i ];
-                               at_val->bv_val != NULL;
-                               i++, at_val = &at->a_vals[ i ] ) {
-                       char logbuf[] = "val[18446744073709551615UL], id=18446744073709551615UL";
+                       po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0;
+                       currpos = pno + 1 + po;
+                       SQLBindParameter( sth, currpos,
+                                       SQL_PARAM_INPUT, SQL_C_ULONG,
+                                       SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
+                       currpos = pno + 2 - po;
 
                        /*
                         * Do not deal with the objectClass that is used
@@ -966,12 +1006,14 @@ backsql_add( Operation *op, SlapReply *rs )
                                        goto done;
                                }
                        }
-               }
 #ifndef BACKSQL_REALLOC_STMT
-               SQLFreeStmt( sth, SQL_RESET_PARAMS ); 
+                       SQLFreeStmt( sth, SQL_RESET_PARAMS ); 
 #else /* BACKSQL_REALLOC_STMT */
-               SQLFreeStmt( sth, SQL_DROP );
+                       SQLFreeStmt( sth, SQL_DROP );
 #endif /* BACKSQL_REALLOC_STMT */
+               }
+
+next_attr:;
        }
 
 #ifdef BACKSQL_REALLOC_STMT
@@ -983,8 +1025,7 @@ backsql_add( Operation *op, SlapReply *rs )
        }
 #endif /* BACKSQL_REALLOC_STMT */
        
-       backsql_BindParamStr( sth, 1, op->oq_add.rs_e->e_name.bv_val,
-                       BACKSQL_MAX_DN_LEN );
+       backsql_BindParamStr( sth, 1, realdn.bv_val, BACKSQL_MAX_DN_LEN );
        SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
                        0, 0, &oc->bom_id, 0, 0 );
 #ifdef BACKSQL_ARBITRARY_KEY
@@ -1050,13 +1091,15 @@ backsql_add( Operation *op, SlapReply *rs )
 done:;
        send_ldap_result( op, rs );
 
-       if ( realdn.bv_val != op->oq_add.rs_e->e_name.bv_val ) {
+       if ( !BER_BVISNULL( &realdn )
+                       && realdn.bv_val != op->oq_add.rs_e->e_name.bv_val )
+       {
                ch_free( realdn.bv_val );
        }
-       if ( realpdn.bv_val != pdn.bv_val ) {
+       if ( !BER_BVISNULL( &realpdn ) && realpdn.bv_val != pdn.bv_val ) {
                ch_free( realpdn.bv_val );
        }
-       if ( parent_id.eid_dn.bv_val != NULL ) {
+       if ( !BER_BVISNULL( &parent_id.eid_dn ) ) {
                backsql_free_entryID( &parent_id, 0 );
        }
 
index de5e279edc148cf42582b993c68ac9e0984366eb..6bfedc643cb0bdf2ea7474cfd9df2f08ea46076f 100644 (file)
@@ -250,6 +250,7 @@ typedef struct backsql_srch_info {
        time_t                  bsi_stoptime;
 
        backsql_entryID         *bsi_id_list,
+                               **bsi_id_listtail,
                                *bsi_c_eid;
        int                     bsi_n_candidates;
        int                     bsi_abandon;
index 69bd1c293ee268943bdc54da1f3bfb36cd39261f..e7d701b8bce4dfd52fceef50a1ae30b31abf5f09 100644 (file)
@@ -41,7 +41,10 @@ backsql_cmp_oc( const void *v_m1, const void *v_m2 )
 {
        const backsql_oc_map_rec *m1 = v_m1, *m2 = v_m2;
 
+#if 0
        return SLAP_PTRCMP( m1->bom_oc, m2->bom_oc );
+#endif
+       return ber_bvcmp( &m1->bom_oc->soc_cname, &m2->bom_oc->soc_cname );
 }
 
 static int
@@ -60,7 +63,10 @@ backsql_cmp_attr( const void *v_m1, const void *v_m2 )
 {
        const backsql_at_map_rec *m1 = v_m1, *m2 = v_m2;
 
+#if 0
        return SLAP_PTRCMP( m1->bam_ad, m2->bam_ad );
+#endif
+       return ber_bvcmp( &m1->bam_ad->ad_cname, &m2->bam_ad->ad_cname );
 }
 
 int
index e14733b53b9cb1355c18e22cbe8090392cc4326b..ed43829b12ce0de978507c1fcc38b6a54d140c8c 100644 (file)
@@ -126,6 +126,8 @@ backsql_init_search(
                bsi->bsi_attrs = NULL;
 
        } else {
+               int     is_oc = 0;
+
                bsi->bsi_attrs = (AttributeName *)ch_calloc( 1, 
                                sizeof( AttributeName ) );
                BER_BVZERO( &bsi->bsi_attrs[ 0 ].an_name );
@@ -140,14 +142,25 @@ backsql_init_search(
 
                        } else if ( BACKSQL_NCMP( &p->an_name, &NoAttrs ) == 0 ) {
                                continue;
+                       } else if ( p->an_desc == slap_schema.si_ad_objectClass ) {
+                               is_oc = 1;
                        }
 
                        backsql_attrlist_add( bsi, p->an_desc );
                }
+
+               if ( is_oc == 0 ) {
+                       /* add objectClass if not present,
+                        * because it is required to understand
+                        * if an entry is a referral, an alias 
+                        * or so... */
+                       backsql_attrlist_add( bsi, slap_schema.si_ad_objectClass );
+               }
        }
 
        bsi->bsi_abandon = 0;
        bsi->bsi_id_list = NULL;
+       bsi->bsi_id_listtail = &bsi->bsi_id_list;
        bsi->bsi_n_candidates = 0;
        bsi->bsi_stoptime = stoptime;
        BER_BVZERO( &bsi->bsi_sel.bb_val );
@@ -1315,9 +1328,10 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
                        c_id->eid_dn = dn;
                }
 
-               c_id->eid_next = bsi->bsi_id_list;
-               bsi->bsi_id_list = c_id;
-               bsi->bsi_n_candidates--;
+               /* append at end of list ... */
+               c_id->eid_next = NULL;
+               *bsi->bsi_id_listtail = c_id;
+               bsi->bsi_id_listtail = &c_id->eid_next;
 
 #ifdef BACKSQL_ARBITRARY_KEY
                Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
@@ -1330,6 +1344,8 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
                        c_id->eid_id, c_id->eid_keyval, row.cols[ 3 ] );
 #endif /* ! BACKSQL_ARBITRARY_KEY */
 
+               /* count candidates, for unchecked limit */
+               bsi->bsi_n_candidates--;
                if ( bsi->bsi_n_candidates == -1 ) {
                        break;
                }
@@ -1495,6 +1511,28 @@ backsql_search( Operation *op, SlapReply *rs )
 
                        ber_dupbv( &matched_dn, &user_entry.e_name );
                        refs = get_entry_referrals( op, &user_entry );
+                       if ( !refs ) {
+                               backsql_srch_info       srch_info2 = { 0 };
+                               Entry                   user_entry2 = { 0 };
+
+                               /* retry with the full entry... */
+                               backsql_init_search( &srch_info2,
+                                               &user_entry.e_name,
+                                               LDAP_SCOPE_BASE, 
+                                               -1, -1, -1, NULL,
+                                               dbh, op, rs, NULL );
+                               srch_info2.bsi_e = &user_entry2;
+                               rc = backsql_id2entry( &srch_info2, eid );
+                               if ( rc == LDAP_SUCCESS ) {
+                                       if ( is_entry_referral( &user_entry2 ) )
+                                       {
+                                               refs = get_entry_referrals( op,
+                                                               &user_entry2 );
+                                       } /* else: FIXME: inconsistency! */
+                                       entry_clean( &user_entry2 );
+                               }
+                       }
+
                        if ( refs ) {
                                rs->sr_ref = referral_rewrite( refs,
                                                &matched_dn, &op->o_req_dn,
@@ -1515,7 +1553,7 @@ backsql_search( Operation *op, SlapReply *rs )
                        ber_memfree( matched_dn.bv_val );
                        rs->sr_matched = NULL;
 
-                       continue;
+                       goto next_entry;
                }
 
                /*
@@ -1546,11 +1584,7 @@ backsql_search( Operation *op, SlapReply *rs )
                                        "has_children failed( %d)\n", 
                                        rc, 0, 0 );
                                rc = 1;
-                               break;
-                       }
-
-                       if ( rc ) {
-                               continue;
+                               goto next_entry;
                        }
                }
 
@@ -1563,39 +1597,32 @@ backsql_search( Operation *op, SlapReply *rs )
                                hasSubordinate = NULL;
                        }
 
-#if 0  /* noop is masked SLAP_CTRL_UPDATE */
-                       if ( op->o_noop ) {
-                               sres = 0;
-                       } else
-#endif
-                       {
-                               rs->sr_attrs = op->ors_attrs;
-                               rs->sr_operational_attrs = NULL;
-                               rs->sr_entry = &user_entry;
-                               rs->sr_flags = REP_ENTRY_MODIFIABLE;
-                               sres = send_search_entry( op, rs );
-                               rs->sr_entry = NULL;
-                               rs->sr_attrs = NULL;
-                               rs->sr_operational_attrs = NULL;
-                       }
+                       rs->sr_attrs = op->ors_attrs;
+                       rs->sr_operational_attrs = NULL;
+                       rs->sr_entry = &user_entry;
+                       rs->sr_flags = REP_ENTRY_MODIFIABLE;
+                       sres = send_search_entry( op, rs );
+                       rs->sr_entry = NULL;
+                       rs->sr_attrs = NULL;
+                       rs->sr_operational_attrs = NULL;
 
                        switch ( sres ) {
                        case 0:
                                break;
 
-                       case -1:
-                               Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
-                                       "connection lost\n", 0, 0, 0 );
-                               goto end_of_search;
-
                        default:
                                /*
                                 * FIXME: send_search_entry failed;
                                 * better stop
                                 */
-                               break;
+                       case -1:
+                               Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
+                                       "connection lost\n", 0, 0, 0 );
+                               goto end_of_search;
                        }
                }
+
+next_entry:;
                entry_clean( &user_entry );
 
                if ( op->ors_slimit != SLAP_NO_LIMIT