From 115408986c62fea339b99f93dafc820bd8c94062 Mon Sep 17 00:00:00 2001
From: Pierangelo Masarati <ando@openldap.org>
Date: Tue, 13 Aug 2002 17:12:27 +0000
Subject: [PATCH] changes: - re-style according to the style giudelines for
 better readability - updated to recent frontend/backend API changes - fixed a
 few quirks about normalization - "optimized" a few memory allocation/string
 handling functions - fixed a few quirks about add/modify (still have to look
 ad modrdn)

todo:
- there is still something broken (at least with PostgreSQL and IBM db2,
  the two RDBMS O have at hand) when adding
- move everything to struct bervals and try to save a few strlen
- try some LDAP/SQL syntax relation to use appropriate value bind if possible
- ...
---
 servers/slapd/back-sql/back-sql.h   |   70 +-
 servers/slapd/back-sql/bind.c       |  180 ++--
 servers/slapd/back-sql/config.c     |  348 ++++---
 servers/slapd/back-sql/docs/install |    4 +-
 servers/slapd/back-sql/entry-id.c   |  461 +++++----
 servers/slapd/back-sql/entry-id.h   |   23 +-
 servers/slapd/back-sql/init.c       |  366 ++++---
 servers/slapd/back-sql/modify.c     | 1358 +++++++++++++++----------
 servers/slapd/back-sql/other.c      |   35 +-
 servers/slapd/back-sql/schema-map.c |  661 +++++++-----
 servers/slapd/back-sql/schema-map.h |   86 +-
 servers/slapd/back-sql/search.c     | 1456 ++++++++++++++++-----------
 servers/slapd/back-sql/sql-types.h  |   17 +-
 servers/slapd/back-sql/sql-wrap.c   |  666 +++++++-----
 servers/slapd/back-sql/sql-wrap.h   |   37 +-
 servers/slapd/back-sql/util.c       |  337 ++++---
 servers/slapd/back-sql/util.h       |   82 +-
 17 files changed, 3709 insertions(+), 2478 deletions(-)

diff --git a/servers/slapd/back-sql/back-sql.h b/servers/slapd/back-sql/back-sql.h
index d38b9d0120..02614e3ff2 100644
--- a/servers/slapd/back-sql/back-sql.h
+++ b/servers/slapd/back-sql/back-sql.h
@@ -10,35 +10,47 @@
  *	 in file LICENSE in the top-level directory of the distribution.
  */
 
-
 #include "external.h"
 #include "sql-types.h"
-#define BACKSQL_MAX_DN_LEN 255
-
-typedef struct
-{
- char *dbhost;
- int dbport;
- char *dbuser;
- char *dbpasswd;
- char *dbname;
- /*SQL condition for subtree searches differs in syntax:
- *"LIKE CONCAT('%',?)" or "LIKE '%'+?" or smth else */
- char *subtree_cond;
- char *oc_query,*at_query;
- char *insentry_query,*delentry_query;
- char *id_query;
- char *upper_func;
- Avlnode *db_conns;
- Avlnode *oc_by_name;
- Avlnode *oc_by_id;
- int schema_loaded;
- ldap_pvt_thread_mutex_t dbconn_mutex;
- ldap_pvt_thread_mutex_t schema_mutex;
- SQLHENV db_env;
- int   isTimesTen; /* TimesTen */
- int   has_ldapinfo_dn_ru;  /* Does ldapinfo.dn_ru exist in schema? */
-}backsql_info;
-
-#endif
+
+/*
+ * Better use the standard length of 8192 (as of servers/slapd/dn.c) ?
+ */
+#define BACKSQL_MAX_DN_LEN	255
+
+typedef struct {
+	char		*dbhost;
+	int		dbport;
+	char		*dbuser;
+	char		*dbpasswd;
+	char		*dbname;
+ 	/*
+	 * SQL condition for subtree searches differs in syntax:
+	 * "LIKE CONCAT('%',?)" or "LIKE '%'+?" or smth else 
+	 */
+	char		*subtree_cond;
+	char		*oc_query,*at_query;
+	char		*insentry_query,*delentry_query;
+	char		*id_query;
+	char		*upper_func;
+	char		*strcast_func;
+	Avlnode		*db_conns;
+	Avlnode		*oc_by_name;
+	Avlnode		*oc_by_id;
+	int		schema_loaded;
+	ldap_pvt_thread_mutex_t		dbconn_mutex;
+	ldap_pvt_thread_mutex_t		schema_mutex;
+ 	SQLHENV		db_env;
+ 	int		isTimesTen;
+
+	/* 
+	 * Does ldapinfo.dn_ru exist in schema?
+	 */
+	int		has_ldapinfo_dn_ru;  
+} backsql_info;
+
+#define BACKSQL_SUCCESS( rc ) \
+	( (rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO )
+
+#endif /* __BACKSQL_H__ */
 
diff --git a/servers/slapd/back-sql/bind.c b/servers/slapd/back-sql/bind.c
index 35847d0bff..9c112c1960 100644
--- a/servers/slapd/back-sql/bind.c
+++ b/servers/slapd/back-sql/bind.c
@@ -19,91 +19,111 @@
 #include "util.h"
 #include "entry-id.h"
 
-int backsql_bind(BackendDB *be,Connection *conn,Operation *op,
-	struct berval *dn,struct berval *ndn,int method,struct berval *cred,struct berval *edn)
+int 
+backsql_bind(
+	BackendDB 	*be,
+	Connection 	*conn,
+	Operation 	*op,
+	struct berval 	*dn,
+	struct berval 	*ndn,
+	int method,
+	struct berval 	*cred,
+	struct berval 	*edn )
 {
- backsql_info *bi=(backsql_info*)be->be_private;
- backsql_entryID user_id,*res;
- SQLHDBC dbh;
- AttributeDescription *password = slap_schema.si_ad_userPassword;
- Entry		*e,user_entry;
- Attribute	*a;
- backsql_srch_info bsi;
+	backsql_info		*bi = (backsql_info*)be->be_private;
+	backsql_entryID		user_id;
+	SQLHDBC			dbh;
+	AttributeDescription	*password = slap_schema.si_ad_userPassword;
+	Entry			*e, user_entry;
+	Attribute		*a;
+	backsql_srch_info	bsi;
  
- Debug(LDAP_DEBUG_TRACE,"==>backsql_bind()\n",0,0,0);
- 
- if ( be_isroot_pw( be, conn, ndn, cred ) )
-    {
-     ber_dupbv(edn, be_root_dn(be));
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_bind() root bind\n",0,0,0);
-     return LDAP_SUCCESS;
-    }
- 
- ber_dupbv(edn, ndn);
- 
- if (method == LDAP_AUTH_SIMPLE)
-  {	 
-   dbh=backsql_get_db_conn(be,conn);
-
-   if (!dbh)
-    {
-     Debug(LDAP_DEBUG_TRACE,"backsql_bind(): could not get connection handle - exiting\n",0,0,0);
-     send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-     return 1;
-    }
-  
-   res=backsql_dn2id(bi,&user_id,dbh,ndn->bv_val);
-   if (res==NULL)
-    {
-     Debug(LDAP_DEBUG_TRACE,"backsql_bind(): could not retrieve bind dn id - no such entry\n",0,0,0);
-     send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,NULL, NULL, NULL, NULL );
-     return 1;
-    }
-    
-   backsql_init_search(&bsi,bi,(char*)ndn->bv_val,LDAP_SCOPE_BASE,-1,-1,-1,NULL,dbh,
-		 be,conn,op,NULL);
-   e=backsql_id2entry(&bsi,&user_entry,&user_id);
-   if (e==NULL)
-    {
-     Debug(LDAP_DEBUG_TRACE,"backsql_bind(): error in backsql_id2entry() - auth failed\n",0,0,0);
-     send_ldap_result( conn, op, LDAP_OTHER,NULL, NULL, NULL, NULL );
-     return 1;
-    }
-    
-   if ( ! access_allowed( be, conn, op, e, password, NULL, ACL_AUTH, NULL ) )
-    {
-     send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL );
-     return 1;
-    }
-
-   if ( (a = attr_find( e->e_attrs, password )) == NULL )
-    {
-     send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, NULL, NULL );
-     return 1;
-    }
-
-   if ( slap_passwd_check( conn, a, cred ) != 0 ) 
-    {
-     send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,NULL, NULL, NULL, NULL );
-     return 1;
-    }
-  }  
- else /*method != SIMPLE */
-  {
-   send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
-		    NULL, "authentication method not supported", NULL, NULL );
-   return 1;
-  }
- Debug(LDAP_DEBUG_TRACE,"<==backsql_bind()\n",0,0,0);
- return 0;
+ 	Debug( LDAP_DEBUG_TRACE, "==>backsql_bind()\n", 0, 0, 0 );
+
+	if ( be_isroot_pw( be, conn, ndn, cred ) ) {
+     		ber_dupbv( edn, be_root_dn( be ) );
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_bind() root bind\n", 
+				0, 0, 0 );
+		return LDAP_SUCCESS;
+	}
+
+	ber_dupbv( edn, ndn );
+
+	if ( method != LDAP_AUTH_SIMPLE ) {
+		send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
+	    		NULL, "authentication method not supported", 
+			NULL, NULL );
+		return 1;
+	}
+
+	/*
+	 * method = LDAP_AUTH_SIMPLE
+	 */
+	dbh = backsql_get_db_conn( be, conn );
+	if (!dbh) {
+     		Debug( LDAP_DEBUG_TRACE, "backsql_bind(): "
+			"could not get connection handle - exiting\n",
+			0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+
+	if ( backsql_dn2id( bi, &user_id, dbh, ndn ) != LDAP_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_bind(): "
+			"could not retrieve bind dn id - no such entry\n", 
+			0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
+				NULL, NULL, NULL, NULL );
+		return 1;
+	}
+
+	backsql_init_search( &bsi, bi, ndn, LDAP_SCOPE_BASE, -1, -1, -1,
+			NULL, dbh, be, conn, op, NULL );
+	e = backsql_id2entry( &bsi, &user_entry, &user_id );
+	if ( e == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_bind(): "
+			"error in backsql_id2entry() - auth failed\n",
+			0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OTHER,
+				NULL, NULL, NULL, NULL );
+		return 1;
+	}
+
+	if ( ! access_allowed( be, conn, op, e, password, NULL, 
+				ACL_AUTH, NULL ) ) {
+     		send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, 
+				NULL, NULL, NULL, NULL );
+		return 1;
+	}
+
+	if ( ( a = attr_find( e->e_attrs, password ) ) == NULL ) {
+		send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, 
+				NULL, NULL, NULL, NULL );
+		return 1;
+	}
+
+	if ( slap_passwd_check( conn, a, cred ) != 0 ) {
+		send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
+				NULL, NULL, NULL, NULL );
+		return 1;
+	}
+
+	Debug(LDAP_DEBUG_TRACE,"<==backsql_bind()\n",0,0,0);
+	return 0;
 }
  
-int backsql_unbind(BackendDB *be,Connection *conn,Operation *op)
+int
+backsql_unbind(
+	BackendDB 	*be,
+	Connection 	*conn,
+	Operation 	*op )
 {
- Debug(LDAP_DEBUG_TRACE,"==>backsql_unbind()\n",0,0,0);
- send_ldap_result(conn,op,LDAP_SUCCESS,NULL,NULL,NULL,0);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_unbind()\n",0,0,0);
- return 0;
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_unbind()\n", 0, 0, 0 );
+	send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 0 );
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_unbind()\n", 0, 0, 0 );
+	return 0;
 }
 
 #endif /* SLAPD_SQL */
+
diff --git a/servers/slapd/back-sql/config.c b/servers/slapd/back-sql/config.c
index 85c9cabf09..7403cc1d6e 100644
--- a/servers/slapd/back-sql/config.c
+++ b/servers/slapd/back-sql/config.c
@@ -18,170 +18,194 @@
 #include "back-sql.h"
 #include "sql-wrap.h"
 
-int backsql_db_config(BackendDB *be,const char *fname,int lineno,int argc,char **argv)
+int
+backsql_db_config(
+	BackendDB	*be,
+	const char	*fname,
+	int		lineno,
+	int		argc,
+	char		**argv )
 {
- backsql_info *si=(backsql_info*) be->be_private;
-
- Debug(LDAP_DEBUG_TRACE,"==>backsql_db_config()\n",0,0,0);
- if (!si)
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_db_config: be_private is NULL!!!\n",0,0,0);
-   exit(1);
-  }
-  
- if (!strcasecmp(argv[0],"dbhost"))
-  {
-   if (argc<2)
-    {
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config (%s line %d): missing hostname in dbhost directive\n",
-                     fname,lineno,0);
-    }
-   else
-    {
-     si->dbhost=ch_strdup(argv[1]);
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config(): hostname=%s\n",si->dbhost,0,0);
-    }
-   return(0);
-  }
-  
- if (!strcasecmp(argv[0],"dbuser"))
-  {
-   if (argc<2)
-    {
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config (%s line %d): missing username in dbuser directive\n",
-                     fname,lineno,0);
-    }
-   else
-    {
-     si->dbuser=ch_strdup(argv[1]);
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config(): dbuser=%s\n",argv[1],0,0);
-    }
-   return(0);
-  }
- 
- if (!strcasecmp(argv[0],"dbpasswd"))
-  {
-   if (argc<2)
-    {
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config (%s line %d): missing password in dbpasswd directive\n",
-                     fname,lineno,0);
-    }
-   else
-    {
-     si->dbpasswd=ch_strdup(argv[1]);
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config(): dbpasswd=%s\n",si->dbpasswd,0,0);
-    }
-   return(0);
-  }
+	backsql_info 	*si = (backsql_info *)be->be_private;
+
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_db_config()\n", 0, 0, 0 );
+	assert( si );
   
- if (!strcasecmp(argv[0],"dbname"))
-  {
-   if (argc<2)
-    {
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config (%s line %d): missing database name in dbname directive\n",
-                     fname,lineno,0);
-    }
-   else
-    {
-     si->dbname=ch_strdup(argv[1]);
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config(): dbname=%s\n",si->dbname,0,0);
-    }
-   return(0);
-  }
-
- if (!strcasecmp(argv[0],"subtree_cond"))
-  {
-   if (argc<2)
-    {
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config (%s line %d): missing SQL condition in subtree_cond directive\n",
-                     fname,lineno,0);
-    }
-   else
-    {
-     si->subtree_cond=ch_strdup(argv[1]);
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config(): subtree_cond=%s\n",si->subtree_cond,0,0);
-    }
-   return(0);
-  }
-
- if (!strcasecmp(argv[0],"oc_query"))
-  {
-   if (argc<2)
-    {
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config (%s line %d): missing SQL statement in oc_query directive\n",
-                     fname,lineno,0);
-    }
-   else
-    {
-     si->oc_query=ch_strdup(argv[1]);
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config(): oc_query=%s\n",si->oc_query,0,0);
-    }
-   return(0);
-  }
-
- if (!strcasecmp(argv[0],"at_query"))
-  {
-   if (argc<2)
-    {
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config (%s line %d): missing SQL statement in at_query directive\n",
-                     fname,lineno,0);
-    }
-   else
-    {
-     si->at_query=ch_strdup(argv[1]);
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config(): at_query=%s\n",si->at_query,0,0);
-    }
-   return(0);
-  }
-
- if (!strcasecmp(argv[0],"insentry_query"))
-  {
-   if (argc<2)
-    {
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config (%s line %d): missing SQL statement in insentry_query directive\n",
-                     fname,lineno,0);
-    }
-   else
-    {
-     si->insentry_query=ch_strdup(argv[1]);
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config(): insentry_query=%s\n",si->insentry_query,0,0);
-    }
-   return(0);
-  }
-
- if (!strcasecmp(argv[0],"upper_func"))
-  {
-   if (argc<2)
-    {
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config (%s line %d): missing function name in upper_func directive\n",
-                     fname,lineno,0);
-    }
-   else
-    {
-     si->upper_func=ch_strdup(argv[1]);
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config(): upper_func=%s\n",si->upper_func,0,0);
-    }
-   return(0);
-  }
-
- if (!strcasecmp(argv[0],"delentry_query"))
-  {
-   if (argc<2)
-    {
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config (%s line %d): missing SQL statement in delentry_query directive\n",
-                     fname,lineno,0);
-    }
-   else
-    {
-     si->delentry_query=ch_strdup(argv[1]);
-     Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config(): delentry_query=%s\n",si->delentry_query,0,0);
-    }
-   return(0);
-  }
- 
- Debug(LDAP_DEBUG_TRACE,"<==backsql_db_config (%s line %d): unknown directive '%s' (ignored)\n",
-                     fname,lineno,argv[0]);
- return 0;
+	if ( !strcasecmp( argv[ 0 ], "dbhost" ) ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE, 
+				"<==backsql_db_config (%s line %d): "
+				"missing hostname in dbhost directive\n",
+				fname, lineno, 0 );
+			return 1;
+	    	}
+		si->dbhost = ch_strdup( argv[ 1 ] );
+		Debug( LDAP_DEBUG_TRACE,
+			"<==backsql_db_config(): hostname=%s\n",
+			si->dbhost, 0, 0 );
+
+	} else if ( !strcasecmp( argv[ 0 ], "dbuser" ) ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE, 
+				"<==backsql_db_config (%s line %d): "
+				"missing username in dbuser directive\n",
+				fname, lineno, 0 );
+			return 1;
+		}
+		si->dbuser = ch_strdup( argv[ 1 ] );
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): dbuser=%s\n",
+			si->dbuser, 0, 0 );
+
+	} else if ( !strcasecmp( argv[ 0 ], "dbpasswd" ) ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE, 
+				"<==backsql_db_config (%s line %d): "
+				"missing password in dbpasswd directive\n",
+				fname, lineno, 0 );
+			return 1;
+		}
+		si->dbpasswd = ch_strdup( argv[ 1 ] );
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+			"dbpasswd=%s\n", /* si->dbpasswd */ "xxxx", 0, 0 );
+
+	} else if ( !strcasecmp( argv[ 0 ], "dbname" ) ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE, 
+				"<==backsql_db_config (%s line %d): "
+				"missing database name in dbname directive\n",
+				fname, lineno, 0 );
+			return 1;
+		}
+		si->dbname = ch_strdup( argv[ 1 ] );
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): dbname=%s\n",
+			si->dbname, 0, 0 );
+
+	} else if ( !strcasecmp( argv[ 0 ], "subtree_cond" ) ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE, 
+				"<==backsql_db_config (%s line %d): "
+				"missing SQL condition "
+				"in subtree_cond directive\n",
+				fname, lineno, 0 );
+			return 1;
+		}
+		si->subtree_cond = ch_strdup( argv[ 1 ] );
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+			"subtree_cond=%s\n", si->subtree_cond, 0, 0 );
+
+	} else if ( !strcasecmp( argv[ 0 ], "oc_query" ) ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE, 
+				"<==backsql_db_config (%s line %d): "
+				"missing SQL statement "
+				"in oc_query directive\n",
+				fname, lineno, 0 );
+			return 1;
+		}
+		si->oc_query = ch_strdup( argv[ 1 ] );
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+			"oc_query=%s\n", si->oc_query, 0, 0 );
+
+	} else if ( !strcasecmp( argv[ 0 ], "at_query" ) ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE,
+				"<==backsql_db_config (%s line %d): "
+				"missing SQL statement "
+				"in at_query directive\n",
+				fname, lineno, 0 );
+			return 1;
+		}
+		si->at_query = ch_strdup( argv[ 1 ] );
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+			"at_query=%s\n", si->at_query, 0, 0 );
+
+	} else if ( !strcasecmp( argv[ 0 ], "insentry_query" ) ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE, 
+				"<==backsql_db_config (%s line %d): "
+				"missing SQL statement "
+				"in insentry_query directive\n",
+				fname, lineno, 0 );
+			return 1;
+		}
+		si->insentry_query = ch_strdup( argv[ 1 ] );
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+			"insentry_query=%s\n", si->insentry_query, 0, 0 );
+
+	} else if ( !strcasecmp( argv[ 0 ], "upper_func" ) ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE,
+				"<==backsql_db_config (%s line %d): "
+				"missing function name "
+				"in upper_func directive\n",
+				fname, lineno, 0 );
+			return 1;
+		}
+		si->upper_func = ch_strdup( argv[ 1 ] );
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+			"upper_func=%s\n", si->upper_func, 0, 0 );
+
+	} else if ( !strcasecmp( argv[ 0 ], "strcast_func" ) ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE,
+				"<==backsql_db_config (%s line %d): "
+				"missing function name "
+				"in strcast_func directive\n",
+				fname, lineno, 0 );
+			return 1;
+		}
+		si->strcast_func = ch_strdup( argv[ 1 ] );
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+			"strcast_func=%s\n", si->strcast_func, 0, 0 );
+
+	} else if ( !strcasecmp( argv[ 0 ], "delentry_query" ) ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE,
+				"<==backsql_db_config (%s line %d): "
+				"missing SQL statement "
+				"in delentry_query directive\n",
+				fname, lineno, 0 );
+			return 1;
+		}
+		si->delentry_query = ch_strdup( argv[ 1 ] );
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+			"delentry_query=%s\n", si->delentry_query, 0, 0 );
+
+	} else if ( !strcasecmp( argv[ 0 ], "has_ldapinfo_dn_ru") ) {
+		if ( argc < 2 ) {
+			Debug( LDAP_DEBUG_TRACE,
+				"<==backsql_db_config (%s line %d): "
+				"missing { yes | no }"
+				"in has_ldapinfo_dn_ru directive\n",
+				fname, lineno, 0 );
+			return 1;
+		}
+
+		if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+			si->has_ldapinfo_dn_ru = 1;
+		} else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+			si->has_ldapinfo_dn_ru = 0;
+		} else {
+			Debug( LDAP_DEBUG_TRACE,
+				"<==backsql_db_config (%s line %d): "
+				"has_ldapinfo_dn_ru directive arg "
+				"must be \"yes\" or \"no\"\n",
+				fname, lineno, 0 );
+			return 1;
+
+		}
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+			"has_ldapinfo_dn_ru=%s\n", 
+			si->has_ldapinfo_dn_ru == 0 ? "no" : "yes", 0, 0 );
+
+	} else {
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): "
+			"unknown directive '%s' (ignored)\n",
+			fname, lineno, argv[ 0 ] );
+	}
+
+	return 0;
 }
 
 #endif /* SLAPD_SQL */
+
diff --git a/servers/slapd/back-sql/docs/install b/servers/slapd/back-sql/docs/install
index daa686367e..230bf0ad62 100644
--- a/servers/slapd/back-sql/docs/install
+++ b/servers/slapd/back-sql/docs/install
@@ -10,7 +10,7 @@ Then, at top of OpenLDAP source tree, run
 this should build back-sql-enabled slapd, provided that you have iODBC/unixODBC
 libraries and include files in include/library paths, "make install"...
 In other words, follow installation procedure described in OpenLDAP 
-Administrators Guide, adding --enbale-sql option to configure, and
+Administrators Guide, adding --enable-sql option to configure, and
 having iODBC/unixODBC libraries installed an accessible by compiler.
 
 Under Win32/MSVC++, I modified the workspace so that back-sql is built into
@@ -41,7 +41,7 @@ Several things worth noting about ODBC:
   Also worth noting are: ODBC-ODBC bridge by EasySoft (which was claimed
    by several people to be far more effective and stable than OpenLink),
    OpenRDA package etc.
-- be carefull defining RDBMS connection parameters, you'll probably need only
+- be careful defining RDBMS connection parameters, you'll probably need only
   "dbname" directive - all the rest can be defined in datasource. Every other
   directive is used to override value stored in datasource definition.
   Maybe you will want to use dbuser/dbpasswd to override credentials defined in datasource
diff --git a/servers/slapd/back-sql/entry-id.c b/servers/slapd/back-sql/entry-id.c
index 73086850f4..eab33bbc14 100644
--- a/servers/slapd/back-sql/entry-id.c
+++ b/servers/slapd/back-sql/entry-id.c
@@ -13,7 +13,8 @@
 
 #include <stdio.h>
 #include <sys/types.h>
-#include <string.h>
+#include "ac/string.h"
+#include "ldap_pvt.h"
 #include "slap.h"
 #include "back-sql.h"
 #include "sql-wrap.h"
@@ -21,208 +22,292 @@
 #include "entry-id.h"
 #include "util.h"
 
-backsql_entryID* backsql_free_entryID(backsql_entryID* id)
+backsql_entryID *
+backsql_free_entryID( backsql_entryID *id, int freeit )
 {
- backsql_entryID* next=id->next;
- if (id->dn!=NULL)
-  free(id->dn);
- free(id);
- return next;
+	backsql_entryID 	*next;
+
+	assert( id );
+
+	next = id->next;
+
+	if ( id->dn.bv_val != NULL ) {
+		free( id->dn.bv_val );
+	}
+
+	if ( freeit ) {
+		free( id );
+	}
+
+	return next;
 }
 
-backsql_entryID* backsql_dn2id(backsql_info *bi,backsql_entryID *id,SQLHDBC dbh,char *dn)
+/*
+ * FIXME: need to change API to pass backsql_entryID **id 
+ * and return an error code, to distinguish LDAP_OTHER from
+ * LDAP_NO_SUCH_OBJECT
+ */
+int
+backsql_dn2id(
+	backsql_info		*bi,
+	backsql_entryID		*id,
+	SQLHDBC			dbh,
+	struct berval		*dn )
 {
- SQLHSTMT sth; 
- BACKSQL_ROW_NTS row;
- /*SQLINTEGER nrows=0;*/
- RETCODE rc;
-
- /* TimesTen */
- char upperdn[BACKSQL_MAX_DN_LEN+1];
- char* toBind;
- int i, j, k;
-
- Debug(LDAP_DEBUG_TRACE,"==>backsql_dn2id(): dn='%s'\n",dn,0,0);
- /* begin TimesTen */
- Debug(LDAP_DEBUG_TRACE, "id_query '%s'\n", bi->id_query, 0, 0);
- rc = backsql_Prepare(dbh,&sth,bi->id_query,0);
- if (rc != SQL_SUCCESS) {
-   Debug(LDAP_DEBUG_TRACE, "backsql_dn2id(): error preparing SQL:\n", 0, 0, 0);
-   Debug(LDAP_DEBUG_TRACE, "%s\n", bi->id_query, 0, 0);
-   backsql_PrintErrors(SQL_NULL_HENV, dbh, sth, rc);
-   SQLFreeStmt(sth, SQL_DROP);
-   return NULL;
- }
-
- if (bi->has_ldapinfo_dn_ru) {
-   /* Prepare an upper cased, byte reversed version that can be
-      searched using indexes */
-
-   for ((i=0, j=strlen(dn)-1); *(dn+i); (i++, j--)) {
-     *(upperdn+i) = toupper(*(dn+j));
-   }   
-   *(upperdn+i) = '\0';
-   Debug(LDAP_DEBUG_TRACE,"==>backsql_dn2id(): upperdn='%s'\n",upperdn,0,0);
-   toBind = upperdn;
- }
- else {
-   if (bi->isTimesTen) {
-     for (i = 0; *(dn+i); i++) {
-       *(upperdn+i) = toupper(*(dn+i)); /* Copy while upper casing */
-     }
-     *(upperdn+i) = '\0';
-     Debug(LDAP_DEBUG_TRACE,"==>backsql_dn2id(): upperdn='%s'\n",upperdn,0,0);
-     toBind = upperdn;
-   }
-   else
-     toBind = dn;
- }
-
- if ((rc=backsql_BindParamStr(sth,1,toBind,
-                  BACKSQL_MAX_DN_LEN)) != SQL_SUCCESS)
- /* end TimesTen*/
- {
-   Debug(LDAP_DEBUG_TRACE,"backsql_dn2id(): error binding dn parameter:\n",0,0,0);
-   backsql_PrintErrors(SQL_NULL_HENV,dbh,sth,rc);
-   SQLFreeStmt(sth,SQL_DROP);
-   return NULL;
- }
- 
- if ((rc=SQLExecute(sth)) != SQL_SUCCESS)
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_dn2id(): error executing query:\n",0,0,0);
-   backsql_PrintErrors(SQL_NULL_HENV,dbh,sth,rc);
-   SQLFreeStmt(sth,SQL_DROP);
-   return NULL;
-  }
- 
- backsql_BindRowAsStrings(sth,&row);
- if ((rc=SQLFetch(sth)) == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
-  {
-   if (id==NULL)
-    {
-     id=(backsql_entryID*)ch_calloc(1,sizeof(backsql_entryID));
-    }
-   id->id=atoi(row.cols[0]);
-   id->keyval=atoi(row.cols[1]);
-   id->oc_id=atoi(row.cols[2]);
-   id->dn=ch_strdup(dn);
-   id->next=NULL;
-  }
- else
-  id=NULL;
- backsql_FreeRow(&row);
- 
- SQLFreeStmt(sth, SQL_DROP);
- if (id!=NULL)
-  Debug(LDAP_DEBUG_TRACE,"<==backsql_dn2id(): id=%d\n",(int)id->id,0,0);
- else
-  Debug(LDAP_DEBUG_TRACE,"<==backsql_dn2id(): no match\n",0,0,0);
- return id;
-}
+	SQLHSTMT		sth; 
+	BACKSQL_ROW_NTS		row;
+#if 0
+ 	SQLINTEGER		nrows = 0;
+#endif
+	RETCODE 		rc;
+	int			res;
+
+	/* TimesTen */
+	char			upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
+	char			*toBind;
+	int			i, j;
+
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): dn='%s'\n", 
+			dn->bv_val, 0, 0 );
+
+	assert( id );
+
+	if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
+		Debug( LDAP_DEBUG_TRACE, 
+			"backsql_dn2id(): DN \"%s\" (%ld bytes) "
+			"exceeds max DN length (%d):\n",
+			dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
+		return LDAP_OTHER;
+	}
+	
+	/* begin TimesTen */
+	Debug(LDAP_DEBUG_TRACE, "id_query '%s'\n", bi->id_query, 0, 0);
+	assert( bi->id_query );
+ 	rc = backsql_Prepare( dbh, &sth, bi->id_query, 0 );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, 
+			"backsql_dn2id(): error preparing SQL:\n%s", 
+			bi->id_query, 0, 0);
+		backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
+		SQLFreeStmt( sth, SQL_DROP );
+		return LDAP_OTHER;
+	}
+
+	if ( bi->has_ldapinfo_dn_ru ) {
+		/*
+		 * Prepare an upper cased, byte reversed version 
+		 * that can be searched using indexes
+		 */
+
+		for ( i = 0, j = dn->bv_len - 1; dn->bv_val[ i ]; i++, j--) {
+			upperdn[ i ] = dn->bv_val[ j ];
+		}
+		upperdn[ i ] = '\0';
+		ldap_pvt_str2upper( upperdn );
+
+		Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): upperdn='%s'\n",
+				upperdn, 0, 0 );
+		toBind = upperdn;
+	} else {
+		if ( bi->isTimesTen ) {
+			AC_MEMCPY( upperdn, dn->bv_val, dn->bv_len + 1 );
+			ldap_pvt_str2upper( upperdn );
+			Debug( LDAP_DEBUG_TRACE,
+				"==>backsql_dn2id(): upperdn='%s'\n",
+				upperdn, 0, 0 );
+			toBind = upperdn;
+
+		} else {
+			toBind = dn->bv_val;
+		}
+	}
+
+	rc = backsql_BindParamStr( sth, 1, toBind, BACKSQL_MAX_DN_LEN );
+	if ( rc != SQL_SUCCESS) {
+		/* end TimesTen */ 
+		Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
+			"error binding dn=\"%s\" parameter:\n", toBind, 0, 0 );
+		backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
+		SQLFreeStmt( sth, SQL_DROP );
+		return LDAP_OTHER;
+	}
 
+	rc = SQLExecute( sth );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
+			"error executing query (\"%s\", \"%s\"):\n", 
+			bi->id_query, toBind, 0 );
+		backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
+		SQLFreeStmt( sth, SQL_DROP );
+		return LDAP_OTHER;
+	}
 
-int backsql_get_attr_vals(backsql_at_map_rec *at,backsql_srch_info *bsi)
+	backsql_BindRowAsStrings( sth, &row );
+	rc = SQLFetch( sth );
+	if ( BACKSQL_SUCCESS( rc ) ) {
+		id->id = atoi( row.cols[ 0 ] );
+		id->keyval = atoi( row.cols[ 1 ] );
+		id->oc_id = atoi( row.cols[ 2 ] );
+		ber_dupbv( &id->dn, dn );
+		id->next = NULL;
+
+		res = LDAP_SUCCESS;
+
+	} else {
+		res = LDAP_NO_SUCH_OBJECT;
+	}
+	backsql_FreeRow( &row );
+
+	SQLFreeStmt( sth, SQL_DROP );
+	if ( res == LDAP_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(): id=%ld\n",
+				id->id, 0, 0 );
+	} else {
+		Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(): no match\n",
+				0, 0, 0 );
+	}
+	return res;
+}
+
+int
+backsql_get_attr_vals( backsql_at_map_rec *at, backsql_srch_info *bsi )
 {
- RETCODE rc;
- SQLHSTMT sth;
- BACKSQL_ROW_NTS row;
- int i;
+	RETCODE		rc;
+	SQLHSTMT	sth;
+	BACKSQL_ROW_NTS	row;
+	int		i;
+
+	assert( at );
+	assert( bsi );
  
- Debug(LDAP_DEBUG_TRACE,"==>backsql_get_attr_vals(): oc='%s' attr='%s' keyval=%d\n",
-			bsi->oc->name,at->name,bsi->c_eid->keyval);
-
- if ((rc=backsql_Prepare(bsi->dbh,&sth,at->query,0)) != SQL_SUCCESS)
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_get_attr_values(): error preparing query: %s\n",at->query,0,0);
-   backsql_PrintErrors(bsi->bi->db_env,bsi->dbh,sth,rc);
-   return 1;
-  }
-
- if (backsql_BindParamID(sth,1,&(bsi->c_eid->keyval)) != SQL_SUCCESS)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_get_attr_values(): error binding key value parameter\n",0,0,0);
-  return 1;
- }
-
- if ((rc=SQLExecute(sth)) != SQL_SUCCESS && rc!= SQL_SUCCESS_WITH_INFO)
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_get_attr_values(): error executing attribute query '%s'\n",at->query,0,0);
-   backsql_PrintErrors(bsi->bi->db_env,bsi->dbh,sth,rc);
-   SQLFreeStmt(sth,SQL_DROP);
-   return 1;
-  }
-
- backsql_BindRowAsStrings(sth,&row);
- while ((rc=SQLFetch(sth)) == SQL_SUCCESS || rc==SQL_SUCCESS_WITH_INFO)
-  {
-   for (i=0;i<row.ncols;i++)
-    {
-     if (row.is_null[i]>0)
-      {
-       backsql_entry_addattr(bsi->e,row.col_names[i],row.cols[i],/*row.col_prec[i]*/
-					strlen(row.cols[i]));
-/*       Debug(LDAP_DEBUG_TRACE,"prec=%d\n",(int)row.col_prec[i],0,0);*/
-      }
-    /* else
-      Debug(LDAP_DEBUG_TRACE,"NULL value in this row for attribute '%s'\n",row.col_names[i],0,0);
-*/
-    }
-  }
- backsql_FreeRow(&row);
- SQLFreeStmt(sth,SQL_DROP);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_get_attr_vals()\n",0,0,0);
- return 1;
-}
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
+		"oc='%s' attr='%s' keyval=%ld\n",
+		bsi->oc->name, at->name, bsi->c_eid->keyval );
+
+	rc = backsql_Prepare( bsi->dbh, &sth, at->query, 0 );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
+			"error preparing query: %s\n", at->query, 0, 0 );
+		backsql_PrintErrors( bsi->bi->db_env, bsi->dbh, sth, rc );
+		return 1;
+	}
+
+	rc = backsql_BindParamID( sth, 1, &bsi->c_eid->keyval );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
+			"error binding key value parameter\n", 0, 0, 0 );
+		return 1;
+	}
+
+	rc = SQLExecute( sth );
+	if ( ! BACKSQL_SUCCESS( rc ) ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
+			"error executing attribute query '%s'\n",
+			at->query, 0, 0 );
+		backsql_PrintErrors( bsi->bi->db_env, bsi->dbh, sth, rc );
+		SQLFreeStmt( sth, SQL_DROP );
+		return 1;
+	}
 
+	backsql_BindRowAsStrings( sth, &row );
 
-Entry* backsql_id2entry(backsql_srch_info *bsi,Entry* e,backsql_entryID* eid)
+	rc = SQLFetch( sth );
+	for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
+		for ( i = 0; i < row.ncols; i++ ) {
+			if ( row.is_null[ i ] > 0 ) {
+       				backsql_entry_addattr( bsi->e, 
+						row.col_names[ i ],
+						row.cols[ i ],
+#if 0
+						row.col_prec[ i ]
+#else
+						/*
+						 * FIXME: what if a binary 
+						 * is fetched?
+						 */
+						strlen( row.cols[ i ] )
+#endif
+						);
+#if 0
+				Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
+					(int)row.col_prec[ i ], 0, 0 );
+			} else {
+      				Debug( LDAP_DEBUG_TRACE, "NULL value "
+					"in this row for attribute '%s'\n",
+					row.col_names[ i ], 0, 0 );
+#endif
+			}
+		}
+	}
+
+	backsql_FreeRow( &row );
+	SQLFreeStmt( sth, SQL_DROP );
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 );
+
+	return 1;
+}
+
+Entry *
+backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
 {
- char **c_at_name;
- backsql_at_map_rec *at;
+	char			**c_at_name;
+	backsql_at_map_rec	*at;
+	int			rc;
 
- Debug(LDAP_DEBUG_TRACE,"==>backsql_id2entry()\n",0,0,0);
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );
 
- bsi->oc=backsql_oc_with_id(bsi->bi,eid->oc_id);
- bsi->e=e;
- bsi->c_eid=eid;
- e->e_attrs=NULL;
- e->e_private=NULL;
- 
-/* if (bsi->base_dn != NULL)???*/
+	rc = dnPrettyNormal( NULL, &eid->dn, &e->e_name, &e->e_nname );
+	if ( rc != LDAP_SUCCESS ) {
+		return NULL;
+	}
 
- e->e_id=eid->id;
- e->e_dn=ch_strdup(bsi->c_eid->dn);
- e->e_ndn=dn_normalize(ch_strdup(bsi->c_eid->dn));
+	bsi->oc = backsql_oc_with_id( bsi->bi, eid->oc_id );
+	bsi->e = e;
+	bsi->c_eid = eid;
+	e->e_attrs = NULL;
+	e->e_private = NULL;
  
- if (bsi->attrs!=NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_id2entry(): custom attribute list\n",0,0,0);
-  for(c_at_name=bsi->attrs;*c_at_name!=NULL;c_at_name++)
-  {
-   if (!strcasecmp(*c_at_name,"objectclass") || !strcasecmp(*c_at_name,"0.10"))
-   {
-	/*backsql_entry_addattr(bsi->e,"objectclass",bsi->oc->name,strlen(bsi->oc->name));*/
-    continue;
-   }
-   at=backsql_at_with_name(bsi->oc,*c_at_name);
-   if (at!=NULL)
-    backsql_get_attr_vals(at,bsi);
-   else
-	Debug(LDAP_DEBUG_TRACE,"backsql_id2entry(): attribute '%s' is not defined for objectlass '%s'\n",
-			*c_at_name,bsi->oc->name,0);
-
-  }
- }
- else
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_id2entry(): retrieving all attributes\n",0,0,0);
-  avl_apply(bsi->oc->attrs,(AVL_APPLY)backsql_get_attr_vals,bsi,0,AVL_INORDER);
- }
- backsql_entry_addattr(bsi->e,"objectclass",bsi->oc->name,strlen(bsi->oc->name));
-
- Debug(LDAP_DEBUG_TRACE,"<==backsql_id2entry()\n",0,0,0);
- return e;
+	/* if ( bsi->base_dn != NULL)??? */
+	
+	e->e_id = eid->id;
+ 
+	if ( bsi->attrs != NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
+			"custom attribute list\n", 0, 0, 0 );
+		for ( c_at_name = bsi->attrs; *c_at_name != NULL; c_at_name++ ) {
+			if ( !strcasecmp( *c_at_name, "objectclass" ) 
+					|| !strcasecmp( *c_at_name, "0.10" ) ) {
+#if 0
+				backsql_entry_addattr( bsi->e, "objectclass",
+						bsi->oc->name,
+						strlen( bsi->oc->name ) );
+#endif
+				continue;
+			}
+			at = backsql_at_with_name( bsi->oc, *c_at_name );
+			if ( at != NULL ) {
+    				backsql_get_attr_vals( at, bsi );
+			} else {
+				Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
+					"attribute '%s' is not defined "
+					"for objectlass '%s'\n",
+					*c_at_name, bsi->oc->name, 0 );
+			}
+		}
+	} else {
+		Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
+			"retrieving all attributes\n", 0, 0, 0 );
+		avl_apply( bsi->oc->attrs, (AVL_APPLY)backsql_get_attr_vals,
+				bsi, 0, AVL_INORDER );
+	}
+
+	backsql_entry_addattr( bsi->e, "objectclass", bsi->oc->name,
+			strlen( bsi->oc->name ) );
+
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
+
+	return e;
 }
 
 #endif /* SLAPD_SQL */
+
diff --git a/servers/slapd/back-sql/entry-id.h b/servers/slapd/back-sql/entry-id.h
index 5792d85eea..bc52fa8669 100644
--- a/servers/slapd/back-sql/entry-id.h
+++ b/servers/slapd/back-sql/entry-id.h
@@ -11,17 +11,18 @@
  */
 
 
-typedef struct __backsql_entryID
-{
- unsigned long id;
- unsigned long keyval;
- unsigned long oc_id;
- char *dn;
- struct __backsql_entryID *next;
-}backsql_entryID;
+typedef struct backsql_entryID {
+	unsigned long		id;
+	unsigned long		keyval;
+	unsigned long		oc_id;
+	struct berval		dn;
+	struct backsql_entryID	*next;
+} backsql_entryID;
 
-backsql_entryID* backsql_dn2id(backsql_info *bi,backsql_entryID* id,SQLHDBC dbh,char *dn);
-backsql_entryID* backsql_free_entryID(backsql_entryID* id);/*returns next*/
+int backsql_dn2id( backsql_info *bi, backsql_entryID *id,
+		SQLHDBC dbh, struct berval *dn );
+/* returns next */
+backsql_entryID *backsql_free_entryID( backsql_entryID *id, int freeit );
 
-#endif
+#endif /* __BACKSQL_ENTRYID_H__ */
 
diff --git a/servers/slapd/back-sql/init.c b/servers/slapd/back-sql/init.c
index 92f7b5b90b..ab38e37846 100644
--- a/servers/slapd/back-sql/init.c
+++ b/servers/slapd/back-sql/init.c
@@ -21,24 +21,29 @@
 
 #ifdef SLAPD_SQL_DYNAMIC
 
-int backsql_LTX_init_module(int argc, char *argv[]) {
-    BackendInfo bi;
+int
+backsql_LTX_init_module(
+	int 		argc, 
+	char 		*argv[] )
+{
+	BackendInfo bi;
 
-    memset( &bi, '\0', sizeof(bi) );
-    bi.bi_type = "sql";
-    bi.bi_init = backbacksql_initialize;
+	memset( &bi, '\0', sizeof( bi ) );
+	bi.bi_type = "sql";
+	bi.bi_init = backbacksql_initialize;
 
-    backend_add(&bi);
-    return 0;
+	backend_add( &bi );
+	return 0;
 }
 
 #endif /* SLAPD_SHELL_DYNAMIC */
 
-int sql_back_initialize(
-    BackendInfo	*bi
-)
+int
+sql_back_initialize(
+	BackendInfo	*bi )
 { 
- Debug(LDAP_DEBUG_TRACE,"==>backsql_initialize()\n",0,0,0);
+	Debug( LDAP_DEBUG_TRACE,"==>backsql_initialize()\n", 0, 0, 0 );
+	
 	bi->bi_open = 0;
 	bi->bi_config = 0;
 	bi->bi_close = 0;
@@ -72,165 +77,234 @@ int sql_back_initialize(
 	bi->bi_connection_init = 0;
 	bi->bi_connection_destroy = backsql_connection_destroy;
 	
-	Debug(LDAP_DEBUG_TRACE,"<==backsql_initialize()\n",0,0,0);
+	Debug( LDAP_DEBUG_TRACE,"<==backsql_initialize()\n", 0, 0, 0 );
 	return 0;
 }
 
 
-int backsql_destroy ( BackendInfo *bi )
+int
+backsql_destroy( 
+	BackendInfo 	*bi )
 {
- Debug(LDAP_DEBUG_TRACE,"==>backsql_destroy()\n",0,0,0);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_destroy()\n",0,0,0);
- return 0;
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_destroy()\n", 0, 0, 0 );
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_destroy()\n", 0, 0, 0 );
+	return 0;
 }
 
-int backsql_db_init(BackendDB *bd)
+int
+backsql_db_init(
+	BackendDB 	*bd )
 {
- backsql_info *si;
- 
- Debug(LDAP_DEBUG_TRACE,"==>backsql_db_init()\n",0,0,0);
- si = (backsql_info *) ch_calloc( 1, sizeof(backsql_info) );
- ldap_pvt_thread_mutex_init(&si->dbconn_mutex);
- ldap_pvt_thread_mutex_init(&si->schema_mutex);
- backsql_init_db_env(si);
+	backsql_info *si;
  
- bd->be_private=si;
- Debug(LDAP_DEBUG_TRACE,"<==backsql_db_init()\n",0,0,0);
- return 0;
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_db_init()\n", 0, 0, 0 );
+	si = (backsql_info *)ch_calloc( 1, sizeof( backsql_info ) );
+	ldap_pvt_thread_mutex_init( &si->dbconn_mutex );
+	ldap_pvt_thread_mutex_init( &si->schema_mutex );
+	backsql_init_db_env( si );
+	si->has_ldapinfo_dn_ru = -1;
+
+	bd->be_private = si;
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_db_init()\n", 0, 0, 0 );
+	return 0;
 }
 
-int backsql_db_destroy(BackendDB *bd)
+int
+backsql_db_destroy(
+	BackendDB 	*bd )
 {
- backsql_info *si=(backsql_info*)bd->be_private;
+	backsql_info *si = (backsql_info*)bd->be_private;
  
- Debug(LDAP_DEBUG_TRACE,"==>backsql_db_destroy()\n",0,0,0);
- ldap_pvt_thread_mutex_lock(&si->dbconn_mutex);
- backsql_free_db_env(si);
- ldap_pvt_thread_mutex_unlock(&si->dbconn_mutex);
- ldap_pvt_thread_mutex_lock(&si->schema_mutex);
- backsql_destroy_schema_map(si);
- ldap_pvt_thread_mutex_unlock(&si->schema_mutex);
- ldap_pvt_thread_mutex_destroy(&si->schema_mutex);
- ldap_pvt_thread_mutex_destroy(&si->dbconn_mutex);
- free(si->dbname);
- free(si->dbuser);
- if (si->dbpasswd)
-  free(si->dbpasswd);
- if (si->dbhost)
-  free(si->dbhost);
- if (si->upper_func)
-  free(si->upper_func);
- free(si->subtree_cond);
- free(si->oc_query);
- free(si->at_query);
- free(si->insentry_query);
- free(si->delentry_query);
- free(si);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_db_destroy()\n",0,0,0);
- return 0;
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_db_destroy()\n", 0, 0, 0 );
+	ldap_pvt_thread_mutex_lock( &si->dbconn_mutex );
+	backsql_free_db_env( si );
+	ldap_pvt_thread_mutex_unlock( &si->dbconn_mutex );
+	ldap_pvt_thread_mutex_lock( &si->schema_mutex );
+	backsql_destroy_schema_map( si );
+	ldap_pvt_thread_mutex_unlock( &si->schema_mutex );
+	ldap_pvt_thread_mutex_destroy( &si->schema_mutex );
+	ldap_pvt_thread_mutex_destroy( &si->dbconn_mutex );
+	free( si->dbname );
+	free( si->dbuser );
+	if ( si->dbpasswd ) {
+		free( si->dbpasswd );
+	}
+	if ( si->dbhost ) {
+		free( si->dbhost );
+	}
+	if ( si->upper_func ) {
+		free( si->upper_func );
+	}
+	
+	free( si->subtree_cond );
+	free( si->oc_query );
+	free( si->at_query );
+	free( si->insentry_query );
+	free( si->delentry_query );
+	free( si );
+	
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_db_destroy()\n", 0, 0, 0 );
+	return 0;
 }
 
-int backsql_db_open (BackendDB *bd)
+int
+backsql_db_open(
+	BackendDB 	*bd )
 {
- backsql_info *si=(backsql_info*)bd->be_private;
- Connection tmp;
- SQLHDBC dbh;
- int idq_len;
-
- Debug(LDAP_DEBUG_TRACE,"==>backsql_db_open(): testing RDBMS connection\n",0,0,0);
- if (si->dbname==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): datasource name not specified (use dbname directive in slapd.conf)\n",0,0,0);
-  return 1;
- }
- if (si->dbuser==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): user name not specified (use dbuser directive in slapd.conf)\n",0,0,0);
-  return 1;
- }
- if (si->subtree_cond==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): subtree search SQL condition not specified (use subtree_cond directive in slapd.conf)\n",0,0,0);
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): setting '%s' as default\n",backsql_def_subtree_cond,0,0);
-  si->subtree_cond=ch_strdup(backsql_def_subtree_cond);
- }
- if (si->oc_query==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): objectclass mapping SQL statement not specified (use oc_query directive in slapd.conf)\n",0,0,0);
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): setting '%s' by default\n",backsql_def_oc_query,0,0);
-  si->oc_query=ch_strdup(backsql_def_oc_query);
- }
- if (si->at_query==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): attribute mapping SQL statement not specified (use at_query directive in slapd.conf)\n",0,0,0);
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): setting '%s' by default\n",backsql_def_at_query,0,0);
-  si->at_query=ch_strdup(backsql_def_at_query);
- }
- if (si->insentry_query==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): entry insertion SQL statement not specified (use insentry_query directive in slapd.conf)\n",0,0,0);
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): setting '%s' by default\n",backsql_def_insentry_query,0,0);
-  si->insentry_query=ch_strdup(backsql_def_insentry_query);
- }
- if (si->delentry_query==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): entry deletion SQL statement not specified (use delentry_query directive in slapd.conf)\n",0,0,0);
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): setting '%s' by default\n",backsql_def_delentry_query,0,0);
-  si->delentry_query=ch_strdup(backsql_def_delentry_query);
- }
- tmp.c_connid=-1;
- dbh=backsql_get_db_conn(bd,&tmp);
- if (!dbh)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): connection failed, exiting\n",0,0,0
-);
-  return 1;
- }
-
- si->id_query=NULL;
- idq_len=0;
- if (si->upper_func==NULL)
- {
-  si->id_query=backsql_strcat(si->id_query,&idq_len,backsql_id_query,"dn=?",NULL);
- }
- else
- {
-    if (si->has_ldapinfo_dn_ru) {
-      si->id_query=backsql_strcat(si->id_query,&idq_len,backsql_id_query,"dn_ru=?",NULL);
-    }
-    else {
-      if (si->isTimesTen) {
-    si->id_query=backsql_strcat(si->id_query,&idq_len,backsql_id_query,si->upper_func,"(dn)=?",NULL);
-      }
-      else {
-   		si->id_query=backsql_strcat(si->id_query,&idq_len,backsql_id_query,si->upper_func,"(dn)=",si->upper_func,"(?)",NULL);
-   	  }
+	backsql_info 	*si = (backsql_info*)bd->be_private;
+	Connection 	tmp;
+	SQLHDBC 	dbh;
+	int 		idq_len;
+	struct berval	bv;
+
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): "
+		"testing RDBMS connection\n", 0, 0, 0 );
+	if ( si->dbname == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"datasource name not specified "
+			"(use dbname directive in slapd.conf)\n", 0, 0, 0 );
+		return 1;
+	}
+	
+	if ( si->dbuser == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"user name not specified "
+			"(use dbuser directive in slapd.conf)\n", 0, 0, 0 );
+		return 1;
+	}
+	
+	if ( si->subtree_cond == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"subtree search SQL condition not specified "
+			"(use subtree_cond directive in slapd.conf)\n", 
+			0, 0, 0);
+		if ( si->upper_func ) {
+			struct berval	bv = { 0, NULL };
+			int		len = 0;
+
+			backsql_strcat( &bv, &len, si->upper_func,
+					backsql_def_upper_subtree_cond, NULL );
+			si->subtree_cond = bv.bv_val;
+		} else {
+			si->subtree_cond = ch_strdup( backsql_def_subtree_cond );
+		}
+			
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"setting '%s' as default\n",
+			si->subtree_cond, 0, 0 );
 	}
- }
+
+	if ( si->oc_query == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"objectclass mapping SQL statement not specified "
+			"(use oc_query directive in slapd.conf)\n", 0, 0, 0 );
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"setting '%s' by default\n", 
+			backsql_def_oc_query, 0, 0 );
+		si->oc_query = ch_strdup( backsql_def_oc_query );
+	}
+	
+	if ( si->at_query == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"attribute mapping SQL statement not specified "
+			"(use at_query directive in slapd.conf)\n",
+			0, 0, 0 );
+		Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"setting '%s' by default\n",
+			backsql_def_at_query, 0, 0 );
+		si->at_query = ch_strdup( backsql_def_at_query );
+	}
+	
+	if ( si->insentry_query == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"entry insertion SQL statement not specified "
+			"(use insentry_query directive in slapd.conf)\n",
+			0, 0, 0 );
+		Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"setting '%s' by default\n",
+			backsql_def_insentry_query, 0, 0 );
+		si->insentry_query = ch_strdup( backsql_def_insentry_query );
+	}
+	
+	if ( si->delentry_query == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"entry deletion SQL statement not specified "
+			"(use delentry_query directive in slapd.conf)\n",
+			0, 0, 0 );
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"setting '%s' by default\n",
+			backsql_def_delentry_query, 0, 0 );
+		si->delentry_query = ch_strdup( backsql_def_delentry_query );
+	}
+	
+	tmp.c_connid =- 1;
+	dbh = backsql_get_db_conn( bd, &tmp );
+	if ( !dbh ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"connection failed, exiting\n", 0, 0, 0 );
+		return 1;
+	}
+
+	si->id_query = NULL;
+	idq_len = 0;
+
+	bv.bv_val = NULL;
+	bv.bv_len = 0;
+	if ( si->upper_func == NULL ) {
+		backsql_strcat( &bv, &idq_len, backsql_id_query, 
+				"dn=?", NULL );
+	} else {
+		if ( si->has_ldapinfo_dn_ru ) {
+			backsql_strcat( &bv, &idq_len, backsql_id_query,
+					"dn_ru=?", NULL );
+		} else {
+			if ( si->isTimesTen ) {
+				backsql_strcat( &bv, &idq_len, 
+						backsql_id_query,
+						si->upper_func, "(dn)=?",
+						NULL );
+			} else {
+				backsql_strcat( &bv, &idq_len, 
+						backsql_id_query,
+						si->upper_func, "(dn)=",
+						si->upper_func, "(?)", NULL );
+			}
+		}
+	}
+	si->id_query = bv.bv_val;
  
-backsql_free_db_conn(bd,&tmp);
- if (!si->schema_loaded)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_db_open(): test failed, schema map not loaded - exiting\n",0,0,0);
-  return 1;
- }
- Debug(LDAP_DEBUG_TRACE,"<==backsql_db_open(): test succeeded, schema map loaded\n",0,0,0);
- return 0;
+	backsql_free_db_conn( bd, &tmp );
+	if ( !si->schema_loaded ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+			"test failed, schema map not loaded - exiting\n",
+			0, 0, 0 );
+		return 1;
+	}
+	
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_db_open(): "
+		"test succeeded, schema map loaded\n", 0, 0, 0 );
+	return 0;
 }
 
-int backsql_db_close(BackendDB *bd)
+int
+backsql_db_close(
+	BackendDB	*bd )
 {
- Debug(LDAP_DEBUG_TRACE,"==>backsql_db_close()\n",0,0,0);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_db_close()\n",0,0,0);
- return 0;
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_db_close()\n", 0, 0, 0 );
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_db_close()\n", 0, 0, 0 );
+	return 0;
 }
 
-int backsql_connection_destroy(BackendDB *be,Connection *conn)
+int
+backsql_connection_destroy(
+	BackendDB 	*be,
+	Connection 	*conn )
 {
- Debug(LDAP_DEBUG_TRACE,"==>backsql_connection_destroy()\n",0,0,0);
- backsql_free_db_conn(be,conn);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_connection_destroy()\n",0,0,0);
- return 0;
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_connection_destroy()\n", 0, 0, 0 );
+	backsql_free_db_conn( be, conn );
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_connection_destroy()\n", 0, 0, 0 );
+	return 0;
 }
 
 #endif /* SLAPD_SQL */
+
diff --git a/servers/slapd/back-sql/modify.c b/servers/slapd/back-sql/modify.c
index 9514da0155..f1bc54869b 100644
--- a/servers/slapd/back-sql/modify.c
+++ b/servers/slapd/back-sql/modify.c
@@ -21,543 +21,883 @@
 #include "entry-id.h"
 #include "util.h"
 
-int backsql_modify(BackendDB *be,Connection *conn,Operation *op,
-	const char *dn,const char *ndn,Modifications *modlist)
+/*
+ * PostgreSQL doesn't work without :(
+ */
+#define	BACKSQL_REALLOC_STMT
+
+int
+backsql_modify(
+	BackendDB 	*be,
+	Connection 	*conn,
+	Operation 	*op,
+	struct berval	*dn,
+	struct berval	*ndn,
+	Modifications 	*modlist )
 {
- backsql_info *bi=(backsql_info*)be->be_private;
- SQLHDBC dbh;
- SQLHSTMT sth;
- RETCODE rc;
- backsql_oc_map_rec *oc=NULL;
- backsql_entryID e_id,*res;
- Modification *c_mod;
- Modifications *ml;
- backsql_at_map_rec *at=NULL;
- struct berval *at_val;
- int i;
- int pno,po;/*first parameter no, parameter order*/
- int prc; /*procedure return code*/
-
- Debug(LDAP_DEBUG_TRACE,"==>backsql_modify(): changing entry '%s'\n",ndn,0,0);
- dbh=backsql_get_db_conn(be,conn);
- if (!dbh)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modify(): could not get connection handle - exiting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
- res=backsql_dn2id(bi,&e_id,dbh,(char*)ndn);
- if (res==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modify(): could not lookup entry id\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_NO_SUCH_OBJECT,"",NULL,NULL,NULL);
-  return 1;
- }
-
- oc=backsql_oc_with_id(bi,e_id.oc_id);
- if (oc==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modify(): cannot determine objectclass of entry -- aborting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
-
- SQLAllocStmt(dbh, &sth);
-
- Debug(LDAP_DEBUG_TRACE,"backsql_modify(): traversing modifications list\n",0,0,0);
- for(ml=modlist;ml!=NULL;ml=ml->sml_next)
- {
-  c_mod=&ml->sml_mod;
-  Debug(LDAP_DEBUG_TRACE,"backsql_modify(): attribute '%s'\n",c_mod->sm_desc->ad_cname.bv_val,0,0);
-  at=backsql_at_with_name(oc,c_mod->sm_desc->ad_cname.bv_val);
-  if (at==NULL)
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_modify(): attribute provided is not registered in this objectclass ('%s')\n",c_mod->sm_desc->ad_cname.bv_val,0,0);
-   continue;
-  }
+	backsql_info		*bi = (backsql_info*)be->be_private;
+	SQLHDBC 		dbh;
+	SQLHSTMT		sth;
+	RETCODE			rc;
+	backsql_oc_map_rec	*oc = NULL;
+	backsql_entryID		e_id;
+	int			res;
+	Modification		*c_mod;
+	Modifications		*ml;
+	backsql_at_map_rec	*at = NULL;
+	struct berval		*at_val;
+	int			i;
+	/* first parameter no, parameter order */
+	SQLUSMALLINT		pno, po;
+	/* procedure return code */
+	int			prc;
+
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_modify(): changing entry '%s'\n",
+		ndn->bv_val, 0, 0 );
+	dbh = backsql_get_db_conn( be, conn );
+	if ( !dbh ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+			"could not get connection handle - exiting\n", 
+			0, 0, 0 );
+		/*
+		 * FIXME: we don't want to send back 
+		 * excessively detailed messages
+		 */
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+
+	res = backsql_dn2id( bi, &e_id, dbh, ndn );
+	if ( res != LDAP_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+			"could not lookup entry id\n", 0, 0, 0 );
+		send_ldap_result( conn, op, res , "", NULL, NULL, NULL );
+		return 1;
+	}
+
+	Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+		"modifying entry '%s' (id=%ld)\n", 
+		e_id.dn.bv_val, e_id.id, 0 );
+
+	oc = backsql_oc_with_id( bi, e_id.oc_id );
+	if ( oc == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+			"cannot determine objectclass of entry -- aborting\n",
+			0, 0, 0 );
+		/*
+		 * FIXME: we don't want to send back 
+		 * excessively detailed messages
+		 */
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+
+	SQLAllocStmt( dbh, &sth );
+	Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+		"traversing modifications list\n", 0, 0, 0 );
+	for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
+		char *attrname;
+
+		c_mod = &ml->sml_mod;
+
+		attrname = c_mod->sm_desc->ad_cname.bv_val;
+		Debug( LDAP_DEBUG_TRACE, "backsql_modify(): attribute '%s'\n",
+				attrname, 0, 0 );
+  		at = backsql_at_with_name( oc, attrname );
+		if ( at == NULL ) {
+			Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+				"attribute provided is not registered "
+				"in objectclass '%s'\n",
+				attrname, 0, 0 );
+			continue;
+		}
   
-  switch(c_mod->sm_op)
-  {
-   case LDAP_MOD_REPLACE:
-			{
-			 SQLHSTMT asth;
-			 BACKSQL_ROW_NTS row;
+		switch( c_mod->sm_op ) {
+		case LDAP_MOD_REPLACE: {
+			SQLHSTMT asth;
+			BACKSQL_ROW_NTS row;
 			 
-			 Debug(LDAP_DEBUG_TRACE,"backsql_modify(): replacing values for attribute '%s'\n",at->name,0,0);
-             if (at->add_proc==NULL)
-			 {
-			  Debug(LDAP_DEBUG_TRACE,"backsql_modify(): add procedure is not defined for this attribute ('%s') - unable to perform replacements\n",at->name,0,0);
-			  break;
-			 }
+			Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+				"replacing values for attribute '%s'\n",
+				at->name, 0, 0 );
+
+			if ( at->add_proc == NULL ) {
+				Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+					"add procedure is not defined "
+					"for attribute '%s' "
+					"- unable to perform replacements\n",
+					at->name, 0, 0 );
+				break;
+			}
+
+			if ( at->delete_proc == NULL ) {
+				Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+					"delete procedure is not defined "
+					"for attribute '%s' "
+					"- adding only\n",
+					at->name, 0, 0 );
+				goto add_only;
+			}
+			
 del_all:
+			rc = backsql_Prepare( dbh, &asth, at->query, 0 );
+			if ( rc != SQL_SUCCESS ) {
+				Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+					"error preparing query\n", 0, 0, 0 );
+				backsql_PrintErrors( bi->db_env, dbh, 
+						asth, rc );
+				break;
+			}
+
+			rc = backsql_BindParamID( asth, 1, &e_id.keyval );
+			if ( rc != SQL_SUCCESS ) {
+				Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+					"error binding key value parameter\n",
+					0, 0, 0 );
+				backsql_PrintErrors( bi->db_env, dbh, 
+						asth, rc );
+				SQLFreeStmt( asth, SQL_DROP );
+				break;
+			}
+			
+			rc = SQLExecute( asth );
+			if ( !BACKSQL_SUCCESS( rc ) ) {
+				Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+					"error executing attribute query\n",
+					0, 0, 0 );
+				backsql_PrintErrors( bi->db_env, dbh, 
+						asth, rc );
+				SQLFreeStmt( asth, SQL_DROP );
+				break;
+			}
+
+			backsql_BindRowAsStrings( asth, &row );
+			rc = SQLFetch( asth );
+			for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( asth ) ) {
+				for ( i = 0; i < row.ncols; i++ ) {
+			   		if ( at->expect_return & BACKSQL_DEL ) {
+						pno = 1;
+						SQLBindParameter(sth, 1,
+							SQL_PARAM_OUTPUT,
+							SQL_C_ULONG,
+							SQL_INTEGER,
+							0, 0, &prc, 0, 0 );
+					} else {
+						pno = 0;
+					}
+					po = ( at->param_order & BACKSQL_DEL ) > 0;
+					SQLBindParameter( sth, pno + 1 + po,
+						SQL_PARAM_INPUT,
+						SQL_C_ULONG, SQL_INTEGER,
+						0, 0, &e_id.keyval, 0, 0 );
+
+					/*
+					 * check for syntax needed here 
+					 * maybe need binary bind?
+					 */
+					SQLBindParameter(sth, pno + 2 - po,
+						SQL_PARAM_INPUT,
+						SQL_C_CHAR, SQL_CHAR,
+						0, 0, row.cols[ i ],
+						strlen( row.cols[ i ] ), 0 );
 			 
-			 if ((rc=backsql_Prepare(dbh,&asth,at->query,0)) != SQL_SUCCESS)
-			 {
-			  Debug(LDAP_DEBUG_TRACE,"backsql_modify(): error preparing query\n",0,0,0);
-			  backsql_PrintErrors(bi->db_env,dbh,asth,rc);
-			  break;
-			 }
-
-			 if (backsql_BindParamID(asth,1,&e_id.keyval) != SQL_SUCCESS)
-			 {
-			  Debug(LDAP_DEBUG_TRACE,"backsql_modify(): error binding key value parameter\n",0,0,0);
-			  backsql_PrintErrors(bi->db_env,dbh,asth,rc);
-			  SQLFreeStmt(asth,SQL_DROP);
-			  break;
-			 }
-
-			 if ((rc=SQLExecute(asth)) != SQL_SUCCESS && rc!= SQL_SUCCESS_WITH_INFO)
-			 {
-			  Debug(LDAP_DEBUG_TRACE,"backsql_modify(): error executing attribute query\n",0,0,0);
-			  backsql_PrintErrors(bi->db_env,dbh,asth,rc);
-			  SQLFreeStmt(asth,SQL_DROP);
-			  break;
-			 }
-
-			 backsql_BindRowAsStrings(asth,&row);
-			 while ((rc=SQLFetch(asth)) == SQL_SUCCESS || rc==SQL_SUCCESS_WITH_INFO)
-			 {
-			  for (i=0;i<row.ncols;i++)
-			  {
-			   if (at->expect_return & BACKSQL_DEL)
-			   {
-			    pno=1;
-			    SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&prc,0,0);
-			   }
-			   else
-			    pno=0;
-			   po=(at->param_order & BACKSQL_DEL)>0;
-			   SQLBindParameter(sth,(SQLUSMALLINT)(pno+1+po),SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&e_id.keyval,0,0);
-			   /*check for syntax needed here - maybe need binary bind?*/
-			   SQLBindParameter(sth,(SQLUSMALLINT)(pno+2-po),SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,0,0,row.cols[i],strlen(row.cols[i]),0);
-			 
-			   Debug(LDAP_DEBUG_TRACE,"backsql_modify(): executing '%s'\n",at->delete_proc,0,0);
-			   rc=SQLExecDirect(sth,at->delete_proc,SQL_NTS);
-			   if (rc!=SQL_SUCCESS)
-				{
-			     Debug(LDAP_DEBUG_TRACE,"backsql_modify(): delete_proc execution failed\n",0,0,0);
-			     backsql_PrintErrors(bi->db_env,dbh,sth,rc);
+					Debug( LDAP_DEBUG_TRACE, 
+						"backsql_modify(): "
+						"executing '%s'\n",
+						at->delete_proc, 0, 0 );
+					rc = SQLExecDirect( sth,
+						at->delete_proc, SQL_NTS );
+					if ( rc != SQL_SUCCESS ) {
+						Debug( LDAP_DEBUG_TRACE,
+							"backsql_modify(): "
+							"delete_proc "
+							"execution failed\n",
+							0, 0, 0 );
+						backsql_PrintErrors( bi->db_env,
+								dbh, sth, rc );
+					}
 				}
-			  }
-			 }
-			 backsql_FreeRow(&row);
-             SQLFreeStmt(asth,SQL_DROP);
 			}
-			/*PASSTHROUGH - to add new attributes -- do NOT add break*/
-  case LDAP_MOD_ADD:
-			if (at->add_proc==NULL)
-			{
-			 Debug(LDAP_DEBUG_TRACE,"backsql_modify(): add procedure is not defined for this attribute ('%s')\n",at->name,0,0);
-			 break;
+			backsql_FreeRow( &row );
+	   		SQLFreeStmt( asth, SQL_DROP );
+	       	}
+				       
+		/*
+		 * PASSTHROUGH - to add new attributes -- do NOT add break
+		 */
+		case LDAP_MOD_ADD:
+add_only:;
+			if ( at->add_proc == NULL ) {
+				Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+					"add procedure is not defined "
+					"for attribute '%s'\n",
+					at->name, 0, 0 );
+				break;
 			}
-			if (c_mod->sm_bvalues==NULL)
-			{
-			 Debug(LDAP_DEBUG_TRACE,"backsql_modify(): no values given to add for attribute '%s'\n",at->name,0,0);
-			 break;
+			
+			if ( c_mod->sm_bvalues == NULL ) {
+				Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+					"no values given to add "
+					"for attribute '%s'\n",
+					at->name, 0, 0 );
+				break;
 			}
-			Debug(LDAP_DEBUG_TRACE,"backsql_modify(): adding new values for attribute '%s'\n",at->name,0,0);
-			for(i=0,at_val=c_mod->sm_bvalues[0];at_val!=NULL;i++,at_val=c_mod->sm_bvalues[i])
-			{
-			 if (at->expect_return & BACKSQL_ADD)
-			 {
-			  pno=1;
-			  SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&prc,0,0);
-			 }
-			 else
-			  pno=0;
-			 po=(at->param_order & BACKSQL_ADD)>0;
-			 SQLBindParameter(sth,(SQLUSMALLINT)(pno+1+po),SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&e_id.keyval,0,0);
-			 /*check for syntax needed here - maybe need binary bind?*/
-			 SQLBindParameter(sth,(SQLUSMALLINT)(pno+2-po),SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,0,0,at_val->bv_val,at_val->bv_len,0);
-			 
-			 Debug(LDAP_DEBUG_TRACE,"backsql_modify(): executing '%s'\n",at->add_proc,0,0);
-			 rc=SQLExecDirect(sth,at->add_proc,SQL_NTS);
-			 if (rc!=SQL_SUCCESS)
-			 {
-			  Debug(LDAP_DEBUG_TRACE,"backsql_modify(): add_proc execution failed\n",0,0,0);
-			  backsql_PrintErrors(bi->db_env,dbh,sth,rc);
-			 }
+			
+			Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+				"adding new values for attribute '%s'\n",
+				at->name, 0, 0 );
+			for ( i = 0, at_val = &c_mod->sm_bvalues[ 0 ];
+					at_val->bv_val != NULL; 
+					i++, at_val = &c_mod->sm_bvalues[ i ] ) {
+				if ( at->expect_return & BACKSQL_ADD ) {
+					pno = 1;
+	      				SQLBindParameter( sth, 1,
+						SQL_PARAM_OUTPUT,
+						SQL_C_ULONG, SQL_INTEGER,
+						0, 0, &prc, 0, 0);
+				} else {
+	      				pno = 0;
+				}
+				po = ( at->param_order & BACKSQL_ADD ) > 0;
+				SQLBindParameter( sth, pno + 1 + po,
+					SQL_PARAM_INPUT, 
+					SQL_C_ULONG, SQL_INTEGER,
+					0, 0, &e_id.keyval, 0, 0 );
+
+				/*
+				 * check for syntax needed here
+				 * maybe need binary bind?
+				 */
+				SQLBindParameter( sth, pno + 2 - po,
+					SQL_PARAM_INPUT,
+					SQL_C_CHAR, SQL_CHAR,
+					0, 0, at_val->bv_val, 
+					at_val->bv_len, 0 );
+
+				Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+					"executing '%s'\n", 
+					at->add_proc, 0, 0 );
+				rc = SQLExecDirect( sth, at->add_proc, 
+						SQL_NTS );
+				if ( rc != SQL_SUCCESS ) {
+					Debug( LDAP_DEBUG_TRACE,
+						"backsql_modify(): "
+						"add_proc execution failed\n",
+						0, 0, 0 );
+					backsql_PrintErrors( bi->db_env,
+							dbh, sth, rc );
+				}
 			}
 			break;
-  case LDAP_MOD_DELETE:
-			if (at->delete_proc==NULL)
-			{
-			 Debug(LDAP_DEBUG_TRACE,"backsql_modify(): delete procedure is not defined for this attribute ('%s')\n",at->name,0,0);
-			 break;
+			
+	      	case LDAP_MOD_DELETE:
+			if ( at->delete_proc == NULL ) {
+				Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+					"delete procedure is not defined "
+					"for attribute '%s'\n",
+					at->name, 0, 0 );
+				break;
 			}
-			if (c_mod->sm_bvalues==NULL)
-			{
-			 Debug(LDAP_DEBUG_TRACE,"backsql_modify(): no values given to delete for attribute '%s' -- deleting all values\n",at->name,0,0);
-			 goto del_all;
+
+			if ( c_mod->sm_bvalues == NULL ) {
+				Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+					"no values given to delete "
+					"for attribute '%s' "
+					"-- deleting all values\n",
+					at->name, 0, 0 );
+				goto del_all;
 			}
-            Debug(LDAP_DEBUG_TRACE,"backsql_modify(): deleting values for attribute '%s'\n",at->name,0,0);
-			for(i=0,at_val=c_mod->sm_bvalues[0];at_val!=NULL;i++,at_val=c_mod->sm_bvalues[i])
-			{
-			 if (at->expect_return & BACKSQL_DEL)
-			  {
-			   pno=1;
-			   SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&prc,0,0);
-			  }
-			 else
-			  pno=0;
-			 po=(at->param_order & BACKSQL_DEL)>0;
-			 SQLBindParameter(sth,(SQLUSMALLINT)(pno+1+po),SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&e_id.keyval,0,0);
-			 /*check for syntax needed here - maybe need binary bind?*/
-			 SQLBindParameter(sth,(SQLUSMALLINT)(pno+2-po),SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,0,0,at_val->bv_val,at_val->bv_len,0);
-			   
-			 Debug(LDAP_DEBUG_TRACE,"backsql_modify(): executing '%s'\n",at->delete_proc,0,0);
-			 rc=SQLExecDirect(sth,at->delete_proc,SQL_NTS);
-			 if (rc!=SQL_SUCCESS)
-			 {
-			  Debug(LDAP_DEBUG_TRACE,"backsql_modify(): delete_proc execution failed\n",0,0,0);
-			  backsql_PrintErrors(bi->db_env,dbh,sth,rc);
-			 }
+
+			Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+				"deleting values for attribute '%s'\n",
+				at->name, 0, 0 );
+			for( i = 0, at_val = &c_mod->sm_bvalues[ 0 ];
+					at_val->bv_val != NULL;
+					i++, at_val = &c_mod->sm_bvalues[ i ] ) {
+				if ( at->expect_return & BACKSQL_DEL ) {
+					pno = 1;
+					SQLBindParameter( sth, 1,
+						SQL_PARAM_OUTPUT,
+						SQL_C_ULONG, SQL_INTEGER,
+						0, 0, &prc, 0, 0 );
+				} else {
+					pno = 0;
+				}
+				po = ( at->param_order & BACKSQL_DEL ) > 0;
+				SQLBindParameter( sth, pno + 1 + po,
+					SQL_PARAM_INPUT, 
+					SQL_C_ULONG, SQL_INTEGER,
+					0, 0, &e_id.keyval, 0, 0 );
+
+				/*
+				 * check for syntax needed here 
+				 * maybe need binary bind?
+				 */
+				SQLBindParameter( sth, pno + 2 - po,
+					SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
+					0, 0, at_val->bv_val, 
+					at_val->bv_len, 0 );
+
+				Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+					"executing '%s'\n", 
+					at->delete_proc, 0, 0 );
+				rc = SQLExecDirect( sth, at->delete_proc,
+						SQL_NTS );
+				if ( rc != SQL_SUCCESS ) {
+					Debug( LDAP_DEBUG_TRACE,
+						"backsql_modify(): "
+						"delete_proc execution "
+						"failed\n", 0, 0, 0 );
+					backsql_PrintErrors( bi->db_env,
+							dbh, sth, rc );
+				}
 			}
 			break;
-  }
-  SQLFreeStmt(sth,SQL_RESET_PARAMS);
- }
-
- SQLFreeStmt(sth,SQL_DROP);
- send_ldap_result(conn,op,LDAP_SUCCESS,"",NULL,NULL,NULL);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_modify()\n",0,0,0);
- return 0;
+		}
+		
+		SQLFreeStmt( sth, SQL_RESET_PARAMS );
+	}
+
+	SQLFreeStmt( sth, SQL_DROP );
+	send_ldap_result( conn, op, LDAP_SUCCESS, "", NULL, NULL, NULL );
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n", 0, 0, 0 );
+
+	return 0;
 }
 
-int backsql_modrdn(BackendDB *be,Connection *conn,Operation *op,
-	const char *dn,const char *ndn,const char *newrdn,int deleteoldrdn,const char *newSuperior)
+int
+backsql_modrdn(
+	BackendDB 	*be,
+	Connection 	*conn,
+	Operation 	*op,
+	struct berval	*dn,
+	struct berval	*ndn,
+	struct berval	*newrdn,
+	struct berval	*nnewrdn,
+	int 		deleteoldrdn,
+	struct berval	*newSuperior,
+	struct berval	*nnewSuperior )
 {
- backsql_info *bi=(backsql_info*)be->be_private;
- SQLHDBC dbh;
- SQLHSTMT sth;
- RETCODE rc;
- backsql_oc_map_rec *oc=NULL;
- backsql_entryID e_id,pe_id,new_pid,*res;
- backsql_at_map_rec *at=NULL;
- char *p_dn=NULL,*new_pdn=NULL, *new_dn;
+	backsql_info		*bi = (backsql_info*)be->be_private;
+	SQLHDBC			dbh;
+	SQLHSTMT		sth;
+	RETCODE			rc;
+	backsql_entryID		e_id, pe_id, new_pid;
+	int			res;
+	struct berval		p_dn, p_ndn,
+				*new_pdn = NULL, *new_npdn = NULL,
+				new_dn, new_ndn;
  
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry '%s', "
+			"newrdn='%s', newSuperior='%s'\n",
+			dn->bv_val, newrdn->bv_val, newSuperior->bv_val );
+	dbh = backsql_get_db_conn( be, conn );
+	if ( !dbh ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+			"could not get connection handle - exiting\n", 
+			0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+			"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+
+	res = backsql_dn2id( bi, &e_id, dbh, ndn );
+	if ( res != LDAP_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+			"could not lookup entry id\n", 0, 0, 0 );
+		send_ldap_result( conn, op, res , "", NULL, NULL, NULL );
+		return 1;
+	}
+
+	Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): entry id is %ld\n",
+		e_id.id, 0, 0 );
+
+	dnParent( dn, &p_dn );
+	dnParent( ndn, &p_ndn );
+
+	if ( newSuperior ) {
+		new_pdn = newSuperior;
+		new_npdn = nnewSuperior;
+	} else {
+		new_pdn = &p_dn;
+		new_npdn = &p_ndn;
+	}
+
+	SQLAllocStmt( dbh, &sth );
+
+	if ( newSuperior && dn_match( &p_ndn, new_npdn ) ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+			"newSuperior is equal to old parent - aborting\n",
+			0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", 
+				NULL, NULL, NULL );
+  		goto modrdn_return;
+	}
+
+	if ( newSuperior && dn_match( ndn, new_npdn ) ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+			"newSuperior is equal to entry being moved "
+			"- aborting\n", 0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", 
+				NULL, NULL, NULL );
+		goto modrdn_return;
+	}
+
+	build_new_dn( &new_dn, new_pdn, newrdn ); 
+	if ( dnNormalize2( NULL, &new_dn, &new_ndn ) != LDAP_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+			"new dn is invalid ('%s') - aborting\n",
+			new_dn.bv_val, 0, 0 );
+		send_ldap_result( conn, op, LDAP_INVALID_DN_SYNTAX, "", 
+				NULL, NULL, NULL );
+		goto modrdn_return;
+	}
+	
+	Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): new entry dn is '%s'\n",
+			new_dn.bv_val, 0, 0 );
+
+	res = backsql_dn2id( bi, &pe_id, dbh, &p_ndn );
+	if ( res != LDAP_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+			"could not lookup old parent entry id\n", 0, 0, 0 );
+		send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
+		goto modrdn_return;
+	}
+
+	Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+		"old parent entry id is %ld\n", pe_id.id, 0, 0 );
+
+	res = backsql_dn2id( bi, &new_pid, dbh, new_npdn );
+	if ( res != LDAP_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+			"could not lookup new parent entry id\n", 0, 0, 0 );
+		send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
+		goto modrdn_return;
+	}
+	
+	Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+		"new parent entry id is %ld\n", new_pid.id, 0, 0 );
+
  
- Debug(LDAP_DEBUG_TRACE,"==>backsql_modrdn() renaming entry '%s', newrdn='%s', newSuperior='%s'\n",dn,newrdn,newSuperior);
- dbh=backsql_get_db_conn(be,conn);
- if (!dbh)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): could not get connection handle - exiting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
- res=backsql_dn2id(bi,&e_id,dbh,(char*)ndn);
- if (res==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): could not lookup entry id\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_NO_SUCH_OBJECT,"",NULL,NULL,NULL);
-  return 1;
- }
- Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): entry id is %d\n",e_id.id,0,0);
-
- p_dn=dn_parent(be,ndn);
-
- if (newSuperior)
-  new_pdn=dn_validate(ch_strdup(newSuperior));
- else
-   new_pdn=p_dn;
-
- SQLAllocStmt(dbh, &sth);
-
- if (newSuperior && !strcasecmp(p_dn,new_pdn))
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): newSuperior is equal to old parent - aborting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"",NULL,NULL,NULL);
-  goto modrdn_return;
- }
-
- if (newSuperior && !strcasecmp(ndn,new_pdn))
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): newSuperior is equal to entry being moved - aborting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"",NULL,NULL,NULL);
-  goto modrdn_return;
- }
-
- build_new_dn( &new_dn, dn, new_pdn, newrdn ); 
- if (!dn_validate(new_dn))
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): new dn is invalid ('%s') - aborting\n",new_dn,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"",NULL,NULL,NULL);
-  goto modrdn_return;
- }
- Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): new entry dn is '%s'\n",new_dn,0,0);
-
- res=backsql_dn2id(bi,&pe_id,dbh,(char*)p_dn);
- if (res==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): could not lookup old parent entry id\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_NO_SUCH_OBJECT,"",NULL,NULL,NULL);
-  goto modrdn_return;
- }
- Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): old parent entry id is %d\n",pe_id.id,0,0);
-
- res=backsql_dn2id(bi,&new_pid,dbh,(char*)new_pdn);
- if (res==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): could not lookup new parent entry id\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_NO_SUCH_OBJECT,"",NULL,NULL,NULL);
-  goto modrdn_return;
- }
- Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): new parent entry id is %d\n",new_pid.id,0,0);
-
- Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): executing delentry_query\n",0,0,0);
- SQLBindParameter(sth,1,SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&e_id.id,0,0);
- rc=SQLExecDirect(sth,bi->delentry_query,SQL_NTS);
- if (rc != SQL_SUCCESS)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): failed to delete record from ldap_entries\n",0,0,0);
-  backsql_PrintErrors(bi->db_env,dbh,sth,rc);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  goto modrdn_return;
- }
-
- SQLFreeStmt(sth,SQL_RESET_PARAMS);
-
- Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): executing insentry_query\n",0,0,0);
- backsql_BindParamStr(sth,1,new_dn,BACKSQL_MAX_DN_LEN);
- SQLBindParameter(sth,2,SQL_PARAM_INPUT,SQL_C_LONG,SQL_INTEGER,0,0,&e_id.oc_id,0,0);
- SQLBindParameter(sth,3,SQL_PARAM_INPUT,SQL_C_LONG,SQL_INTEGER,0,0,&new_pid.id,0,0);
- SQLBindParameter(sth,4,SQL_PARAM_INPUT,SQL_C_LONG,SQL_INTEGER,0,0,&e_id.keyval,0,0);
- rc=SQLExecDirect(sth,bi->insentry_query,SQL_NTS);
- if (rc != SQL_SUCCESS)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_modrdn(): could not insert ldap_entries record\n",0,0,0);
-  backsql_PrintErrors(bi->db_env,dbh,sth,rc);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  goto modrdn_return;
- }
-
- /*should process deleteoldrdn here...*/
-
- send_ldap_result(conn,op,LDAP_SUCCESS,"",NULL,NULL,NULL);
+	Debug(	LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+		"executing delentry_query\n", 0, 0, 0 );
+	SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
+			0, 0, &e_id.id, 0, 0 );
+	rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+			"failed to delete record from ldap_entries\n",
+			0, 0, 0 );
+		backsql_PrintErrors( bi->db_env, dbh, sth, rc );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		goto modrdn_return;
+	}
+
+	SQLFreeStmt( sth, SQL_RESET_PARAMS );
+
+	Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+		"executing insentry_query\n", 0, 0, 0 );
+	backsql_BindParamStr( sth, 1, new_dn.bv_val, BACKSQL_MAX_DN_LEN );
+	SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
+			0, 0, &e_id.oc_id, 0, 0 );
+	SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
+			0, 0, &new_pid.id, 0, 0 );
+	SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
+			0, 0, &e_id.keyval, 0, 0 );
+	rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+			"could not insert ldap_entries record\n", 0, 0, 0 );
+		backsql_PrintErrors( bi->db_env, dbh, sth, rc );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		goto modrdn_return;
+	}
+
+	/*
+	 * FIXME: should process deleteoldrdn here...
+	 */
+
+	send_ldap_result( conn, op, LDAP_SUCCESS, "", NULL, NULL, NULL );
+
 modrdn_return:
- SQLFreeStmt(sth,SQL_DROP);
- if (newSuperior && new_pdn)
-  ch_free(new_pdn);
- if (new_dn)
-  ch_free(new_dn);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_modrdn()\n",0,0,0);
- return 0;
+	SQLFreeStmt( sth, SQL_DROP );
+
+	if ( new_dn.bv_val ) {
+		ch_free( new_dn.bv_val );
+	}
+	
+	if ( new_ndn.bv_val ) {
+		ch_free( new_ndn.bv_val );
+	}
+	
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );
+	return 0;
 }
 
-int backsql_add(BackendDB *be,Connection *conn,Operation *op,Entry *e)
+int
+backsql_add(
+	BackendDB	*be,
+	Connection 	*conn,
+	Operation 	*op,
+	Entry 		*e )
 {
- backsql_info *bi=(backsql_info*)be->be_private;
- SQLHDBC dbh;
- SQLHSTMT sth;
- unsigned long new_keyval;
- long i;
- RETCODE rc;
- backsql_oc_map_rec *oc=NULL;
- backsql_at_map_rec *at_rec=NULL;
- backsql_entryID parent_id,*res;
- Attribute *at;
- struct berval *at_val;
- char *pdn;
- int pno,po;/*first parameter no, parameter order*/
- int prc; /*procedure return code*/
-
- Debug(LDAP_DEBUG_TRACE,"==>backsql_add(): adding entry '%s'\n",e->e_dn,0,0);
- if (dn_validate(e->e_dn)==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"==>backsql_add(): invalid dn '%s' -- aborting\n",e->e_dn,0,0);
- }
- for(at=e->e_attrs;at!=NULL;at=at->a_next)
- {
-  /*Debug(LDAP_DEBUG_TRACE,"backsql_add(): scanning entry -- %s\n",at->a_type,0,0);*/
-  if (!strcasecmp(at->a_desc->ad_cname.bv_val,"objectclass"))
-  {
-   oc=backsql_oc_with_name(bi,at->a_vals[0]->bv_val);
-   break;
-  }
- }
-
- if (oc==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_add(): cannot determine objectclass of entry -- aborting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
- if (oc->create_proc == NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_add(): create procedure is not defined for this objectclass - aborting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
-
- dbh=backsql_get_db_conn(be,conn);
- if (!dbh)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_add(): could not get connection handle - exiting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
-
- SQLAllocStmt(dbh, &sth);
- SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&new_keyval,0,0);
-
- Debug(LDAP_DEBUG_TRACE,"backsql_add(): executing '%s'\n",oc->create_proc,0,0);
- rc=SQLExecDirect(sth,oc->create_proc,SQL_NTS);
- if (rc != SQL_SUCCESS)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_add(): create_proc execution failed\n",0,0,0);
-  backsql_PrintErrors(bi->db_env,dbh,sth,rc);
-  SQLFreeStmt(sth,SQL_DROP);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
- SQLFreeStmt(sth,SQL_RESET_PARAMS);
- Debug(LDAP_DEBUG_TRACE,"backsql_add(): create_proc returned keyval=%d\n",new_keyval,0,0);
-
- for(at=e->e_attrs;at!=NULL;at=at->a_next)
- {
-  at_rec=backsql_at_with_name(oc,at->a_desc->ad_cname.bv_val); 
-  
-  if (at_rec==NULL)
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_add(): attribute provided is not registered in this objectclass ('%s')\n",at->a_desc->ad_cname.bv_val,0,0);
-   continue;
-  }
-  if (at_rec->add_proc==NULL)
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_add(): add procedure is not defined for this attribute ('%s')\n",at->a_desc->ad_cname.bv_val,0,0);
-   continue;
-  }
+	backsql_info		*bi = (backsql_info*)be->be_private;
+	SQLHDBC 		dbh;
+	SQLHSTMT 		sth;
+	unsigned long		new_keyval = 0;
+	long			i;
+	RETCODE			rc;
+	backsql_oc_map_rec 	*oc = NULL;
+	backsql_at_map_rec	*at_rec = NULL;
+	backsql_entryID		parent_id;
+	int			res;
+	Attribute		*at;
+	struct berval		*at_val;
+	struct berval		pdn;
+	/* first parameter no, parameter order */
+	SQLUSMALLINT		pno, po;
+	/* procedure return code */
+	int			prc;
+
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_add(): adding entry '%s'\n",
+			e->e_dn, 0, 0 );
+
+	for ( at = e->e_attrs; at != NULL; at = at->a_next ) {
+#if 0
+		Debug( LDAP_DEBUG_TRACE, "backsql_add(): scanning entry "
+			"-- %s\n", at->a_type, 0, 0 );
+#endif
+		if ( !strcasecmp( at->a_desc->ad_cname.bv_val, "objectclass" ) ) {
+			oc = backsql_oc_with_name( bi, at->a_vals[ 0 ].bv_val );
+		     	break;
+		}
+	}
+
+	if ( oc == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+			"cannot determine objectclass of entry -- aborting\n",
+			0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+
+	if ( oc->create_proc == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+			"create procedure is not defined for this objectclass "
+			"- aborting\n", 0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+
+	dbh = backsql_get_db_conn( be, conn );
+	if ( !dbh ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+			"could not get connection handle - exiting\n", 
+			0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+
+#ifndef BACKSQL_REALLOC_STMT
+	SQLAllocStmt( dbh, &sth );
+#else /* BACKSQL_REALLOC_STMT */
+	rc = backsql_Prepare( dbh, &sth, oc->create_proc, 0 );
+	if ( rc != SQL_SUCCESS ) {
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+#endif /* BACKSQL_REALLOC_STMT */
+
+	if ( oc->expect_return ) {
+		SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG, 
+				SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
+	}
+
+	Debug( LDAP_DEBUG_TRACE, "backsql_add(): executing '%s'\n",
+		oc->create_proc, 0, 0 );
+#ifndef BACKSQL_REALLOC_STMT
+	rc = SQLExecDirect( sth, oc->create_proc, SQL_NTS );
+#else /* BACKSQL_REALLOC_STMT */
+	rc = SQLExecute( sth );
+#endif /* BACKSQL_REALLOC_STMT */
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+			"create_proc execution failed\n", 0, 0, 0 );
+		backsql_PrintErrors( bi->db_env, dbh, sth, rc);
+		SQLFreeStmt( sth, SQL_DROP );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+
+	if ( !oc->expect_return ) {
+		/*
+		 * FIXME: need query to know the id of the inserted entry
+		 */
+	}
+
+#ifndef BACKSQL_REALLOC_STMT
+	SQLFreeStmt( sth, SQL_RESET_PARAMS );
+#else /* BACKSQL_REALLOC_STMT */
+	SQLFreeStmt( sth, SQL_DROP );
+#endif /* BACKSQL_REALLOC_STMT */
+	Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+		"create_proc returned keyval=%ld\n", new_keyval, 0, 0 );
+
+	for ( at = e->e_attrs; at != NULL; at = at->a_next ) {
+		SQLUSMALLINT	currpos;
+
+		if ( at->a_vals[ 0 ].bv_val == NULL ) {
+			continue;
+		}
+
+		at_rec = backsql_at_with_name( oc, 
+				at->a_desc->ad_cname.bv_val ); 
   
-  for(i=0,at_val=at->a_vals[0];at_val!=NULL;i++,at_val=at->a_vals[i])
-  {
-	if (at_rec->expect_return & BACKSQL_ADD)
-	{
-	 pno=1;
-	 SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&prc,0,0);
-	}
-	else
-	 pno=0;
-	po=(at_rec->param_order & BACKSQL_ADD)>0;
-	SQLBindParameter(sth,(SQLUSMALLINT)(pno+1+po),SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&new_keyval,0,0);
-	/*check for syntax needed here - maybe need binary bind?*/
-	SQLBindParameter(sth,(SQLUSMALLINT)(pno+2-po),SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,0,0,at_val->bv_val,at_val->bv_len,0);
-   Debug(LDAP_DEBUG_TRACE,"backsql_add(): executing '%s'\n",at_rec->add_proc,0,0);
-   rc=SQLExecDirect(sth,at_rec->add_proc,SQL_NTS);
-   if (rc!=SQL_SUCCESS)
-   {
-	Debug(LDAP_DEBUG_TRACE,"backsql_add(): add_proc execution failed\n",0,0,0);
-	backsql_PrintErrors(bi->db_env,dbh,sth,rc);
-   }
-  }
- }
- SQLFreeStmt(sth,SQL_RESET_PARAMS); 
- pdn=dn_parent(be,e->e_dn);
- res=backsql_dn2id(bi,&parent_id,dbh,pdn);
- if (res==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_add(): could not lookup parent entry for new record ('%s')\n",
-												pdn,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
- backsql_BindParamStr(sth,1,e->e_dn,BACKSQL_MAX_DN_LEN);
- SQLBindParameter(sth,2,SQL_PARAM_INPUT,SQL_C_LONG,SQL_INTEGER,0,0,&oc->id,0,0);
- SQLBindParameter(sth,3,SQL_PARAM_INPUT,SQL_C_LONG,SQL_INTEGER,0,0,&parent_id.id,0,0);
- SQLBindParameter(sth,4,SQL_PARAM_INPUT,SQL_C_LONG,SQL_INTEGER,0,0,&new_keyval,0,0);
- rc=SQLExecDirect(sth,bi->insentry_query,SQL_NTS);
- if (rc != SQL_SUCCESS)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_add(): could not insert ldap_entries record\n",0,0,0);
-  backsql_PrintErrors(bi->db_env,dbh,sth,rc);
-  /*execute delete_proc to delete data added !!!*/
-  SQLFreeStmt(sth,SQL_DROP);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
- SQLFreeStmt(sth,SQL_DROP);
- send_ldap_result(conn,op,LDAP_SUCCESS,"",NULL,NULL,NULL);
- return 0;
+		if ( at_rec == NULL ) {
+			Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+				"attribute '%s' is not registered "
+				"in objectclass '%s'\n",
+				at->a_desc->ad_cname.bv_val, oc->name, 0 );
+			continue;
+		}
+		
+		if ( at_rec->add_proc == NULL ) {
+			Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+				"add procedure is not defined "
+				"for attribute '%s'\n",
+				at->a_desc->ad_cname.bv_val, 0, 0 );
+			continue;
+		}
+
+#ifdef BACKSQL_REALLOC_STMT
+		rc = backsql_Prepare( dbh, &sth, at_rec->add_proc, 0 );
+		if ( rc != SQL_SUCCESS ) {
+			continue;
+		}
+#endif /* BACKSQL_REALLOC_STMT */
+
+		if ( at_rec->expect_return & BACKSQL_ADD ) {
+			pno = 1;
+			SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT,
+					SQL_C_ULONG, SQL_INTEGER,
+					0, 0, &prc, 0, 0 );
+		} else {
+			pno = 0;
+		}
+
+		po = ( at_rec->param_order & BACKSQL_ADD ) > 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;
+
+		for ( i = 0, at_val = &at->a_vals[ 0 ];
+				at_val->bv_val != NULL;
+				i++, at_val = &at->a_vals[ i ] ) {
+
+			/*
+			 * check for syntax needed here 
+			 * maybe need binary bind?
+			 */
+
+			backsql_BindParamStr( sth, currpos,
+					at_val->bv_val, at_val->bv_len + 1 );
+
+			Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+				"executing '%s' with val='%s', id=%ld\n", 
+				at_rec->add_proc, at_val->bv_val, new_keyval );
+#ifndef BACKSQL_REALLOC_STMT
+			rc = SQLExecDirect( sth, at_rec->add_proc, SQL_NTS );
+#else /* BACKSQL_REALLOC_STMT */
+			rc = SQLExecute( sth );
+#endif /* BACKSQL_REALLOC_STMT */
+			if ( rc != SQL_SUCCESS ) {
+				Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+					"add_proc execution failed\n", 
+					0, 0, 0 );
+				backsql_PrintErrors( bi->db_env, dbh, sth, rc );
+			}
+		}
+#ifndef BACKSQL_REALLOC_STMT
+		SQLFreeStmt( sth, SQL_RESET_PARAMS ); 
+#else /* BACKSQL_REALLOC_STMT */
+		SQLFreeStmt( sth, SQL_DROP );
+#endif /* BACKSQL_REALLOC_STMT */
+	}
+
+	dnParent( &e->e_name, &pdn );
+	res = backsql_dn2id( bi, &parent_id, dbh, &pdn );
+	if ( res != LDAP_SUCCESS ) {
+		/*
+		 * NO SUCH OBJECT seems more appropriate
+		 */
+		Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+			"could not lookup parent entry for new record '%s'\n",
+			pdn.bv_val, 0, 0 );
+		send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
+		return 1;
+	}
+#ifdef BACKSQL_REALLOC_STMT
+	rc = backsql_Prepare( dbh, &sth, bi->insentry_query, 0 );
+	if ( rc != SQL_SUCCESS ) {
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+#endif /* BACKSQL_REALLOC_STMT */
+	backsql_BindParamStr( sth, 1, e->e_name.bv_val, BACKSQL_MAX_DN_LEN );
+	SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
+			0, 0, &oc->id, 0, 0 );
+	SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
+			0, 0, &parent_id.id, 0, 0 );
+	SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
+			0, 0, &new_keyval, 0, 0 );
+
+	Debug( LDAP_DEBUG_TRACE, "backsql_add(): executing '%s' for dn '%s'\n",
+			bi->insentry_query, e->e_name.bv_val, 0 );
+	Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, parent_id=%ld, "
+			"keyval=%ld\n", oc->id, parent_id.id, new_keyval );
+#ifndef BACKSQL_REALLOC_STMT
+	rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
+#else /* BACKSQL_REALLOC_STMT */
+	rc = SQLExecute( sth );
+#endif /* BACKSQL_REALLOC_STMT */
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+			"could not insert ldap_entries record\n", 0, 0, 0 );
+		backsql_PrintErrors( bi->db_env, dbh, sth, rc );
+		
+		/*
+		 * execute delete_proc to delete data added !!!
+		 */
+		SQLFreeStmt( sth, SQL_DROP );
+		send_ldap_result( conn, op, LDAP_OTHER, "", 
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+	
+	SQLFreeStmt( sth, SQL_DROP );
+	send_ldap_result( conn, op, LDAP_SUCCESS, "",
+			NULL, NULL, NULL );
+	return 0;
 }
 
-int backsql_delete(BackendDB *be,Connection *conn,Operation *op,
-	const char *dn,const char *ndn)
+int
+backsql_delete(
+	BackendDB	*be,
+	Connection	*conn,
+	Operation	*op,
+	struct berval	*dn,
+	struct berval	*ndn )
 {
- backsql_info *bi=(backsql_info*)be->be_private;
- SQLHDBC dbh;
- SQLHSTMT sth;
- RETCODE rc;
- backsql_oc_map_rec *oc=NULL;
- backsql_entryID e_id,*res;
- int pno;/*first parameter no, parameter order*/
-
- Debug(LDAP_DEBUG_TRACE,"==>backsql_delete(): deleting entry '%s'\n",ndn,0,0);
- dbh=backsql_get_db_conn(be,conn);
- if (!dbh)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_delete(): could not get connection handle - exiting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
- res=backsql_dn2id(bi,&e_id,dbh,(char*)ndn);
- if (res==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_delete(): could not lookup entry id\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_NO_SUCH_OBJECT,"",NULL,NULL,NULL);
-  return 1;
- }
-
- oc=backsql_oc_with_id(bi,e_id.oc_id);
- if (oc==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_delete(): cannot determine objectclass of entry -- aborting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
- if (oc->delete_proc == NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_delete(): delete procedure is not defined for this objectclass - aborting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
-
- SQLAllocStmt(dbh, &sth);
- if (oc->expect_return)
- {
-  pno=1;
-  SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&rc,0,0);
- }
- else
-  pno=0;
- SQLBindParameter(sth,(SQLUSMALLINT)(pno+1),SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&e_id.keyval,0,0);
- /*SQLBindParameter(sth,2,SQL_PARAM_OUTPUT,SQL_C_SLONG,SQL_INTEGER,0,0,&retcode,0,0);*/
-
- Debug(LDAP_DEBUG_TRACE,"backsql_delete(): executing '%s'\n",oc->delete_proc,0,0);
- rc=SQLExecDirect(sth,oc->delete_proc,SQL_NTS);
- if (rc != SQL_SUCCESS)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_delete(): delete_proc execution failed\n",0,0,0);
-  backsql_PrintErrors(bi->db_env,dbh,sth,rc);
-  SQLFreeStmt(sth,SQL_DROP);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
- SQLFreeStmt(sth,SQL_RESET_PARAMS);
-
- SQLBindParameter(sth,1,SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&e_id.id,0,0);
- rc=SQLExecDirect(sth,bi->delentry_query,SQL_NTS);
- if (rc != SQL_SUCCESS)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_delete(): failed to delete record from ldap_entries\n",0,0,0);
-  backsql_PrintErrors(bi->db_env,dbh,sth,rc);
-  SQLFreeStmt(sth,SQL_DROP);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
- SQLFreeStmt(sth,SQL_DROP);
-
- send_ldap_result(conn,op,LDAP_SUCCESS,"",NULL,NULL,NULL);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_delete()\n",0,0,0);
- return 0;
+	backsql_info 		*bi = (backsql_info*)be->be_private;
+	SQLHDBC 		dbh;
+	SQLHSTMT		sth;
+	RETCODE			rc;
+	backsql_oc_map_rec	*oc = NULL;
+	backsql_entryID		e_id;
+	int			res;
+	/* first parameter no */
+	SQLUSMALLINT		pno;
+
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry '%s'\n",
+			ndn->bv_val, 0, 0 );
+	dbh = backsql_get_db_conn( be, conn );
+	if ( !dbh ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+			"could not get connection handle - exiting\n", 
+			0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+	
+	res = backsql_dn2id( bi, &e_id, dbh, ndn );
+	if ( res != LDAP_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+			"could not lookup entry id\n", 0, 0, 0 );
+		send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
+		return 1;
+	}
+
+	oc = backsql_oc_with_id( bi, e_id.oc_id );
+	if ( oc == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+			"cannot determine objectclass of entry "
+			"-- aborting\n", 0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+ 		return 1;
+	}
+
+	if ( oc->delete_proc == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+			"delete procedure is not defined "
+			"for this objectclass - aborting\n", 0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+
+	SQLAllocStmt( dbh, &sth );
+	if ( oc->expect_return ) {
+		pno = 1;
+		SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
+				SQL_INTEGER, 0, 0, &rc, 0, 0 );
+	} else {
+		pno = 0;
+	}
+
+	SQLBindParameter( sth, pno + 1, SQL_PARAM_INPUT, 
+			SQL_C_ULONG, SQL_INTEGER, 0, 0, &e_id.keyval, 0, 0 );
+#if 0
+	SQLBindParameter( sth, 2, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER,
+			0, 0, &retcode, 0, 0 );
+#endif
+
+	Debug( LDAP_DEBUG_TRACE, "backsql_delete(): executing '%s'\n",
+			oc->delete_proc, 0, 0 );
+	rc = SQLExecDirect( sth, oc->delete_proc, SQL_NTS );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+			"delete_proc execution failed\n", 0, 0, 0 );
+		backsql_PrintErrors( bi->db_env, dbh, sth, rc );
+		SQLFreeStmt( sth, SQL_DROP );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+	SQLFreeStmt( sth, SQL_RESET_PARAMS );
+
+	SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
+			0, 0, &e_id.id, 0, 0 );
+	rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+			"failed to delete record from ldap_entries\n", 
+			0, 0, 0 );
+		backsql_PrintErrors( bi->db_env, dbh, sth, rc );
+		SQLFreeStmt( sth, SQL_DROP );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+	
+	SQLFreeStmt( sth, SQL_DROP );
+	send_ldap_result( conn, op, LDAP_SUCCESS, "", NULL, NULL, NULL );
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );
+	return 0;
 }
 
 #endif /* SLAPD_SQL */
+
diff --git a/servers/slapd/back-sql/other.c b/servers/slapd/back-sql/other.c
index dc40a0e28d..62dcbe8150 100644
--- a/servers/slapd/back-sql/other.c
+++ b/servers/slapd/back-sql/other.c
@@ -17,26 +17,37 @@
 #include "back-sql.h"
 #include "sql-wrap.h"
 
-int backsql_dummy()
+int
+backsql_dummy( void )
 {
- return 0;
+	return 0;
 }
 
-int	backsql_compare(BackendDB *bd,
-	Connection *conn, Operation *op,
-	const char *dn, const char *ndn,
+int
+backsql_compare(
+	BackendDB	*bd,
+	Connection	*conn,
+	Operation	*op,
+	struct berval	*dn,
+	struct berval	*ndn,
 	AttributeAssertion *ava )
 {
- Debug(LDAP_DEBUG_TRACE,"==>backsql_compare() - not implemented\n",0,0,0);
- return 0;
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_compare() - not implemented\n",
+			0, 0, 0 );
+	return 1;
 }
 
-int backsql_abandon( BackendDB *be,
-	Connection *conn, Operation *op, int msgid )
+int
+backsql_abandon(
+	BackendDB 	*be,
+	Connection	*conn, 
+	Operation	*op, 
+	int		msgid )
 {
- Debug(LDAP_DEBUG_TRACE,"==>backsql_abandon()\n",0,0,0);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_abandon()\n",0,0,0);
- return 0;
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_abandon()\n", 0, 0, 0 );
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_abandon()\n", 0, 0, 0 );
+	return 0;
 }
 
 #endif /* SLAPD_SQL */
+
diff --git a/servers/slapd/back-sql/schema-map.c b/servers/slapd/back-sql/schema-map.c
index 5f84573787..2598849c48 100644
--- a/servers/slapd/back-sql/schema-map.c
+++ b/servers/slapd/back-sql/schema-map.c
@@ -20,309 +20,440 @@
 #include "schema-map.h"
 #include "util.h"
 
-int backsql_dummy(void *,void *);
+int backsql_dummy( void *, void * );
 
-int backsql_cmp_oc_name(backsql_oc_map_rec *m1,backsql_oc_map_rec *m2)
+int
+backsql_cmp_oc_name( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
 {
- return strcasecmp(m1->name,m2->name);
+	return strcasecmp( m1->name, m2->name );
 }
 
-int backsql_cmp_oc_id(backsql_oc_map_rec *m1,backsql_oc_map_rec *m2)
+int
+backsql_cmp_oc_id( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
 {
- if (m1->id < m2->id)
-  return -1;
- if (m1->id > m2->id)
-  return 1;
- return 0;
+	if ( m1->id < m2->id ) {
+		return -1;
+	}
+	if ( m1->id > m2->id ) {
+		return 1;
+	}
+	return 0;
 }
 
-int backsql_cmp_attr(backsql_at_map_rec *m1,backsql_at_map_rec *m2)
+int
+backsql_cmp_attr( 
+	backsql_at_map_rec 	*m1, 
+	backsql_at_map_rec 	*m2 )
 {
- return strcasecmp(m1->name,m2->name);
+	return strcasecmp( m1->name, m2->name );
 }
 
-char* backsql_make_attr_query(backsql_oc_map_rec *oc_map,backsql_at_map_rec *at_map)
+char *
+backsql_make_attr_query( 
+	backsql_oc_map_rec 	*oc_map,
+	backsql_at_map_rec 	*at_map )
 {
- char *tmps;
- int tmpslen;
-
- tmps=NULL;tmpslen=0;
- tmps=backsql_strcat(tmps,&tmpslen,"SELECT ",at_map->sel_expr," AS ",at_map->name,
-			" FROM ",at_map->from_tbls,
-			" WHERE ",oc_map->keytbl,".",oc_map->keycol,"=?",NULL);
- if (at_map->join_where!=NULL && at_map->join_where[0]!='\0')
-  tmps=backsql_strcat(tmps,&tmpslen," AND ",at_map->join_where,NULL);
- at_map->query=ch_strdup(tmps);
- ch_free(tmps);
- return at_map->query;
-}
+	struct berval	tmps = { 0, NULL };
+	int		tmpslen = 0;
+
+	backsql_strcat( &tmps, &tmpslen, "SELECT ", at_map->sel_expr, 
+			" AS ", at_map->name, " FROM ", at_map->from_tbls,
+			" WHERE ", oc_map->keytbl,".", oc_map->keycol,
+			"=?", NULL );
+	if ( at_map->join_where != NULL ) {
+		backsql_strcat( &tmps, &tmpslen, " AND ", 
+				at_map->join_where, NULL );
+	}
 
+	at_map->query = tmps.bv_val;
+	
+	return at_map->query;
+}
 
-int backsql_add_sysmaps(backsql_oc_map_rec *oc_map)
+int
+backsql_add_sysmaps( backsql_oc_map_rec *oc_map )
 {
- backsql_at_map_rec *at_map;
- int len;
- char s[30]; 
-
- sprintf(s,"%d",oc_map->id);
- at_map=(backsql_at_map_rec*)ch_calloc(1,sizeof(backsql_at_map_rec));
- at_map->name=ch_strdup("objectClass");
- at_map->sel_expr=ch_strdup("ldap_entry_objclasses.oc_name");
- at_map->from_tbls=ch_strdup("ldap_entry_objclasses,ldap_entries");
- len=strlen(at_map->from_tbls);
- backsql_merge_from_clause(&at_map->from_tbls,&len,oc_map->keytbl);
- at_map->join_where=NULL; len=0;
- at_map->join_where=backsql_strcat(at_map->join_where,&len,
-			"ldap_entries.id=ldap_entry_objclasses.entry_id and ldap_entries.keyval=",
-			oc_map->keytbl,".",oc_map->keycol," and ldap_entries.oc_map_id=",s,NULL);
- at_map->add_proc=NULL;
- at_map->delete_proc=NULL;
- at_map->param_order=0;
- at_map->expect_return=0;
- backsql_make_attr_query(oc_map,at_map);
- avl_insert(&oc_map->attrs,at_map,(AVL_CMP)backsql_cmp_attr,backsql_dummy);
-
- at_map=(backsql_at_map_rec*)ch_calloc(1,sizeof(backsql_at_map_rec));
- at_map->name=ch_strdup("ref");
- at_map->sel_expr=ch_strdup("ldap_referrals.url");
- at_map->from_tbls=ch_strdup("ldap_referrals,ldap_entries");
- len=strlen(at_map->from_tbls);
- backsql_merge_from_clause(&at_map->from_tbls,&len,oc_map->keytbl);
- at_map->join_where=NULL; len=0;
- at_map->join_where=backsql_strcat(at_map->join_where,&len,
-			"ldap_entries.id=ldap_referrals.entry_id and ldap_entries.keyval=",
-			oc_map->keytbl,".",oc_map->keycol," and ldap_entries.oc_map_id=",s,NULL);
- at_map->add_proc=NULL;
- at_map->delete_proc=NULL;
- at_map->param_order=0;
- at_map->expect_return=0;
- backsql_make_attr_query(oc_map,at_map);
- avl_insert(&oc_map->attrs,at_map,(AVL_CMP)backsql_cmp_attr,backsql_dummy);
-
- return 1;
+	backsql_at_map_rec	*at_map;
+	int			len;
+	char			s[ 30 ]; 
+	struct berval		bv;
+
+	snprintf( s, sizeof( s ), "%ld", oc_map->id );
+
+	at_map = (backsql_at_map_rec *)ch_calloc(1, 
+			sizeof( backsql_at_map_rec ) );
+	at_map->name = ch_strdup( "objectClass" );
+	at_map->sel_expr = ch_strdup( "ldap_entry_objclasses.oc_name" );
+	at_map->from_tbls = ch_strdup( "ldap_entry_objclasses,ldap_entries" );
+	len = strlen( at_map->from_tbls );
+	backsql_merge_from_clause( &at_map->from_tbls, &len, oc_map->keytbl );
+	len = 0;
+	bv.bv_val = NULL;
+	bv.bv_len = 0;
+	backsql_strcat( &bv, &len,
+			"ldap_entries.id=ldap_entry_objclasses.entry_id "
+			"and ldap_entries.keyval=",
+			oc_map->keytbl, ".", oc_map->keycol,
+			" and ldap_entries.oc_map_id=", s, NULL );
+	at_map->join_where = bv.bv_val;
+	at_map->add_proc = NULL;
+	at_map->delete_proc = NULL;
+	at_map->param_order = 0;
+	at_map->expect_return = 0;
+	backsql_make_attr_query( oc_map, at_map );
+	avl_insert( &oc_map->attrs, at_map, 
+			(AVL_CMP)backsql_cmp_attr, backsql_dummy );
+
+	at_map = (backsql_at_map_rec *)ch_calloc( 1, 
+			sizeof( backsql_at_map_rec ) );
+	at_map->name = ch_strdup( "ref" );
+	at_map->sel_expr = ch_strdup( "ldap_referrals.url" );
+	at_map->from_tbls = ch_strdup( "ldap_referrals,ldap_entries" );
+	len = strlen( at_map->from_tbls );
+	backsql_merge_from_clause( &at_map->from_tbls, &len,oc_map->keytbl );
+
+	/* FIXME: no free? */
+	at_map->join_where = NULL;
+
+	len = 0;
+	bv.bv_val = NULL;
+	bv.bv_len = 0;
+	backsql_strcat( &bv, &len,
+			"ldap_entries.id=ldap_referrals.entry_id "
+			"and ldap_entries.keyval=",
+			oc_map->keytbl, ".", oc_map->keycol,
+			" and ldap_entries.oc_map_id=", s, NULL );
+	at_map->join_where = bv.bv_val;
+	at_map->add_proc = NULL;
+	at_map->delete_proc = NULL;
+	at_map->param_order = 0;
+	at_map->expect_return = 0;
+	backsql_make_attr_query( oc_map, at_map );
+	avl_insert( &oc_map->attrs, at_map, 
+			(AVL_CMP)backsql_cmp_attr, backsql_dummy );
+
+	return 1;
 }
 
-int backsql_load_schema_map(backsql_info *si,SQLHDBC dbh)
+int
+backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
 {
- SQLHSTMT oc_sth,at_sth;
- RETCODE rc;
- BACKSQL_ROW_NTS oc_row,at_row;
- unsigned long oc_id;
- backsql_oc_map_rec *oc_map;
- backsql_at_map_rec *at_map;
- char *tmps;
- int tmpslen;
-
- Debug(LDAP_DEBUG_TRACE,"==>load_schema_map()\n",0,0,0);
-
- /* TimesTen : See if the ldap_entries.dn_ru field exists in the schema. */
-
- rc = backsql_Prepare(dbh, &oc_sth, backsql_check_dn_ru_query, 0);
- if (rc == SQL_SUCCESS) {
-   si->has_ldapinfo_dn_ru = 1;  /* Yes, the field exists */
-   Debug(LDAP_DEBUG_TRACE, "ldapinfo.dn_ru field exists in the schema\n", 0, 0,0);
- }
- else {
-   si->has_ldapinfo_dn_ru = 0;  /* No such field exists */
- }
-
- SQLFreeStmt(oc_sth, SQL_DROP);
-
- rc=backsql_Prepare(dbh,&oc_sth,si->oc_query,0);
- if (rc != SQL_SUCCESS)
-  {
-   Debug(LDAP_DEBUG_TRACE,"load_schema_map(): error preparing oc_query: '%s'\n",si->oc_query,0,0);
-   backsql_PrintErrors(si->db_env,dbh,oc_sth,rc);
-   return -1;
-  }
-  Debug(LDAP_DEBUG_TRACE, "load_schema_map(): at_query '%s'\n", si->at_query,0,0);
-
- rc=backsql_Prepare(dbh,&at_sth,si->at_query,0);
- if (rc != SQL_SUCCESS)
-  {
-   Debug(LDAP_DEBUG_TRACE,"load_schema_map(): error preparing at_query: '%s'\n",si->at_query,0,0);
-   backsql_PrintErrors(si->db_env,dbh,at_sth,rc);
-   return -1;
-  }
- if ((rc=backsql_BindParamID(at_sth,1,&oc_id)) != SQL_SUCCESS)
-  {
-   Debug(LDAP_DEBUG_TRACE,"load_schema_map(): error binding param for at_query: \n",0,0,0);
-   backsql_PrintErrors(si->db_env,dbh,at_sth,rc);
-   return -1;
-  }
- if ((rc=SQLExecute(oc_sth)) != SQL_SUCCESS)
-  {
-   Debug(LDAP_DEBUG_TRACE,"load_schema_map(): error executing oc_query: \n",0,0,0);
-   backsql_PrintErrors(si->db_env,dbh,oc_sth,rc);
-   return -1;
-  }
- backsql_BindRowAsStrings(oc_sth,&oc_row);
- while ((rc=SQLFetch(oc_sth)) == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
-  {
-   oc_map=(backsql_oc_map_rec*)ch_calloc(1,sizeof(backsql_oc_map_rec));
-   oc_map->id=atoi(oc_row.cols[0]);
-   oc_map->name=ch_strdup(oc_row.cols[1]);
-   oc_map->keytbl=ch_strdup(oc_row.cols[2]);
-   oc_map->keycol=ch_strdup(oc_row.cols[3]);
-   oc_map->create_proc=(oc_row.is_null[4]<0)?NULL:ch_strdup(oc_row.cols[4]);
-   oc_map->delete_proc=(oc_row.is_null[5]<0)?NULL:ch_strdup(oc_row.cols[5]);
-   oc_map->expect_return=atoi(oc_row.cols[6]);
-
-   oc_map->attrs=NULL;
-   avl_insert(&si->oc_by_name,oc_map,(AVL_CMP)backsql_cmp_oc_name,backsql_dummy);
-   avl_insert(&si->oc_by_id,oc_map,(AVL_CMP)backsql_cmp_oc_id,backsql_dummy);
-   oc_id=oc_map->id;
-   Debug(LDAP_DEBUG_TRACE,"load_schema_map(): objectclass '%s': keytbl='%s' keycol='%s' ",
-	   oc_map->name,oc_map->keytbl,oc_map->keycol);
-   if (oc_map->delete_proc) {
-     Debug(LDAP_DEBUG_TRACE,"delete_proc='%s'\n", oc_map->delete_proc, 0, 0);
-   }
-   if (oc_map->create_proc) {
-     Debug(LDAP_DEBUG_TRACE,"create_proc='%s'\n", oc_map->create_proc, 0, 0);
-   }
-   Debug(LDAP_DEBUG_TRACE,"expect_return=%d; attributes:\n",
-       oc_map->expect_return, 0, 0);
-
-   Debug(LDAP_DEBUG_TRACE,"load_schema_map(): autoadding 'objectClass' and 'ref' mappings\n",0,0,0);
-   backsql_add_sysmaps(oc_map);
-   if ((rc=SQLExecute(at_sth)) != SQL_SUCCESS)
-    {
-     Debug(LDAP_DEBUG_TRACE,"load_schema_map(): error executing at_query: \n",0,0,0);
-     backsql_PrintErrors(SQL_NULL_HENV,dbh,at_sth,rc);
-     return -1;
-    }
-   backsql_BindRowAsStrings(at_sth,&at_row);
-   while ((rc=SQLFetch(at_sth)) == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
-    {
-     Debug(LDAP_DEBUG_TRACE,"********'%s'\n",at_row.cols[0],0,0);
-     Debug(LDAP_DEBUG_TRACE,"name='%s',sel_expr='%s' from='%s' ",at_row.cols[0],
-             at_row.cols[1],at_row.cols[2]);
-	 Debug(LDAP_DEBUG_TRACE,"join_where='%s',add_proc='%s' ",at_row.cols[3],
-             at_row.cols[4],0);
-	 Debug(LDAP_DEBUG_TRACE,"delete_proc='%s'\n",at_row.cols[5],0,0);
-	 Debug(LDAP_DEBUG_TRACE,"sel_expr_u='%s'\n", at_row.cols[8],0,0); /* TimesTen*/
-     at_map=(backsql_at_map_rec*)ch_calloc(1,sizeof(backsql_at_map_rec));
-     at_map->name=ch_strdup(at_row.cols[0]);
-     at_map->sel_expr=ch_strdup(at_row.cols[1]);
-	 at_map->sel_expr_u = (at_row.is_null[8]<0)?NULL:ch_strdup(at_row.cols[8
-]);
-	 tmps=NULL;tmpslen=0;
-	 backsql_merge_from_clause(&tmps,&tmpslen,at_row.cols[2]);
-     at_map->from_tbls=ch_strdup(tmps);
-	 ch_free(tmps);
-	 at_map->join_where=ch_strdup((at_row.is_null[3]<0)?"":at_row.cols[3]);
-	 at_map->add_proc=(at_row.is_null[4]<0)?NULL:ch_strdup(at_row.cols[4]);
-	 at_map->delete_proc=(at_row.is_null[5]<0)?NULL:ch_strdup(at_row.cols[5]);
-	 at_map->param_order=atoi(at_row.cols[6]);
-	 at_map->expect_return=atoi(at_row.cols[7]);
-	 backsql_make_attr_query(oc_map,at_map);
-	 Debug(LDAP_DEBUG_TRACE,"load_schema_map(): preconstructed query '%s'\n",at_map->query,0,0);
-     avl_insert(&oc_map->attrs,at_map,(AVL_CMP)backsql_cmp_attr,backsql_dummy);
-    }
-   backsql_FreeRow(&at_row);
-   SQLFreeStmt(at_sth,SQL_CLOSE);
-  }
- backsql_FreeRow(&oc_row);
- SQLFreeStmt(at_sth,SQL_DROP);
- SQLFreeStmt(oc_sth,SQL_DROP);
- si->schema_loaded=1;
- Debug(LDAP_DEBUG_TRACE,"<==load_schema_map()\n",0,0,0);
- return 1;
+	SQLHSTMT 		oc_sth, at_sth;
+	RETCODE			rc;
+	BACKSQL_ROW_NTS		oc_row, at_row;
+	unsigned long		oc_id;
+	backsql_oc_map_rec	*oc_map;
+	backsql_at_map_rec	*at_map;
+	char			*tmps;
+	int			tmpslen;
+
+	Debug( LDAP_DEBUG_TRACE, "==>load_schema_map()\n", 0, 0, 0 );
+
+	/* 
+	 * TimesTen : See if the ldap_entries.dn_ru field exists in the schema
+	 */
+	if ( si->has_ldapinfo_dn_ru == -1 ) {
+		rc = backsql_Prepare( dbh, &oc_sth, 
+				backsql_check_dn_ru_query, 0 );
+		if ( rc == SQL_SUCCESS ) {
+			si->has_ldapinfo_dn_ru = 1;  /* Yes, the field exists */
+   			Debug( LDAP_DEBUG_TRACE, "ldapinfo.dn_ru field exists "
+				"in the schema\n", 0, 0, 0 );
+		} else {
+			si->has_ldapinfo_dn_ru = 0;  /* No such field exists */
+		}
+
+		SQLFreeStmt( oc_sth, SQL_DROP );
+	}
+
+
+	rc = backsql_Prepare( dbh, &oc_sth, si->oc_query, 0 );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
+			"error preparing oc_query: '%s'\n", 
+			si->oc_query, 0, 0 );
+		backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
+		return -1;
+	}
+	Debug( LDAP_DEBUG_TRACE, "load_schema_map(): at_query '%s'\n", 
+			si->at_query, 0, 0 );
+
+	rc = backsql_Prepare( dbh, &at_sth, si->at_query, 0 );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
+			"error preparing at_query: '%s'\n", 
+			si->at_query, 0, 0 );
+		backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
+		return -1;
+	}
+
+	rc = backsql_BindParamID( at_sth, 1, &oc_id );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
+			"error binding param for at_query: \n", 0, 0, 0 );
+		backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
+		return -1;
+	}
+
+	rc = SQLExecute( oc_sth );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
+			"error executing oc_query: \n", 0, 0, 0 );
+		backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
+		return -1;
+	}
+
+	backsql_BindRowAsStrings( oc_sth, &oc_row );
+	rc = SQLFetch( oc_sth );
+	for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( oc_sth ) ) {
+		oc_map = (backsql_oc_map_rec *)ch_calloc( 1,
+				sizeof( backsql_oc_map_rec ) );
+		oc_map->id = atoi( oc_row.cols[ 0 ] );
+		oc_map->name = ch_strdup( oc_row.cols[ 1 ] );
+		oc_map->keytbl = ch_strdup( oc_row.cols[ 2 ] );
+		oc_map->keycol = ch_strdup( oc_row.cols[ 3 ] );
+		oc_map->create_proc = ( oc_row.is_null[ 4 ] < 0 ) ? NULL 
+			: ch_strdup( oc_row.cols[ 4 ] );
+		oc_map->delete_proc = ( oc_row.is_null[ 5 ] < 0 ) ? NULL 
+			: ch_strdup( oc_row.cols[ 5 ] );
+		oc_map->expect_return = atoi( oc_row.cols[ 6 ] );
+
+		/*
+		 * FIXME: first attempt to check for offending
+		 * instructions in {create|delete}_proc
+		 */
+
+		oc_map->attrs = NULL;
+		avl_insert( &si->oc_by_name, oc_map,
+				(AVL_CMP)backsql_cmp_oc_name, backsql_dummy );
+		avl_insert( &si->oc_by_id, oc_map,
+				(AVL_CMP)backsql_cmp_oc_id, backsql_dummy );
+		oc_id = oc_map->id;
+		Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
+			"objectClass '%s': keytbl='%s' keycol='%s'\n",
+			oc_map->name, oc_map->keytbl, oc_map->keycol );
+		if ( oc_map->delete_proc ) {
+			Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n", 
+				oc_map->delete_proc, 0, 0 );
+		}
+		if ( oc_map->create_proc ) {
+			Debug( LDAP_DEBUG_TRACE, "create_proc='%s'\n",
+				oc_map->create_proc, 0, 0 );
+		}
+		Debug( LDAP_DEBUG_TRACE, "expect_return=%d; attributes:\n",
+			oc_map->expect_return, 0, 0 );
+
+		Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
+			"autoadding 'objectClass' and 'ref' mappings\n",
+			0, 0, 0 );
+		backsql_add_sysmaps( oc_map );
+		rc = SQLExecute( at_sth );
+		if ( rc != SQL_SUCCESS ) {
+			Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
+				"error executing at_query: \n", 0, 0, 0 );
+			backsql_PrintErrors( SQL_NULL_HENV, dbh, at_sth, rc );
+			return -1;
+		}
+
+		backsql_BindRowAsStrings( at_sth, &at_row );
+		rc = SQLFetch( at_sth );
+		for ( ; BACKSQL_SUCCESS(rc); rc = SQLFetch( at_sth ) ) {
+			Debug( LDAP_DEBUG_TRACE, "********'%s'\n",
+				at_row.cols[ 0 ], 0, 0 );
+			Debug( LDAP_DEBUG_TRACE, 
+				"name='%s',sel_expr='%s' from='%s'",
+				at_row.cols[ 0 ], at_row.cols[ 1 ],
+				at_row.cols[ 2 ] );
+			Debug( LDAP_DEBUG_TRACE, 
+				"join_where='%s',add_proc='%s'",
+				at_row.cols[ 3 ], at_row.cols[ 4 ], 0 );
+			Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n",
+					at_row.cols[ 5 ], 0, 0 );
+			/* TimesTen */
+			Debug( LDAP_DEBUG_TRACE, "sel_expr_u='%s'\n",
+					at_row.cols[ 8 ], 0, 0 );
+			at_map = (backsql_at_map_rec *)ch_calloc( 1,
+					sizeof( backsql_at_map_rec ) );
+			at_map->name = ch_strdup( at_row.cols[ 0 ] );
+			at_map->sel_expr = ch_strdup( at_row.cols[ 1 ] );
+			at_map->sel_expr_u = ( at_row.is_null[ 8 ] < 0 ) ? NULL
+				: ch_strdup( at_row.cols[ 8 ] );
+			tmps = NULL;
+			tmpslen = 0;
+			backsql_merge_from_clause( &tmps, &tmpslen,
+					at_row.cols[ 2 ] );
+			at_map->from_tbls = tmps;
+			at_map->join_where = ( at_row.is_null[ 3 ] < 0 ) ? NULL 
+				: ch_strdup( at_row.cols[ 3 ] );
+			at_map->add_proc = ( at_row.is_null[ 4 ] < 0 ) ? NULL
+				: ch_strdup( at_row.cols[4] );
+			at_map->delete_proc = ( at_row.is_null[ 5 ] < 0 ) ? NULL
+				: ch_strdup( at_row.cols[ 5 ] );
+			at_map->param_order = atoi( at_row.cols[ 6 ] );
+			at_map->expect_return = atoi( at_row.cols[ 7 ] );
+			backsql_make_attr_query( oc_map, at_map );
+			Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
+				"preconstructed query '%s'\n",
+				at_map->query, 0, 0 );
+			avl_insert( &oc_map->attrs, at_map, 
+					(AVL_CMP)backsql_cmp_attr,
+					backsql_dummy );
+		}
+		backsql_FreeRow( &at_row );
+		SQLFreeStmt( at_sth, SQL_CLOSE );
+	}
+	backsql_FreeRow( &oc_row );
+	SQLFreeStmt( at_sth, SQL_DROP );
+	SQLFreeStmt( oc_sth, SQL_DROP );
+	si->schema_loaded = 1;
+	Debug( LDAP_DEBUG_TRACE, "<==load_schema_map()\n", 0, 0, 0 );
+	return 1;
 }
 
-backsql_oc_map_rec* backsql_oc_with_name(backsql_info *si,char* objclass)
+backsql_oc_map_rec *
+backsql_oc_with_name( backsql_info *si, char *objclass )
 {
- backsql_oc_map_rec tmp,*res;
+	backsql_oc_map_rec	tmp, *res;
+
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "==>oc_with_name(): "
+		"searching for objectclass with name='%s'\n",
+		objclass, 0, 0 );
+#endif
+	
+	tmp.name = objclass;
+	res = (backsql_oc_map_rec *)avl_find( si->oc_by_name, &tmp,
+			(AVL_CMP)backsql_cmp_oc_name );
+#if 0
+	if ( res != NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
+			"found name='%s', id=%d\n", res->name, res->id, 0 );
+	} else {
+		Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
+			"not found\n", 0, 0, 0 );
+	}
+#endif
  
-/* Debug(LDAP_DEBUG_TRACE,"==>oc_with_name(): searching for objectclass with name='%s'\n",objclass,0,0);*/
- tmp.name=objclass;
- res=(backsql_oc_map_rec*)avl_find(si->oc_by_name,&tmp,(AVL_CMP)backsql_cmp_oc_name);
-/* if (res!=NULL)
-  Debug(LDAP_DEBUG_TRACE,"<==oc_with_name(): found name='%s', id=%d\n",res->name,res->id,0);
- else
-  Debug(LDAP_DEBUG_TRACE,"<==oc_with_name(): not found\n",0,0,0);
-*/
- return res;
+	return res;
 }
 
-backsql_oc_map_rec* backsql_oc_with_id(backsql_info *si,unsigned long id)
+backsql_oc_map_rec *
+backsql_oc_with_id( backsql_info *si, unsigned long id )
 {
- backsql_oc_map_rec tmp,*res;
+	backsql_oc_map_rec	tmp, *res;
  
-/* Debug(LDAP_DEBUG_TRACE,"==>oc_with_id(): searching for objectclass with id='%d'\n",id,0,0);*/
- tmp.id=id;
- res=(backsql_oc_map_rec*)avl_find(si->oc_by_id,&tmp,(AVL_CMP)backsql_cmp_oc_id);
-/* if (res!=NULL)
-  Debug(LDAP_DEBUG_TRACE,"<==oc_with_name(): found name='%s', id=%d\n",res->name,res->id,0);
- else
-  Debug(LDAP_DEBUG_TRACE,"<==oc_with_name(): not found\n",0,0,0);
-*/
- return res;
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "==>oc_with_id(): "
+		"searching for objectclass with id='%d'\n", id, 0, 0 );
+#endif
+
+	tmp.id = id;
+	res = (backsql_oc_map_rec *)avl_find( si->oc_by_id, &tmp,
+			(AVL_CMP)backsql_cmp_oc_id );
+
+#if 0
+	if ( res != NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
+			"found name='%s', id=%d\n", res->name, res->id, 0 );
+	} else {
+		Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
+			"not found\n", 0, 0, 0 );
+	}
+#endif
+	
+	return res;
 }
 
-backsql_at_map_rec* backsql_at_with_name(backsql_oc_map_rec* objclass,char* attr)
+backsql_at_map_rec *
+backsql_at_with_name( backsql_oc_map_rec* objclass, char *attr )
 {
- backsql_at_map_rec tmp,*res;
+	backsql_at_map_rec	tmp, *res;
  
- /*Debug(LDAP_DEBUG_TRACE,"==>at_with_name(): searching for attribute with name='%s' (for objectclass '%s')\n",
-                 attr,objclass->name,0);
-*/
- tmp.name=attr;
- res=(backsql_at_map_rec*)avl_find(objclass->attrs,&tmp,(AVL_CMP)backsql_cmp_attr);
- /*if (res!=NULL)
-  Debug(LDAP_DEBUG_TRACE,"<==at_with_name(): found name='%s', sel_expr='%s'\n",
-              res->name,res->sel_expr,0);
- else
-  Debug(LDAP_DEBUG_TRACE,"<==at_with_name(): not found\n",0,0,0);
-*/
- return res;
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "==>at_with_name(): "
+		"searching for attribute '%s' for objectclass '%s'\n",
+		attr, objclass->name, 0 );
+#endif
+	tmp.name = attr;
+	res = (backsql_at_map_rec *)avl_find( objclass->attrs, &tmp,
+			(AVL_CMP)backsql_cmp_attr );
+
+#if 0
+	if ( res != NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "<==at_with_name(): "
+			"found name='%s', sel_expr='%s'\n",
+			res->name, res->sel_expr, 0 );
+	} else {
+		Debug( LDAP_DEBUG_TRACE, "<==at_with_name(): "
+			"not found\n", 0, 0, 0 );
+	}
+#endif
+
+	return res;
 }
 
-int backsql_free_attr(backsql_at_map_rec *at)
+int
+backsql_free_attr( backsql_at_map_rec *at )
 {
- Debug(LDAP_DEBUG_TRACE,"==>free_attr(): '%s'\n",at->name,0,0);
- ch_free(at->name);
- ch_free(at->sel_expr);
- if (at->from_tbls!=NULL)
-  ch_free(at->from_tbls);
- if (at->join_where!=NULL)
-  ch_free(at->join_where);
- if (at->add_proc!=NULL)
-  ch_free(at->add_proc);
- if (at->delete_proc!=NULL)
-  ch_free(at->delete_proc);
- if (at->query)
-  ch_free(at->query);
- ch_free(at);
- if (at->sel_expr_u)
-   ch_free(at->sel_expr_u); /* TimesTen */
- Debug(LDAP_DEBUG_TRACE,"<==free_attr()\n",0,0,0);
- return 1;
+	Debug( LDAP_DEBUG_TRACE, "==>free_attr(): '%s'\n", at->name, 0, 0 );
+	ch_free( at->name );
+	ch_free( at->sel_expr );
+	if ( at->from_tbls != NULL ) {
+		ch_free( at->from_tbls );
+	}
+	if ( at->join_where != NULL ) {
+		ch_free( at->join_where );
+	}
+	if ( at->add_proc != NULL ) {
+		ch_free( at->add_proc );
+	}
+	if ( at->delete_proc != NULL ) {
+		ch_free( at->delete_proc );
+	}
+	if ( at->query ) {
+		ch_free( at->query );
+	}
+	ch_free( at );
+
+	/* TimesTen */
+	if ( at->sel_expr_u ) {
+		ch_free( at->sel_expr_u );
+	}
+	
+	Debug( LDAP_DEBUG_TRACE, "<==free_attr()\n", 0, 0, 0 );
+
+	return 1;
 }
 
-int backsql_free_oc(backsql_oc_map_rec *oc)
+int
+backsql_free_oc( backsql_oc_map_rec *oc )
 {
- Debug(LDAP_DEBUG_TRACE,"==>free_oc(): '%s'\n",oc->name,0,0);
- avl_free(oc->attrs,(AVL_FREE)backsql_free_attr);
- ch_free(oc->name);
- ch_free(oc->keytbl);
- ch_free(oc->keycol);
- if (oc->create_proc!=NULL)
-  ch_free(oc->create_proc);
- if (oc->delete_proc!=NULL)
-  ch_free(oc->delete_proc);
- ch_free(oc);
- Debug(LDAP_DEBUG_TRACE,"<==free_oc()\n",0,0,0);
- return 1;
+	Debug( LDAP_DEBUG_TRACE, "==>free_oc(): '%s'\n", oc->name, 0, 0 );
+	avl_free( oc->attrs, (AVL_FREE)backsql_free_attr );
+	ch_free( oc->name );
+	ch_free( oc->keytbl );
+	ch_free( oc->keycol );
+	if ( oc->create_proc != NULL ) {
+		ch_free( oc->create_proc );
+	}
+	if ( oc->delete_proc != NULL ) {
+		ch_free( oc->delete_proc );
+	}
+	ch_free( oc );
+
+	Debug( LDAP_DEBUG_TRACE, "<==free_oc()\n", 0, 0, 0 );
+	return 1;
 }
 
-int backsql_destroy_schema_map(backsql_info *si)
+int
+backsql_destroy_schema_map( backsql_info *si )
 {
- Debug(LDAP_DEBUG_TRACE,"==>destroy_schema_map()\n",0,0,0);
- avl_free(si->oc_by_id,(AVL_FREE)backsql_free_oc);
- avl_free(si->oc_by_name,(AVL_FREE)backsql_dummy);
- Debug(LDAP_DEBUG_TRACE,"<==destroy_schema_map()\n",0,0,0);
- return 0;
+	Debug( LDAP_DEBUG_TRACE, "==>destroy_schema_map()\n", 0, 0, 0 );
+	avl_free( si->oc_by_id, (AVL_FREE)backsql_free_oc );
+	avl_free( si->oc_by_name, (AVL_FREE)backsql_dummy );
+	Debug( LDAP_DEBUG_TRACE, "<==destroy_schema_map()\n", 0, 0, 0 );
+	return 0;
 }
 
 #endif /* SLAPD_SQL */
+
diff --git a/servers/slapd/back-sql/schema-map.h b/servers/slapd/back-sql/schema-map.h
index f2fc02bbfa..7747f59b94 100644
--- a/servers/slapd/back-sql/schema-map.h
+++ b/servers/slapd/back-sql/schema-map.h
@@ -11,42 +11,60 @@
  */
 
 
-typedef struct
-{
- char *name;
- char *keytbl;
- char *keycol;
- char *create_proc; /*expected to return keyval of newly created entry*/
- char *delete_proc;/*supposed to expect keyval as parameter and delete all the attributes as well*/
- int expect_return; /*flags whether delete_proc is a function (whether back-sql should bind first parameter as output for return code)*/
- unsigned long id;
- Avlnode *attrs;
-}backsql_oc_map_rec;
-
-typedef struct
-{
- char *name;/*literal name of corresponding LDAP attribute type*/
- char *from_tbls;
- char *join_where;
- char *sel_expr;
- char *add_proc; /*supposed to expect 2 binded values: entry keyval and attr. value to add, like "add_name(?,?,?)"*/
- char *delete_proc; /*supposed to expect 2 binded values: entry keyval and attr. value to delete*/
- char *query; /*for optimization purposes attribute load query is preconstructed from parts on schemamap load time*/
- /*following flags are bitmasks (first bit used for add_proc, second - for modify, third - for delete_proc)*/
- int param_order; /*order of parameters for procedures above; 1 means "data then keyval", 0 means "keyval then data"*/
- int expect_return; /*flags whether one or more of procedures is a function (whether back-sql should bind first parameter as output for return code)*/
- char *sel_expr_u; /* TimesTen */
-}backsql_at_map_rec;
-
-/*defines to support bitmasks above*/
+typedef struct {
+	char		*name;
+	char		*keytbl;
+	char		*keycol;
+	/* expected to return keyval of newly created entry */
+	char		*create_proc;
+	/* supposed to expect keyval as parameter and delete 
+	 * all the attributes as well */
+	char		*delete_proc;
+	/* flags whether delete_proc is a function (whether back-sql 
+	 * should bind first parameter as output for return code) */
+	int		expect_return;
+	unsigned long	id;
+	Avlnode		*attrs;
+} backsql_oc_map_rec;
+
+typedef struct {
+	/* literal name of corresponding LDAP attribute type */
+	char		*name;
+	char		*from_tbls;
+	char		*join_where;
+	char		*sel_expr;
+	/* supposed to expect 2 binded values: entry keyval 
+	 * and attr. value to add, like "add_name(?,?,?)" */
+	char		*add_proc;
+	/* supposed to expect 2 binded values: entry keyval 
+	 * and attr. value to delete */
+	char		*delete_proc;
+	/* for optimization purposes attribute load query 
+	 * is preconstructed from parts on schemamap load time */
+	char		*query;
+	/* following flags are bitmasks (first bit used for add_proc, 
+	 * second - for modify, third - for delete_proc) */
+	/* order of parameters for procedures above; 
+	 * 1 means "data then keyval", 0 means "keyval then data" */
+	int 		param_order;
+	/* flags whether one or more of procedures is a function 
+	 * (whether back-sql should bind first parameter as output 
+	 * for return code) */
+	int 		expect_return;
+	/* TimesTen */
+	char		*sel_expr_u;
+} backsql_at_map_rec;
+
+/* defines to support bitmasks above */
 #define BACKSQL_ADD	1
 #define BACKSQL_DEL	2
 
-int backsql_load_schema_map(backsql_info *si,SQLHDBC dbh);
-backsql_oc_map_rec* backsql_oc_with_name(backsql_info *si,char* objclass);
-backsql_oc_map_rec* backsql_oc_with_id(backsql_info *si,unsigned long id);
-backsql_at_map_rec* backsql_at_with_name(backsql_oc_map_rec* objclass,char* attr);
-int backsql_destroy_schema_map(backsql_info *si);
+int backsql_load_schema_map( backsql_info *si, SQLHDBC dbh );
+backsql_oc_map_rec *backsql_oc_with_name( backsql_info *si, char *objclass );
+backsql_oc_map_rec *backsql_oc_with_id( backsql_info *si, unsigned long id );
+backsql_at_map_rec *backsql_at_with_name( backsql_oc_map_rec *objclass,
+		char *attr );
+int backsql_destroy_schema_map( backsql_info *si );
 
-#endif
+#endif /* __BACKSQL_SCHEMA_MAP_H__ */
 
diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c
index 2dca484832..dff51d5d28 100644
--- a/servers/slapd/back-sql/search.c
+++ b/servers/slapd/back-sql/search.c
@@ -13,637 +13,949 @@
 
 #include <stdio.h>
 #include <sys/types.h>
-#include <string.h>
+#include "ac/string.h"
 #include "slap.h"
+#include "lber_pvt.h"
+#include "ldap_pvt.h"
 #include "back-sql.h"
 #include "sql-wrap.h"
 #include "schema-map.h"
 #include "entry-id.h"
 #include "util.h"
 
-int backsql_attrlist_add(backsql_srch_info *bsi,char *at_name)
+static struct berval AllUser = BER_BVC( LDAP_ALL_USER_ATTRIBUTES );
+static struct berval AllOper = BER_BVC( LDAP_ALL_OPERATIONAL_ATTRIBUTES );
+#if 0
+static struct berval NoAttrs = BER_BVC( LDAP_NO_ATTRS );
+#endif
+
+static int
+backsql_attrlist_add( backsql_srch_info *bsi, struct berval *at_name )
 {
- char **p=bsi->attrs;
- int n_attrs=0;
-
- if (bsi->attrs==NULL)
-  return 1;
-
- while(*p)
- {
-  Debug(LDAP_DEBUG_TRACE,"==>backsql_attrlist_add(): attribute '%s' is in list\n",*p,0,0);
-  if (!strcasecmp(*p,at_name))
-   return 1;
-  n_attrs++;
-  p++;
- }
- Debug(LDAP_DEBUG_TRACE,"==>backsql_attrlist_add(): adding '%s' to list\n",at_name,0,0);
- bsi->attrs=(char**)ch_realloc(bsi->attrs,(n_attrs+2)*sizeof(char*));
- bsi->attrs[n_attrs]=ch_strdup(at_name);
- bsi->attrs[n_attrs+1]=NULL;
- return 1;
+	int 	n_attrs = 0;
+	char	**tmp;
+
+	if ( bsi->attrs == NULL ) {
+		return 1;
+	}
+
+	for ( ; bsi->attrs[ n_attrs ]; n_attrs++ ) {
+		Debug( LDAP_DEBUG_TRACE, "==>backsql_attrlist_add(): "
+			"attribute '%s' is in list\n", 
+			bsi->attrs[ n_attrs ], 0, 0 );
+		/*
+		 * We can live with strcmp because the attribute 
+		 * list has been normalized before calling be_search
+		 */
+		if ( !strcmp( bsi->attrs[ n_attrs ], at_name->bv_val ) ) {
+			return 1;
+		}
+	}
+	
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_attrlist_add(): "
+		"adding '%s' to list\n", at_name->bv_val, 0, 0 );
+	tmp = (char **)ch_realloc( bsi->attrs, (n_attrs + 2)*sizeof( char * ) );
+	if ( tmp == NULL ) {
+		return -1;
+	}
+	bsi->attrs = tmp;
+	bsi->attrs[ n_attrs ] = ch_strdup( at_name->bv_val );
+	bsi->attrs[ n_attrs + 1 ] = NULL;
+	return 1;
 }
 
-void backsql_init_search(backsql_srch_info *bsi,backsql_info *bi,char *nbase,int scope,
-						 int slimit,int tlimit,time_t stoptime,Filter *filter,
-						 SQLHDBC dbh,BackendDB *be,Connection *conn,Operation *op,AttributeName *attrs)
+void
+backsql_init_search(
+	backsql_srch_info 	*bsi, 
+	backsql_info 		*bi,
+	struct berval		*nbase, 
+	int 			scope, 
+	int 			slimit,
+	int 			tlimit,
+	time_t 			stoptime, 
+	Filter 			*filter, 
+	SQLHDBC 		dbh,
+	BackendDB 		*be, 
+	Connection 		*conn, 
+	Operation 		*op,
+	AttributeName 		*attrs )
 {
- AttributeName *p;
- bsi->base_dn=nbase;
- bsi->scope=scope;
- bsi->slimit=slimit;
- bsi->tlimit=tlimit;
- bsi->filter=filter;
- bsi->dbh=dbh;
- bsi->be=be;
- bsi->conn=conn;
- bsi->op=op;
- if (attrs!=NULL)
- {
-  bsi->attrs=(char**)ch_calloc(1,sizeof(char*));
-  bsi->attrs[0]=NULL;
-  for(p=attrs;p->an_name.bv_val;p++)
-   backsql_attrlist_add(bsi,p->an_name.bv_val);
- }
- else
-  bsi->attrs=NULL;
- bsi->abandon=0;
- bsi->id_list=NULL;
- bsi->stoptime=stoptime;
- bsi->bi=bi;
- bsi->sel=NULL; bsi->from=NULL; bsi->join_where=NULL; bsi->flt_where=NULL;
- bsi->sel_len=0; bsi->from_len=0; bsi->jwhere_len=0; bsi->fwhere_len=0;
+	AttributeName		*p;
+	
+	bsi->base_dn = nbase;
+	bsi->scope = scope;
+	bsi->slimit = slimit;
+	bsi->tlimit = tlimit;
+	bsi->filter = filter;
+	bsi->dbh = dbh;
+	bsi->be = be;
+	bsi->conn = conn;
+	bsi->op = op;
+
+	/*
+	 * FIXME: need to discover how to deal with 1.1 (NoAttrs)
+	 */
+	
+	/*
+	 * handle "*"
+	 */
+	if ( attrs == NULL || an_find( attrs, &AllUser ) ) {
+		bsi->attrs = NULL;
+
+	} else {
+		bsi->attrs = (char **)ch_calloc( 1, sizeof( char * ) );
+		bsi->attrs[ 0 ] = NULL;
+		
+		for ( p = attrs; p->an_name.bv_val; p++ ) {
+			/*
+			 * ignore "+"
+			 */
+			if ( strcmp( p->an_name.bv_val, AllOper.bv_val ) == 0 ) {
+				continue;
+			}
+			backsql_attrlist_add( bsi, &p->an_name );
+		}
+	}
+
+	bsi->abandon = 0;
+	bsi->id_list = NULL;
+	bsi->n_candidates = 0;
+	bsi->stoptime = stoptime;
+	bsi->bi = bi;
+	bsi->sel.bv_val = NULL;
+	bsi->sel.bv_len = 0;
+	bsi->sel_len = 0;
+	bsi->from.bv_val = NULL;
+	bsi->from.bv_len = 0;
+	bsi->from_len = 0;
+	bsi->join_where.bv_val = NULL;
+	bsi->join_where.bv_len = 0;
+	bsi->jwhere_len = 0;
+	bsi->flt_where.bv_val = NULL;
+	bsi->flt_where.bv_len = 0;
+	bsi->fwhere_len = 0;
+
+	bsi->status = LDAP_SUCCESS;
 }
 
-int backsql_process_filter_list(backsql_srch_info *bsi,Filter *f,int op)
+int
+backsql_process_filter_list( backsql_srch_info *bsi, Filter *f, int op )
 {
- char *sub_clause=NULL;
- int len=0,res;
-
- if (!f)
-  return 0;
- bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,"(",NULL);
- while(1)
- {
-  res=backsql_process_filter(bsi,f);
-  if (res < 0)
-    return -1;    /* TimesTen : If the query has no answers,
-                   don't bother to run the query. */
+	int		res;
+
+	if ( !f ) {
+		return 0;
+	}
+	
+	backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, "(", NULL );
+
+	while ( 1 ) {
+		res = backsql_process_filter( bsi, f );
+		if ( res < 0 ) {
+			/*
+			 * TimesTen : If the query has no answers,
+			 * don't bother to run the query.
+			 */
+			return -1;
+		}
  
-  f=f->f_next;
-  if (f==NULL)
-   break;
-
-  switch (op)
-  {
-   case LDAP_FILTER_AND:
-			bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len," AND ",NULL);
+		f = f->f_next;
+		if ( f == NULL ) {
+			break;
+		}
+
+		switch ( op ) {
+		case LDAP_FILTER_AND:
+			backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, 
+					" AND ", NULL );
 			break;
-   case LDAP_FILTER_OR:
-			bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len," OR ",NULL);
+
+		case LDAP_FILTER_OR:
+			backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, 
+					" OR ", NULL );
 			break;
-  }
- }
+		}
+	}
 
- 
- bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,")",NULL);
- return 1;
+	backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, /* ( */ ")", NULL );
+
+	return 1;
 }
 
-int backsql_process_sub_filter(backsql_srch_info *bsi,Filter *f)
+int
+backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f )
 {
- int i;
- backsql_at_map_rec *at=backsql_at_with_name(bsi->oc,f->f_sub_desc->ad_cname.bv_val);
+	int			i;
+	backsql_at_map_rec	*at;
+
+	if ( !f ) {
+		return 0;
+	}
+
+	at = backsql_at_with_name( bsi->oc, f->f_sub_desc->ad_cname.bv_val );
+
+	backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, "(" /* ) */ , NULL );
+
+	/* TimesTen */
+	Debug( LDAP_DEBUG_TRACE, "expr: '%s' '%s'\n", at->sel_expr,
+		at->sel_expr_u ? at->sel_expr_u : "<NULL>", 0 );
+	if ( bsi->bi->upper_func ) {
+		/*
+		 * If a pre-upper-cased version of the column exists, use it
+		 */
+		if ( at->sel_expr_u ) {
+			backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
+					at->sel_expr_u, " LIKE '", NULL);
+   		} else {
+			backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, 
+					bsi->bi->upper_func,
+					"(", at->sel_expr, ")", 
+					" LIKE '", NULL );
+		}
+	} else {
+		backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
+				at->sel_expr, " LIKE '", NULL );
+	}
  
- if (!f)
-  return 0;
-
- bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,"(",NULL);
- /* TimesTen*/
- Debug(LDAP_DEBUG_TRACE,"expr: '%s' '%s'\n",at->sel_expr,
-       at->sel_expr_u?at->sel_expr_u:"<NULL>",0);
- if (bsi->bi->upper_func)
- {
-   /* If a pre-upper-cased version of the column exists, use it. */
-   if (at->sel_expr_u) {
-     bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,
-                   at->sel_expr_u," LIKE '",NULL);
-   }
-   else {
-      bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,
-	     bsi->bi->upper_func,"(",at->sel_expr,")",
-		 " LIKE '",NULL);
-   }
- }
- else
- {
-  bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,at->sel_expr,
-				" LIKE '",NULL);
- }
- if (f->f_sub_initial!=NULL)
- {
-  if (bsi->bi->upper_func)
-   {
-    bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,ldap_pvt_str2upper(f->f_sub_initial->bv_val),NULL);
-   }
-   else
-    bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,f->f_sub_initial->bv_val,NULL);
- }
-
- bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,"%",NULL);
-
- if (f->f_sub_any!=NULL)
-  for(i=0;f->f_sub_any[i]!=NULL;i++)
-  {
-   /*Debug(LDAP_DEBUG_TRACE,"==>backsql_process_sub_filter(): sub_any='%s'\n",f->f_sub_any[i]->bv_val,0,0);*/
-   if (bsi->bi->upper_func)
-   {
-    bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,ldap_pvt_str2upper(f->f_sub_any[i]->bv_val),"%",NULL);
-   }
-   else
-    bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,f->f_sub_any[i]->bv_val,"%",NULL);    
-  }
-
- if (f->f_sub_final!=NULL)
-  if (bsi->bi->upper_func)
-   {
-    bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,ldap_pvt_str2upper(f->f_sub_final->bv_val),NULL);
-   }
-   else
-    bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,f->f_sub_final->bv_val,NULL);
-
- bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,"')",NULL);
+	if ( f->f_sub_initial.bv_val != NULL ) {
+		size_t	start;
+
+		start = bsi->flt_where.bv_len;
+		backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
+				f->f_sub_initial.bv_val, NULL );
+		if ( bsi->bi->upper_func ) {
+			ldap_pvt_str2upper( &bsi->flt_where.bv_val[ start ] );
+		}
+	}
+
+	backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, "%", NULL );
+
+	if ( f->f_sub_any != NULL ) {
+		for ( i = 0; f->f_sub_any[ i ].bv_val != NULL; i++ ) {
+			size_t	start;
+
+#if 0
+			Debug( LDAP_DEBUG_TRACE, 
+				"==>backsql_process_sub_filter(): "
+				"sub_any='%s'\n", f->f_sub_any[ i ].bv_val,
+				0, 0 );
+#endif
+
+			start = bsi->flt_where.bv_len;
+			backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, 
+					f->f_sub_any[ i ].bv_val, "%", NULL );
+			if ( bsi->bi->upper_func) {
+				/*
+				 * Note: toupper('%') = '%'
+				 */
+				ldap_pvt_str2upper( &bsi->flt_where.bv_val[ start ] );
+			}
+		}
+
+		if ( f->f_sub_final.bv_val != NULL ) {
+			size_t	start;
+
+			start = bsi->flt_where.bv_len;
+    			backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
+					f->f_sub_final.bv_val, NULL);
+  			if ( bsi->bi->upper_func ) {
+				ldap_pvt_str2upper( &bsi->flt_where.bv_val[ start ] );
+			}
+		}
+	}
+
+	backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, /* ( */ "')", NULL );
  
- return 1;
+	return 1;
 }
 
-int backsql_process_filter(backsql_srch_info *bsi,Filter *f)
+int
+backsql_process_filter( backsql_srch_info *bsi, Filter *f )
 {
- backsql_at_map_rec *at;
- backsql_at_map_rec oc_attr={"objectClass","","",NULL,NULL,NULL,NULL};
- char *at_name=NULL;
- int done=0,len=0;
- int rc=0; /* TimesTen */
-
- Debug(LDAP_DEBUG_TRACE,"==>backsql_process_filter()\n",0,0,0);
- if (f==NULL || f->f_choice==SLAPD_FILTER_COMPUTED)
-  {
-   return 0;
-  }
-  
- switch(f->f_choice)
- {
-  case LDAP_FILTER_OR:
-			rc = backsql_process_filter_list(bsi,f->f_or,LDAP_FILTER_OR);
-			done=1;
-			break;
-  case LDAP_FILTER_AND:
-			rc = backsql_process_filter_list(bsi,f->f_and,LDAP_FILTER_AND);
-			done=1;
-			break;
-  case LDAP_FILTER_NOT:
-			bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,"NOT (",NULL);
-			rc = backsql_process_filter(bsi,f->f_not);
-			bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,")",NULL);
-			done=1;
-			break;
-  case LDAP_FILTER_PRESENT:
-			at_name=f->f_desc->ad_cname.bv_val;
-			break;
-  default:
-			 at_name=f->f_av_desc->ad_cname.bv_val;
-			break;
- }
+	backsql_at_map_rec	*at;
+	backsql_at_map_rec 	oc_attr 
+		= { "objectClass", "", "", NULL, NULL, NULL, NULL };
+	AttributeDescription	*ad = NULL;
+	int 			done = 0, len = 0;
+	/* TimesTen */
+	int			rc = 0;
+
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_process_filter()\n", 0, 0, 0 );
+	if ( f == NULL || f->f_choice == SLAPD_FILTER_COMPUTED ) {
+		return 0;
+	}
+
+	switch( f->f_choice ) {
+	case LDAP_FILTER_OR:
+		rc = backsql_process_filter_list( bsi, f->f_or, 
+				LDAP_FILTER_OR );
+		done = 1;
+		break;
+		
+	case LDAP_FILTER_AND:
+		rc = backsql_process_filter_list( bsi, f->f_and,
+				LDAP_FILTER_AND);
+		done = 1;
+		break;
+
+	case LDAP_FILTER_NOT:
+		backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, 
+				"NOT (", NULL );
+		rc = backsql_process_filter( bsi, f->f_not );
+		backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, ")", NULL );
+		done = 1;
+		break;
 
- if (rc == -1)
-   goto impossible;     /* TimesTen : Don't run the query */
+	case LDAP_FILTER_PRESENT:
+		ad = f->f_desc;
+		break;
+		
+	default:
+		ad = f->f_av_desc;
+		break;
+	}
+
+	if ( rc == -1 ) {
+		/* TimesTen : Don't run the query */
+		goto impossible;
+	}
  
- if (done)
-  goto done;
-
- if (strcasecmp(at_name,"objectclass"))
-  at=backsql_at_with_name(bsi->oc,at_name);
- else
- {
-  at=&oc_attr;
-  at->sel_expr=backsql_strcat(at->sel_expr,&len,"'",bsi->oc->name,"'",NULL);
- }
- if (at==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_process_filter(): attribute '%s' is not defined for objectclass '%s'\n",
-                      at_name,bsi->oc->name,0);
-  bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len," 1=0 ",NULL);
-  goto impossible;
- }
-			
- backsql_merge_from_clause(&bsi->from,&bsi->from_len,at->from_tbls);
- /*need to add this attribute to list of attrs to load, so that we could do test_filter() later*/
- backsql_attrlist_add(bsi,at_name);
+	if ( done ) {
+		goto done;
+	}
+
+	if ( strcasecmp( ad->ad_cname.bv_val, "objectclass" ) ) {
+		at = backsql_at_with_name( bsi->oc, ad->ad_cname.bv_val );
+
+	} else {
+		struct berval	bv;
+		
+		at = &oc_attr;
+
+		/*
+		 * FIXME: use berval for at->sel_expr ?
+		 */
+		bv.bv_val = at->sel_expr;
+		bv.bv_len = at->sel_expr ? strlen( at->sel_expr ) : 0;
+		backsql_strcat( &bv, &len, "'", bsi->oc->name, "'", NULL );
+		at->sel_expr = bv.bv_val;
+	}
+	if ( at == NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_process_filter(): "
+			"attribute '%s' is not defined for objectclass '%s'\n",
+			ad->ad_cname.bv_val, bsi->oc->name, 0 );
+		backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, 
+				" 1=0 ", NULL );
+		goto impossible;
+	}
+
+	backsql_merge_from_clause( &bsi->from.bv_val, &bsi->from_len, 
+			at->from_tbls );
+	/*
+	 * need to add this attribute to list of attrs to load,
+	 * so that we could do test_filter() later
+	 */
+	backsql_attrlist_add( bsi, &ad->ad_cname );
+
+	if ( at->join_where != NULL && strstr( bsi->join_where.bv_val, at->join_where ) == NULL ) {
+	       	backsql_strcat( &bsi->join_where, &bsi->jwhere_len, 
+				" AND ", at->join_where, NULL );
+	}
+
+#if 0	
+	if ( at != &oc_attr ) {
+		backsql_strcat( &bsi->sel, &bsi->sel_len,
+				",", at->sel_expr, " AS ", at->name, NULL );
+ 	}
+#endif
+
+	switch ( f->f_choice ) {
+	case LDAP_FILTER_EQUALITY:
+		/*
+		 * maybe we should check type of at->sel_expr here somehow,
+		 * to know whether upper_func is applicable, but for now
+		 * upper_func stuff is made for Oracle, where UPPER is
+		 * safely applicable to NUMBER etc.
+		 */
+		if ( bsi->bi->upper_func ) {
+			size_t	start;
+
+			if ( at->sel_expr_u ) {
+				backsql_strcat( &bsi->flt_where,
+						&bsi->fwhere_len, "(",
+						at->sel_expr_u, "='", NULL );
+			} else {
+				backsql_strcat( &bsi->flt_where,
+						&bsi->fwhere_len, "(",
+						bsi->bi->upper_func, "(",
+						at->sel_expr, ")='", NULL );
+			}
 
- if (at->join_where != NULL && strstr(bsi->join_where,at->join_where)==NULL)
-  bsi->join_where=backsql_strcat(bsi->join_where,&bsi->jwhere_len," AND ",at->join_where,NULL);
+			start = bsi->flt_where.bv_len;
 
- /*if (at!=&oc_attr)
-  bsi->sel=backsql_strcat(bsi->sel,&bsi->sel_len,",",at->sel_expr," AS ",at->name,NULL);
- */
+			backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, 
+					f->f_av_value.bv_val, "')", NULL );
 
- switch(f->f_choice)
- {
-  case LDAP_FILTER_EQUALITY:
-			/*maybe we should check type of at->sel_expr here somehow,
-			* to know whether upper_func is applicable, but for now
-			* upper_func stuff is made for Oracle, where UPPER is
-			* safely applicable to NUMBER etc.
-			*/
-			if (bsi->bi->upper_func) {
-				if (at->sel_expr_u)
-					bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,"(",
-                      at->sel_expr_u,"='",
-                      ldap_pvt_str2upper(f->f_av_value->bv_val),"')",
-                      NULL);
-      			else
-					bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,"(",
-					bsi->bi->upper_func,"(",at->sel_expr,")='",
-					ldap_pvt_str2upper(f->f_av_value->bv_val),"')",NULL);
-			}
-			else
-			 bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,"(",at->sel_expr,"='",
-							f->f_av_value->bv_val,"')",NULL);
+			ldap_pvt_str2upper( &bsi->flt_where.bv_val[ start ] );
 
-			break;
-  case LDAP_FILTER_GE:
-			bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,"(",at->sel_expr,">=",
-							f->f_av_value->bv_val,")",NULL);
+		} else {
+			backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, 
+					"(", at->sel_expr, "='",
+					f->f_av_value.bv_val, "')", NULL );
+		}
+		break;
 
-			break;
-  case LDAP_FILTER_LE:
-			bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,"(",at->sel_expr,"<=",
-							f->f_av_value->bv_val,")",NULL);
-			break;
-  case LDAP_FILTER_PRESENT:
-			bsi->flt_where=backsql_strcat(bsi->flt_where,&bsi->fwhere_len,"NOT (",at->sel_expr,
-						" IS NULL)",NULL);
-			break;
-  case LDAP_FILTER_SUBSTRINGS:
-			backsql_process_sub_filter(bsi,f);
-			break;
- }
+	case LDAP_FILTER_GE:
+		backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, 
+				"(", at->sel_expr, ">=", 
+				f->f_av_value.bv_val, ")", NULL );
+		break;
+		
+	case LDAP_FILTER_LE:
+		backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, 
+				"(", at->sel_expr, "<=", 
+				f->f_av_value.bv_val, ")", NULL );
+		break;
+
+	case LDAP_FILTER_PRESENT:
+		backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, 
+				"NOT (", at->sel_expr, " IS NULL)", NULL );
+		break;
+
+	case LDAP_FILTER_SUBSTRINGS:
+		backsql_process_sub_filter( bsi, f );
+		break;
+	}
 
 done:
- if (oc_attr.sel_expr!=NULL)
-  free(oc_attr.sel_expr);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_process_filter()\n",0,0,0);
- return 1;
+	if ( oc_attr.sel_expr != NULL ) {
+		free( oc_attr.sel_expr );
+	}
+	
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_process_filter()\n", 0, 0, 0 );
+	return 1;
 
 impossible:
- if (oc_attr.sel_expr!=NULL)
-  free(oc_attr.sel_expr);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_process_filter() returns -1\n",0,0,0);
- return -1;
-
+	if ( oc_attr.sel_expr != NULL ) {
+		free( oc_attr.sel_expr );
+	}
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_process_filter() returns -1\n",
+			0, 0, 0 );
+	return -1;
 }
 
-char* backsql_srch_query(backsql_srch_info *bsi)
+static int
+backsql_srch_query( backsql_srch_info *bsi, struct berval *query )
 {
- char *query=NULL;
- int q_len=0;
- int rc;
-
- Debug(LDAP_DEBUG_TRACE,"==>backsql_srch_query()\n",0,0,0);
- bsi->sel=NULL;
- bsi->from=NULL;
- bsi->join_where=NULL;
- bsi->flt_where=NULL;
- bsi->sel_len=bsi->from_len=bsi->jwhere_len=bsi->fwhere_len=0;
-
- bsi->sel=backsql_strcat(bsi->sel,&bsi->sel_len,
-				"SELECT DISTINCT ldap_entries.id,",bsi->oc->keytbl,".",bsi->oc->keycol,
-				", '",bsi->oc->name,"' AS objectClass",
-				", ldap_entries.dn AS dn",
-				NULL);
- bsi->from=backsql_strcat(bsi->from,&bsi->from_len," FROM ldap_entries,",bsi->oc->keytbl,NULL);
- bsi->join_where=backsql_strcat(bsi->join_where,&bsi->jwhere_len," WHERE ",
-	 bsi->oc->keytbl,".",bsi->oc->keycol,"=ldap_entries.keyval AND ",
-	 "ldap_entries.oc_map_id=? AND ",NULL);
-
- switch(bsi->scope)
- {
-  case LDAP_SCOPE_BASE:
-        if (bsi->bi->upper_func)
-		 {
-		  bsi->join_where=backsql_strcat(bsi->join_where,&bsi->jwhere_len,
-			 bsi->bi->upper_func,"(","ldap_entries.dn)=(?)",NULL);
-		 }
-		else
-		 {
-		  bsi->join_where=backsql_strcat(bsi->join_where,&bsi->jwhere_len,
-				"ldap_entries.dn=?",NULL);
-		 }
+	backsql_info	*bi = (backsql_info *)bsi->be->be_private;
+	int		q_len = 0;
+	int		rc;
+
+	assert( query );
+	query->bv_val = NULL;
+	query->bv_len = 0;
+
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_srch_query()\n", 0, 0, 0 );
+	bsi->sel.bv_val = NULL;
+	bsi->sel.bv_len = 0;
+	bsi->sel_len = 0;
+	bsi->from.bv_val = NULL;
+	bsi->from.bv_len = 0;
+	bsi->from_len = 0;
+	bsi->join_where.bv_val = NULL;
+	bsi->join_where.bv_len = 0;
+	bsi->jwhere_len = 0;
+	bsi->flt_where.bv_val = NULL;
+	bsi->flt_where.bv_len = 0;
+	bsi->fwhere_len = 0;
+#if 0
+	backsql_strcat( &bsi->sel, &bsi->sel_len,
+			"SELECT DISTINCT ldap_entries.id,", 
+			bsi->oc->keytbl, ".", bsi->oc->keycol,
+			",'", bsi->oc->name, "' AS objectClass",
+			",ldap_entries.dn AS dn", NULL );
+#endif
+	backsql_strcat( &bsi->sel, &bsi->sel_len,
+			"SELECT DISTINCT ldap_entries.id,", 
+			bsi->oc->keytbl, ".", bsi->oc->keycol, ",", NULL );
+	if ( bi->strcast_func ) {
+		backsql_strcat( &bsi->sel, &bsi->sel_len,
+				bi->strcast_func, 
+				"('", bsi->oc->name, "')", NULL );
+	} else {
+		backsql_strcat( &bsi->sel, &bsi->sel_len,
+				"'", bsi->oc->name, "'", NULL );
+	}
+	backsql_strcat( &bsi->sel, &bsi->sel_len,
+			" AS objectClass,ldap_entries.dn AS dn", NULL );
+
+	backsql_strcat( &bsi->from, &bsi->from_len,
+			" FROM ldap_entries,", bsi->oc->keytbl, NULL );
+	backsql_strcat( &bsi->join_where, &bsi->jwhere_len,
+			" WHERE ", bsi->oc->keytbl, ".", bsi->oc->keycol,
+			"=ldap_entries.keyval AND ",
+			"ldap_entries.oc_map_id=? AND ", NULL );
+
+	switch ( bsi->scope ) {
+	case LDAP_SCOPE_BASE:
+		if ( bsi->bi->upper_func ) {
+      			backsql_strcat( &bsi->join_where, &bsi->jwhere_len, 
+					bsi->bi->upper_func,
+					"(","ldap_entries.dn)=",
+					bsi->bi->upper_func, "(?)", NULL );
+		} else {
+			backsql_strcat( &bsi->join_where, &bsi->jwhere_len, 
+					"ldap_entries.dn=?", NULL );
+		}
 		break;
-  case LDAP_SCOPE_ONELEVEL:
-		bsi->join_where=backsql_strcat(bsi->join_where,&bsi->jwhere_len,
-				"ldap_entries.parent=?",NULL);
+		
+	case LDAP_SCOPE_ONELEVEL:
+		backsql_strcat( &bsi->join_where, &bsi->jwhere_len, 
+				"ldap_entries.parent=?", NULL );
 		break;
-  case LDAP_SCOPE_SUBTREE:
-		bsi->join_where=backsql_strcat(bsi->join_where,&bsi->jwhere_len,
-				bsi->bi->subtree_cond,NULL);
+
+	case LDAP_SCOPE_SUBTREE:
+		backsql_strcat( &bsi->join_where, &bsi->jwhere_len,
+				bsi->bi->subtree_cond, NULL );
 		break;
- }
-
- rc = backsql_process_filter(bsi, bsi->filter);
- if (rc>0) {
-  query=backsql_strcat(query,&q_len,bsi->sel,bsi->from,bsi->join_where," AND ",bsi->flt_where,NULL);
- }
- else if (rc < 0) {
-    /* Indicates that there's no possible way the filter matches
-      anything.  No need to issue the query. */
-
-   Debug(LDAP_DEBUG_TRACE,"<==backsql_srch_query() returns NULL\n",0,0,0);
-   free(query);
-   query = NULL;
- }
+
+	default:
+		assert( 0 );
+	}
+
+	rc = backsql_process_filter( bsi, bsi->filter );
+	if ( rc > 0 ) {
+		backsql_strcat( query, &q_len,
+				bsi->sel.bv_val, bsi->from.bv_val, 
+				bsi->join_where.bv_val,
+				" AND ", bsi->flt_where.bv_val, NULL );
+
+	} else if ( rc < 0 ) {
+		/* 
+		 * Indicates that there's no possible way the filter matches
+		 * anything.  No need to issue the query
+		 */
+		Debug( LDAP_DEBUG_TRACE,
+			"<==backsql_srch_query() returns NULL\n", 0, 0, 0 );
+		free( query->bv_val );
+		query->bv_val = NULL;
+	}
  
- free(bsi->sel);
- free(bsi->from);
- free(bsi->join_where);
- free(bsi->flt_where);
- bsi->sel_len=bsi->from_len=bsi->jwhere_len=bsi->fwhere_len=0;
- Debug(LDAP_DEBUG_TRACE,"<==backsql_srch_query()\n",0,0,0);
- return query;
+	free( bsi->sel.bv_val );
+	bsi->sel.bv_len = 0;
+	bsi->sel_len = 0;
+	free( bsi->from.bv_val );
+	bsi->from.bv_len = 0;
+	bsi->from_len = 0;
+	free( bsi->join_where.bv_val );
+	bsi->join_where.bv_len = 0;
+	bsi->jwhere_len = 0;
+	free( bsi->flt_where.bv_val );
+	bsi->flt_where.bv_len = 0;
+	bsi->fwhere_len = 0;
+	
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_srch_query()\n", 0, 0, 0 );
+	
+	return ( query->bv_val == NULL ? 1 : 0 );
 }
 
-int backsql_oc_get_candidates(backsql_oc_map_rec *oc,backsql_srch_info *bsi)
+int
+backsql_oc_get_candidates( backsql_oc_map_rec *oc, backsql_srch_info *bsi )
 {
- char *query=NULL;
- SQLHSTMT sth;
- RETCODE rc;
- backsql_entryID base_id,*res,*c_id;
- /*Entry *e;*/
- BACKSQL_ROW_NTS row;
- int i;
- int j;
- char temp_base_dn[BACKSQL_MAX_DN_LEN+1]; /* TimesTen*/
+	struct berval		query;
+	SQLHSTMT		sth;
+	RETCODE			rc;
+	backsql_entryID		base_id, *c_id;
+	int			res;
+#if 0
+	Entry			*e;
+#endif
+	BACKSQL_ROW_NTS		row;
+	int			i;
+	int			j;
+	/* TimesTen */
+	char			temp_base_dn[ BACKSQL_MAX_DN_LEN + 1 ];
  
- Debug(LDAP_DEBUG_TRACE,"==>backsql_oc_get_candidates(): oc='%s'\n",oc->name,0,0);
- bsi->oc=oc;
- query=backsql_srch_query(bsi);
- if (query==NULL)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_oc_get_candidates(): could not construct query for objectclass\n",0,0,0);
-  return 1;
- }
-
- Debug(LDAP_DEBUG_TRACE,"Constructed query: %s\n",query,0,0);
-
- if ((rc=backsql_Prepare(bsi->dbh,&sth,query,0)) != SQL_SUCCESS)
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_oc_get_candidates(): error preparing query\n",0,0,0);
-   backsql_PrintErrors(bsi->bi->db_env,bsi->dbh,sth,rc);
-   free(query);
-   return 1;
-  }
- free(query);
-
- if (backsql_BindParamID(sth,1,&bsi->oc->id) != SQL_SUCCESS)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_oc_get_candidates(): error binding objectclass id parameter\n",0,0,0);
-  return 1;
- }
- switch(bsi->scope)
- {
-  case LDAP_SCOPE_BASE:
-		if ((rc=backsql_BindParamStr(sth,2,bsi->base_dn,BACKSQL_MAX_DN_LEN)) != SQL_SUCCESS)
-		{
-         Debug(LDAP_DEBUG_TRACE,"backsql_oc_get_candidates(): error binding base_dn parameter\n",0,0,0);
-		 backsql_PrintErrors(bsi->bi->db_env,bsi->dbh,sth,rc);
-         return 1;
+	Debug(	LDAP_DEBUG_TRACE, "==>backsql_oc_get_candidates(): oc='%s'\n",
+			oc->name, 0, 0 );
+	bsi->oc = oc;
+	if ( backsql_srch_query( bsi, &query ) ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
+			"could not construct query for objectclass\n",
+			0, 0, 0 );
+		return 1;
+	}
+
+	Debug( LDAP_DEBUG_TRACE, "Constructed query: %s\n", 
+			query.bv_val, 0, 0 );
+
+	rc = backsql_Prepare( bsi->dbh, &sth, query.bv_val, 0 );
+	free( query.bv_val );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
+			"error preparing query\n", 0, 0, 0 );
+		backsql_PrintErrors( bsi->bi->db_env, bsi->dbh, sth, rc );
+		return 1;
+	}
+
+	if ( backsql_BindParamID( sth, 1, &bsi->oc->id ) != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
+			"error binding objectclass id parameter\n", 0, 0, 0 );
+		return 1;
+	}
+
+	switch ( bsi->scope ) {
+	case LDAP_SCOPE_BASE:
+		rc = backsql_BindParamStr( sth, 2, bsi->base_dn->bv_val,
+				BACKSQL_MAX_DN_LEN );
+		if ( rc != SQL_SUCCESS ) {
+         		Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
+				"error binding base_dn parameter\n", 0, 0, 0 );
+			backsql_PrintErrors( bsi->bi->db_env, bsi->dbh, 
+					sth, rc );
+			return 1;
 		}
 		break;
 
-  case LDAP_SCOPE_SUBTREE:
-    /* Sets the parameters for the SQL built earlier */
-    /* NOTE that all the databases could actually use the TimesTen version,
-       which would be cleaner and would also eliminate the need for the
-       subtree_cond line in the configuration file.  For now, I'm leaving
-       it the way it is, so non-TimesTen databases use the original code.
-       But at some point this should get cleaned up. */
-     /* If "dn" is being used, do a suffix search.
-     If "dn_ru" is being used, do a prefix search. */
-
-    if (bsi->bi->has_ldapinfo_dn_ru) {
-       temp_base_dn[0] = '\0';
-       for ((i=0, j=strlen(bsi->base_dn)-1); j >= 0; (i++, j--)) {
-         *(temp_base_dn+i) = toupper(*(bsi->base_dn+j));
-       }
-       *(temp_base_dn+i) = '%';
-       *(temp_base_dn+i+1) = '\0';
-    }
-    else {
-        strcpy(temp_base_dn, "%");
-        for (i = 0; *(bsi->base_dn+i); i++) {
-          *(temp_base_dn+i+1) = toupper(*(bsi->base_dn+i));
-        }
-        *(temp_base_dn+i+1) = '\0';
-    }
-    Debug(LDAP_DEBUG_TRACE, "dn '%s'\n", temp_base_dn, 0, 0);
-
-    if ((rc=backsql_BindParamStr(sth,2,temp_base_dn,BACKSQL_MAX_DN_LEN)) !=
-SQL_SUCCESS)
-    {
-         Debug(LDAP_DEBUG_TRACE,"backsql_oc_get_candidates(): error binding base_dn parameter (2)\n",0,0,0);
-         backsql_PrintErrors(bsi->bi->db_env,bsi->dbh,sth,rc);
-         return 1;
-    }
-	break;
-
-  case LDAP_SCOPE_ONELEVEL:
-		res=backsql_dn2id(bsi->bi,&base_id,bsi->dbh,bsi->base_dn);
-		if (res==NULL)
-		{
-		 Debug(LDAP_DEBUG_TRACE,"backsql_oc_get_candidates(): could not retrieve base_dn id - no such entry\n",0,0,0);
-		 bsi->status=LDAP_NO_SUCH_OBJECT;
-		 return 0;
+	case LDAP_SCOPE_SUBTREE:
+		/* 
+		 * Sets the parameters for the SQL built earlier
+		 * NOTE that all the databases could actually use 
+		 * the TimesTen version, which would be cleaner 
+		 * and would also eliminate the need for the
+		 * subtree_cond line in the configuration file.  
+		 * For now, I'm leaving it the way it is, 
+		 * so non-TimesTen databases use the original code.
+		 * But at some point this should get cleaned up.
+		 *
+		 * If "dn" is being used, do a suffix search.
+		 * If "dn_ru" is being used, do a prefix search.
+		 */
+		if ( bsi->bi->has_ldapinfo_dn_ru ) {
+			temp_base_dn[ 0 ] = '\0';
+			for ( i = 0, j = bsi->base_dn->bv_len - 1;
+					j >= 0; i++, j--) {
+				temp_base_dn[ i ] = bsi->base_dn->bv_val[ j ];
+			}
+			temp_base_dn[ i ] = '%';
+			temp_base_dn[ i + 1 ] = '\0';
+			ldap_pvt_str2upper( temp_base_dn );
+
+		} else {
+			temp_base_dn[ 0 ] = '%';
+			AC_MEMCPY( &temp_base_dn[ 1 ], bsi->base_dn->bv_val,
+				bsi->base_dn->bv_len + 1 );
+			ldap_pvt_str2upper( &temp_base_dn[ 1 ] );
+		}
+
+		Debug( LDAP_DEBUG_TRACE, "dn '%s'\n", temp_base_dn, 0, 0 );
+
+		rc = backsql_BindParamStr( sth, 2, temp_base_dn, 
+				BACKSQL_MAX_DN_LEN );
+		if ( rc != SQL_SUCCESS ) {
+			Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
+				"error binding base_dn parameter (2)\n",
+				0, 0, 0 );
+			backsql_PrintErrors( bsi->bi->db_env, bsi->dbh, 
+					sth, rc );
+			return 1;
 		}
-		if (backsql_BindParamID(sth,2,&base_id.id) != SQL_SUCCESS)
-		{
-		 Debug(LDAP_DEBUG_TRACE,"backsql_oc_get_candidates(): error binding base id parameter\n",0,0,0);
-		 free(base_id.dn);
-		 return 1;
-		}		
-		free(base_id.dn);
 		break;
- }
- 
- if ((rc=SQLExecute(sth)) != SQL_SUCCESS && rc!= SQL_SUCCESS_WITH_INFO)
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_oc_get_candidates(): error executing query\n",0,0,0);
-   backsql_PrintErrors(bsi->bi->db_env,bsi->dbh,sth,rc);
-   SQLFreeStmt(sth,SQL_DROP);
-   return 1;
-  }
-
- backsql_BindRowAsStrings(sth,&row);
- while ((rc=SQLFetch(sth)) == SQL_SUCCESS || rc==SQL_SUCCESS_WITH_INFO)
-  {
-   /*
-   e=(Entry*)ch_calloc(1,sizeof(Entry)); 
-   for (i=1;i<row.ncols;i++)
-    {
-     if (row.is_null[i]>0)
-      {
-       backsql_entry_addattr(e,row.col_names[i],row.cols[i],row.col_prec[i]);
-       Debug(LDAP_DEBUG_TRACE,"prec=%d\n",(int)row.col_prec[i],0,0);
-      }
-     else
-      Debug(LDAP_DEBUG_TRACE,"NULL value in this row for attribute '%s'\n",row.col_names[i],0,0);
-    }
-   */
-
-   c_id=(backsql_entryID*)ch_calloc(1,sizeof(backsql_entryID));
-   c_id->id=atoi(row.cols[0]);
-   c_id->keyval=atoi(row.cols[1]);
-   c_id->oc_id=bsi->oc->id;
-   c_id->dn=ch_strdup(row.cols[3]);
-   c_id->next=bsi->id_list;
-   bsi->id_list=c_id;
-   Debug(LDAP_DEBUG_TRACE,"backsql_oc_get_candidates(): added entry id=%d, keyval=%d dn='%s'\n",
-		c_id->id,c_id->keyval,row.cols[3]);
-  }
- backsql_FreeRow(&row);
- SQLFreeStmt(sth,SQL_DROP);
-
- Debug(LDAP_DEBUG_TRACE,"<==backsql_oc_get_candidates()\n",0,0,0);
- return 1;
+
+ 	case LDAP_SCOPE_ONELEVEL:
+		res = backsql_dn2id( bsi->bi, &base_id, 
+				bsi->dbh, bsi->base_dn );
+		if ( res != LDAP_SUCCESS ) {
+			Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
+				"could not retrieve base_dn id%s\n",
+				res == LDAP_NO_SUCH_OBJECT ? ": no such entry"
+				: "", 0, 0 );
+			bsi->status = res;
+			return 0;
+		}
+		
+		rc = backsql_BindParamID( sth, 2, &base_id.id );
+		backsql_free_entryID( &base_id, 0 );
+		if ( rc != SQL_SUCCESS ) {
+			Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
+				"error binding base id parameter\n", 0, 0, 0 );
+			return 1;
+		}
+		break;
+	}
+	
+	rc = SQLExecute( sth );
+	if ( !BACKSQL_SUCCESS( rc ) ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
+			"error executing query\n", 0, 0, 0 );
+		backsql_PrintErrors( bsi->bi->db_env, bsi->dbh, sth, rc );
+		SQLFreeStmt( sth, SQL_DROP );
+		return 1;
+	}
+
+	backsql_BindRowAsStrings( sth, &row );
+	rc = SQLFetch( sth );
+	for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
+#if 0
+		e = (Entry *)ch_calloc( 1, sizeof( Entry ) ); 
+		for ( i = 1; i < row.ncols; i++ ) {
+			if ( row.is_null[ i ] > 0 ) {
+				backsql_entry_addattr( e, row.col_names[ i ],
+						row.cols[ i ], 
+						row.col_prec[ i ] );
+				Debug( LDAP_DEBUG_TRACE, "prec=%d\n", 
+						(int)row.col_prec[ i ], 0, 0 );
+			} else {
+				Debug( LDAP_DEBUG_TRACE, 
+					"NULL value in this row "
+					"for attribute '%s'\n", 
+					row.col_names[ i ], 0, 0 );
+			}
+		}
+#endif
+
+		c_id = (backsql_entryID *)ch_calloc( 1, 
+				sizeof( backsql_entryID ) );
+		c_id->id = atoi( row.cols[ 0 ] );
+		c_id->keyval = atoi( row.cols[ 1 ] );
+		c_id->oc_id = bsi->oc->id;
+		ber_str2bv( row.cols[ 3 ], 0, 1, &c_id->dn );
+		c_id->next = bsi->id_list;
+		bsi->id_list = c_id;
+		bsi->n_candidates++;
+		Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
+			"added entry id=%ld, keyval=%ld dn='%s'\n",
+			c_id->id, c_id->keyval, row.cols[ 3 ] );
+	}
+	backsql_FreeRow( &row );
+	SQLFreeStmt( sth, SQL_DROP );
+
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_oc_get_candidates()\n", 0, 0, 0 );
+
+	return 1;
 }
 
-int backsql_search(BackendDB *be,Connection *conn,Operation *op,
-	const char *base, const char *nbase, int scope,int deref,int slimit,int tlimit,
-	Filter *filter, const char *filterstr,AttributeName *attrs,int attrsonly)
+int
+backsql_search(
+	BackendDB	*be,
+	Connection	*conn,
+	Operation	*op,
+	struct berval	*base,
+	struct berval	*nbase,
+	int		scope,
+	int		deref,
+	int		slimit,
+	int		tlimit,
+	Filter		*filter,
+	struct berval	*filterstr,
+	AttributeName	*attrs,
+	int		attrsonly )
 {
- backsql_info *bi=(backsql_info*)be->be_private;
- SQLHDBC dbh;
- int sres;
- int nentries;
- Entry *entry,*res;
- int manageDSAit = get_manageDSAit( op );
- struct berval **v2refs = NULL;
- time_t	stoptime;
- backsql_srch_info srch_info;
- backsql_entryID *eid=NULL;
-
- Debug(LDAP_DEBUG_TRACE,"==>backsql_search(): base='%s', filter='%s', scope=%d,",
-                     nbase,filterstr,scope);
- Debug(LDAP_DEBUG_TRACE," deref=%d, attrsonly=%d, attributes to load: %s\n",
-	 deref,attrsonly,attrs==NULL?"all":"custom list");
- dbh=backsql_get_db_conn(be,conn);
-
- if (!dbh)
- {
-  Debug(LDAP_DEBUG_TRACE,"backsql_search(): could not get connection handle - exiting\n",0,0,0);
-  send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
-  return 1;
- }
-
- /* TimesTen : Pass it along to the lower level routines */ 
- srch_info.isTimesTen = bi->isTimesTen; 
+	backsql_info		*bi = (backsql_info *)be->be_private;
+	SQLHDBC			dbh;
+	int			sres;
+	int			nentries;
+	Entry			*entry, *res;
+	int			manageDSAit = get_manageDSAit( op );
+	BerVarray		v2refs = NULL;
+	time_t			stoptime = 0;
+	backsql_srch_info	srch_info;
+	backsql_entryID		*eid = NULL;
+	struct slap_limits_set	*limit = NULL;
+	int			isroot = 0;
+
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_search(): "
+		"base='%s', filter='%s', scope=%d,", 
+		nbase->bv_val, filterstr->bv_val, scope );
+	Debug( LDAP_DEBUG_TRACE, " deref=%d, attrsonly=%d, "
+		"attributes to load: %s\n",
+		deref, attrsonly, attrs == NULL ? "all" : "custom list" );
+	dbh = backsql_get_db_conn( be, conn );
+
+	if ( !dbh ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
+			"could not get connection handle - exiting\n", 
+			0, 0, 0 );
+		send_ldap_result( conn, op, LDAP_OTHER, "",
+				"SQL-backend error", NULL, NULL );
+		return 1;
+	}
+
+	/* TimesTen : Pass it along to the lower level routines */ 
+	srch_info.isTimesTen = bi->isTimesTen; 
  
- if (tlimit == 0 && be_isroot(be,&op->o_ndn))
-  {
-   tlimit = -1;	/* allow root to set no limit */
-  } 
- else
-  {
-   tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
-		    be->be_timelimit : tlimit;
-   stoptime = op->o_time + tlimit;
-  }
-  
- if (slimit == 0 && be_isroot(be,&op->o_ndn))
-  {
-   slimit = -1;	/* allow root to set no limit */
-  }
- else
-  {
-   slimit = (slimit > be->be_sizelimit || slimit < 1) ?
-		    be->be_sizelimit : slimit;
-  }
-
- backsql_init_search(&srch_info,bi,(char*)nbase,scope,slimit,tlimit,stoptime,filter,dbh,
-		 be,conn,op,attrs);
-
- /*for each objectclass we try to construct query which gets IDs
-  *of entries matching LDAP query filter and scope (or at least candidates),
-  *and get the IDs
-*/
- avl_apply(bi->oc_by_name,(AVL_APPLY)backsql_oc_get_candidates,&srch_info,0,AVL_INORDER);
-	     
- nentries=0;
- /*now we load candidate entries (only those attrubutes mentioned in attrs and filter),
-  *test it against full filter and then send to client
-*/
- for(eid=srch_info.id_list;eid!=NULL;eid=eid->next)
-  {
-   /* check for abandon */
-   if (op->o_abandon)
-    {
-     break;
-    }
-
-   /* check time limit */
-   if ( tlimit != -1 && slap_get_time() > stoptime)
-    {
-	 send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
+	/* if not root, get appropriate limits */
+	if ( be_isroot( be, &op->o_ndn ) ) {
+		isroot = 1;
+	} else {
+		( void ) get_limits( be, &op->o_ndn, &limit );
+	}
+
+	/* The time/size limits come first because they require very little
+	 * effort, so there's no chance the candidates are selected and then 
+	 * the request is not honored only because of time/size constraints */
+
+	/* if no time limit requested, use soft limit (unless root!) */
+	if ( isroot ) {
+		if ( tlimit == 0 ) {
+			tlimit = -1;	/* allow root to set no limit */
+		}
+
+		if ( slimit == 0 ) {
+			slimit = -1;
+		}
+
+	} else {
+		/* if no limit is required, use soft limit */
+		if ( tlimit <= 0 ) {
+			tlimit = limit->lms_t_soft;
+
+		/* if requested limit higher than hard limit, abort */
+		} else if ( tlimit > limit->lms_t_hard ) {
+			/* no hard limit means use soft instead */
+			if ( limit->lms_t_hard == 0 && tlimit > limit->lms_t_soft ) {
+				tlimit = limit->lms_t_soft;
+
+			/* positive hard limit means abort */
+			} else if ( limit->lms_t_hard > 0 ) {
+				send_search_result( conn, op, 
+						LDAP_UNWILLING_TO_PERFORM,
+						NULL, NULL, NULL, NULL, 0 );
+				return 0;
+			}
+		
+			/* negative hard limit means no limit */
+		}
+		
+		/* if no limit is required, use soft limit */
+		if ( slimit <= 0 ) {
+			slimit = limit->lms_s_soft;
+
+		/* if requested limit higher than hard limit, abort */
+		} else if ( slimit > limit->lms_s_hard ) {
+			/* no hard limit means use soft instead */
+			if ( limit->lms_s_hard == 0 && slimit > limit->lms_s_soft ) {
+				slimit = limit->lms_s_soft;
+
+			/* positive hard limit means abort */
+			} else if ( limit->lms_s_hard > 0 ) {
+				send_search_result( conn, op, 
+						LDAP_UNWILLING_TO_PERFORM,
+						NULL, NULL, NULL, NULL, 0 );
+				return 0;
+			}
+			
+			/* negative hard limit means no limit */
+		}
+	}
+
+	/* compute it anyway; root does not use it */
+	stoptime = op->o_time + tlimit;
+
+	backsql_init_search( &srch_info, bi, nbase, scope,
+			slimit, tlimit, stoptime, filter, dbh,
+			be, conn, op, attrs );
+
+	/*
+	 * for each objectclass we try to construct query which gets IDs
+	 * of entries matching LDAP query filter and scope (or at least 
+	 * candidates), and get the IDs
+	 */
+	avl_apply( bi->oc_by_name, (AVL_APPLY)backsql_oc_get_candidates,
+			&srch_info, 0, AVL_INORDER );
+
+	if ( !isroot && limit->lms_s_unchecked != -1 ) {
+		if ( srch_info.n_candidates > limit->lms_s_unchecked ) {
+			send_search_result( conn, op,
+					LDAP_ADMINLIMIT_EXCEEDED,
+					NULL, NULL, NULL, NULL, 0 );
+			goto done;
+		}
+	}
+	
+	nentries = 0;
+	/*
+	 * now we load candidate entries (only those attributes 
+	 * mentioned in attrs and filter), test it against full filter 
+	 * and then send to client
+	 */
+	for ( eid = srch_info.id_list; eid != NULL; eid = eid->next ) {
+
+		/* check for abandon */
+		if ( op->o_abandon ) {
+			break;
+		}
+
+		/* check time limit */
+		if ( tlimit != -1 && slap_get_time() > stoptime ) {
+			send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
 				NULL, NULL, v2refs, NULL, nentries );
+			break;
+		}
+
+		Debug(LDAP_DEBUG_TRACE, "backsql_search(): loading data "
+			"for entry id=%ld, oc_id=%ld, keyval=%ld\n",
+			eid->id, eid->oc_id, eid->keyval );
+
+		entry = (Entry *)ch_calloc( sizeof( Entry ), 1 );
+		res = backsql_id2entry( &srch_info, entry, eid );
+		if ( res == NULL ) {
+			Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
+				"error in backsql_id2entry() "
+				"- skipping entry\n", 0, 0, 0 );
+			continue;
+		}
+
+		if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
+			is_entry_referral( entry ) ) {
+			BerVarray refs = get_entry_referrals( be, conn,
+					op, entry );
+
+			send_search_reference( be, conn, op, entry, refs, 
+					NULL, &v2refs );
+			ber_bvarray_free( refs );
+			continue;
+		}
+
+		if ( test_filter( be, conn, op, entry, filter ) 
+				== LDAP_COMPARE_TRUE ) {
+			sres = send_search_entry( be, conn, op, entry,
+					attrs, attrsonly, NULL );
+			if ( sres == -1 ) {
+				Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
+					"connection lost\n", 0, 0, 0 );
+				break;
+			}
+			nentries += !sres;					
+		}
+		entry_free( entry );
+
+		if ( slimit != -1 && nentries > slimit ) {
+			send_search_result( conn, op, LDAP_SIZELIMIT_EXCEEDED,
+				NULL, NULL, v2refs, NULL, nentries );
+			break;
+		}
      
-     break;
-    }
-     
-   Debug(LDAP_DEBUG_TRACE,"backsql_search(): loading data for entry id=%d, oc_id=%d, keyval=%d\n",
-               eid->id,eid->oc_id,eid->keyval);
-   
-   entry=(Entry *)ch_calloc(sizeof(Entry),1);
-   res=backsql_id2entry(&srch_info,entry,eid);
-   if (res==NULL)
-    {
-     Debug(LDAP_DEBUG_TRACE,"backsql_search(): error in backsql_id2entry() - skipping entry\n",0,0,0);
-     continue;
-    }
-
-   if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
-			is_entry_referral( entry ) )
-    {
-     struct berval **refs = get_entry_referrals(be,conn,op,entry);
-
-     send_search_reference( be, conn, op, entry, refs, scope, NULL, &v2refs );
-     ber_bvecfree( refs );
-     continue;
-    }
-
-   if (test_filter(be,conn,op,entry,filter)==LDAP_COMPARE_TRUE)
-    {
-     if ((sres=send_search_entry(be,conn,op,entry,attrs,attrsonly,NULL))==-1)
-      {
-       Debug(LDAP_DEBUG_TRACE,"backsql_search(): connection lost\n",0,0,0);
-       break;
-      }
-     nentries+=!sres;					
-    }
-   entry_free(entry);
-  }
-
- for(eid=srch_info.id_list;eid!=NULL;eid=backsql_free_entryID(eid));
-
- charray_free(srch_info.attrs);
-
- if (nentries>0)
-  send_search_result( conn, op,
-		v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
-		NULL, NULL, v2refs, NULL, nentries );
- else
-  send_ldap_result(conn,op,LDAP_NO_SUCH_OBJECT,NULL,NULL,NULL,0);
- 
- Debug(LDAP_DEBUG_TRACE,"<==backsql_search()\n",0,0,0);
- return 0;
+	}
+
+	if ( nentries > 0 ) {
+		send_search_result( conn, op,
+			v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+			NULL, NULL, v2refs, NULL, nentries );
+	} else {
+		send_ldap_result( conn, op, srch_info.status,
+				NULL, NULL, NULL, 0 );
+	}
+	
+done:;
+	for ( eid = srch_info.id_list; eid != NULL; 
+			eid = backsql_free_entryID( eid, 1 ) );
+
+	charray_free( srch_info.attrs );
+
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_search()\n", 0, 0, 0 );
+	return 0;
 }
 
 #endif /* SLAPD_SQL */
+
diff --git a/servers/slapd/back-sql/sql-types.h b/servers/slapd/back-sql/sql-types.h
index 36bb21c4b2..d20a363dad 100644
--- a/servers/slapd/back-sql/sql-types.h
+++ b/servers/slapd/back-sql/sql-types.h
@@ -13,14 +13,13 @@
 #include <sql.h>
 #include <sqlext.h>
 
-typedef struct
-{
- SWORD ncols;
- char** col_names;
- UDWORD *col_prec;
- char** cols;
- SQLINTEGER* is_null;
-}BACKSQL_ROW_NTS;
+typedef struct {
+	SWORD		ncols;
+	char		**col_names;
+	UDWORD		*col_prec;
+	char		**cols;
+	SQLINTEGER	*is_null;
+} BACKSQL_ROW_NTS;
 
-#endif
+#endif /* __BACKSQL_SQL_TYPES_H__ */
 
diff --git a/servers/slapd/back-sql/sql-wrap.c b/servers/slapd/back-sql/sql-wrap.c
index 8251b5a0c9..c549c99b7b 100644
--- a/servers/slapd/back-sql/sql-wrap.c
+++ b/servers/slapd/back-sql/sql-wrap.c
@@ -12,8 +12,9 @@
 #ifdef SLAPD_SQL
 
 #include <stdio.h>
-#include <string.h>
+#include "ac/string.h"
 #include <sys/types.h>
+#include "ldap_pvt.h"
 #include "slap.h"
 #include "back-sql.h"
 #include "sql-types.h"
@@ -22,326 +23,433 @@
 
 #define MAX_ATTR_LEN 16384
 
-typedef struct backsql_conn
-{
- int ldap_cid;
- SQLHDBC dbh;
-}backsql_db_conn;
+typedef struct backsql_conn {
+	int		ldap_cid;
+	SQLHDBC		dbh;
+} backsql_db_conn;
 
-int backsql_dummy(void *,void *);
+int backsql_dummy( void *, void * );
 
-void backsql_PrintErrors(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth,int rc)
+void
+backsql_PrintErrors( SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth, int rc )
 {
- SQLCHAR           msg[SQL_MAX_MESSAGE_LENGTH];    /* msg. buffer    */
- SQLCHAR           state[SQL_SQLSTATE_SIZE];       /* statement buf. */
- SDWORD        iSqlCode;                              /* return code    */
- SWORD       len=SQL_MAX_MESSAGE_LENGTH-1;                               /* return length  */
+	SQLCHAR	msg[SQL_MAX_MESSAGE_LENGTH];		/* msg. buffer    */
+	SQLCHAR	state[SQL_SQLSTATE_SIZE];		/* statement buf. */
+	SDWORD	iSqlCode;				/* return code    */
+	SWORD	len = SQL_MAX_MESSAGE_LENGTH - 1;	/* return length  */ 
 
- 
- Debug(LDAP_DEBUG_TRACE,"Return code: %d\n", rc,0,0);
-  
- while((rc=SQLError(henv,hdbc,sth,state,&iSqlCode,msg,
-             SQL_MAX_MESSAGE_LENGTH - 1, &len)) == SQL_SUCCESS
-	|| rc == SQL_SUCCESS_WITH_INFO
-       )
- {
-  Debug(LDAP_DEBUG_TRACE,"Native error code: %d\n",(int) iSqlCode,0,0);
-  Debug(LDAP_DEBUG_TRACE,"SQL engine state: %s\n", state,0,0);
-  Debug(LDAP_DEBUG_TRACE,"Message: %s\n",msg,0,0);
- }
+	Debug( LDAP_DEBUG_TRACE, "Return code: %d\n", rc, 0, 0 );
+
+
+	rc = SQLError( henv, hdbc, sth, state, &iSqlCode, msg,
+			SQL_MAX_MESSAGE_LENGTH - 1, &len );
+	for ( ; BACKSQL_SUCCESS( rc ); ) {
+		Debug( LDAP_DEBUG_TRACE, "Native error code: %d\n", 
+				(int)iSqlCode, 0, 0 );
+		Debug( LDAP_DEBUG_TRACE, "SQL engine state: %s\n", 
+				state, 0, 0 );
+		Debug( LDAP_DEBUG_TRACE, "Message: %s\n", msg, 0, 0 );
+		rc = SQLError( henv, hdbc, sth, state, &iSqlCode, msg,
+				SQL_MAX_MESSAGE_LENGTH - 1, &len );
+	}
 }
 
-RETCODE backsql_Prepare(SQLHDBC dbh,SQLHSTMT *sth,char* query,int timeout)
+RETCODE
+backsql_Prepare( SQLHDBC dbh, SQLHSTMT *sth, char *query, int timeout )
 {
- RETCODE rc;
- char drv_name[30];
- SWORD len;
- int i;
- 
- rc=SQLAllocStmt(dbh,sth);
- if (rc != SQL_SUCCESS)
-  return rc;
- 
- /*Debug(LDAP_DEBUG_TRACE,"==>_SQLPrepare()\n", 0,0,0);*/
- SQLGetInfo(dbh,SQL_DRIVER_NAME,drv_name,30,&len);
- /*Debug(LDAP_DEBUG_TRACE,"_SQLPrepare(): driver name='%s'\n", drv_name,0,0);*/
- if (!strncmp(ldap_pvt_str2upper(drv_name),"SQLSRV32.DLL",30))
-  {
-   /*stupid default result set in MS SQL Server does not support multiple active statements
-    *on the same connection -- so we are trying to make it not to use default result set...
-   */
-   Debug(LDAP_DEBUG_TRACE,"_SQLprepare(): enabling MS SQL Server default result set workaround\n", 0,0,0);
-   rc=SQLSetStmtOption(*sth,SQL_CONCURRENCY,SQL_CONCUR_ROWVER);
-   if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
-   {
-    Debug(LDAP_DEBUG_TRACE,"_SQLPrepare(): SQLSetStmtOption(SQL_CONCURRENCY,SQL_CONCUR_ROWVER) failed:\n", 0,0,0);
-    backsql_PrintErrors(SQL_NULL_HENV,dbh,sth,rc);
-   }
-  }
- if (timeout>0)
-  {
-   Debug(LDAP_DEBUG_TRACE,"_SQLprepare(): setting query timeout to %d sec.\n", timeout,0,0);
-   if ((rc=SQLSetStmtOption(*sth,SQL_QUERY_TIMEOUT,timeout)) != SQL_SUCCESS)
-    {
-     backsql_PrintErrors(SQL_NULL_HENV,dbh,sth,rc);
-    }
-  }
- 
- /*Debug(LDAP_DEBUG_TRACE,"<==_SQLPrepare() calling SQLPrepare()\n", 0,0,0);*/
- return SQLPrepare(*sth,query,SQL_NTS);
+	RETCODE		rc;
+	char		drv_name[ 30 ];
+	SWORD		len;
+
+	rc = SQLAllocStmt( dbh, sth );
+	if ( rc != SQL_SUCCESS ) {
+		return rc;
+	}
+
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "==>_SQLPrepare()\n", 0, 0, 0 );
+#endif
+
+	SQLGetInfo( dbh, SQL_DRIVER_NAME, drv_name, 30, &len );
+
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "_SQLPrepare(): driver name='%s'\n",
+			drv_name, 0, 0 );
+#endif
+	
+	if ( !strncmp( ldap_pvt_str2upper( drv_name ), "SQLSRV32.DLL", 30 ) ) {
+		/*
+		 * stupid default result set in MS SQL Server
+		 * does not support multiple active statements
+		 * on the same connection -- so we are trying 
+		 * to make it not to use default result set...
+		 */
+		Debug( LDAP_DEBUG_TRACE, "_SQLprepare(): "
+			"enabling MS SQL Server default result "
+			"set workaround\n", 0, 0, 0 );
+		rc = SQLSetStmtOption( *sth, SQL_CONCURRENCY, 
+				SQL_CONCUR_ROWVER );
+		if ( rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO ) {
+			Debug( LDAP_DEBUG_TRACE, "_SQLPrepare(): "
+				"SQLSetStmtOption(SQL_CONCURRENCY,SQL_CONCUR_ROWVER) failed:\n", 
+				0, 0, 0 );
+			backsql_PrintErrors( SQL_NULL_HENV, dbh, *sth, rc );
+		}
+	}
+
+	if ( timeout > 0 ) {
+		Debug( LDAP_DEBUG_TRACE, "_SQLprepare(): "
+			"setting query timeout to %d sec.\n", 
+			timeout, 0, 0 );
+		rc = SQLSetStmtOption( *sth, SQL_QUERY_TIMEOUT, timeout );
+		if ( rc != SQL_SUCCESS ) {
+			backsql_PrintErrors( SQL_NULL_HENV, dbh, *sth, rc );
+		}
+	}
+
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "<==_SQLPrepare() calling SQLPrepare()\n",
+			0, 0, 0 );
+#endif
+
+	return SQLPrepare( *sth, query, SQL_NTS );
 }
 
-RETCODE backsql_BindParamStr(SQLHSTMT sth,int par_ind,char *str,int maxlen)
+#if 0
+RETCODE
+backsql_BindParamStr( SQLHSTMT sth, int par_ind, char *str, int maxlen )
 {
- RETCODE rc;
- SQLINTEGER len=SQL_NTS;
- 
- rc=SQLBindParameter(sth,(SQLUSMALLINT)par_ind,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_VARCHAR,
-         (SQLUINTEGER)maxlen,0,(SQLPOINTER)str,(SQLUINTEGER)maxlen,NULL);
- return rc;
+	RETCODE		rc;
+
+	rc = SQLBindParameter( sth, (SQLUSMALLINT)par_ind, SQL_PARAM_INPUT,
+			SQL_C_CHAR, SQL_VARCHAR,
+         		(SQLUINTEGER)maxlen, 0, (SQLPOINTER)str,
+			(SQLUINTEGER)maxlen, NULL );
+	return rc;
 }
 
-RETCODE backsql_BindParamID(SQLHSTMT sth,int par_ind,unsigned long *id)
+RETCODE
+backsql_BindParamID( SQLHSTMT sth, int par_ind, unsigned long *id )
 {
- 
- return SQLBindParameter(sth,(SQLUSMALLINT)par_ind,SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,
-         0,0,(SQLPOINTER)id,0,(SQLINTEGER*)NULL);
+	return SQLBindParameter( sth, (SQLUSMALLINT)par_ind,
+			SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
+			0, 0, (SQLPOINTER)id, 0, (SQLINTEGER*)NULL );
 }
+#endif
 
-RETCODE backsql_BindRowAsStrings(SQLHSTMT sth,BACKSQL_ROW_NTS *row)
+RETCODE
+backsql_BindRowAsStrings( SQLHSTMT sth, BACKSQL_ROW_NTS *row )
 {
- RETCODE rc;
- SQLCHAR colname[64];
- SQLSMALLINT name_len,col_type,col_scale,col_null;
- UDWORD col_prec;
- int i;
- 
- if (row == NULL)
-  return SQL_ERROR;
- 
- /*Debug(LDAP_DEBUG_TRACE,"==> backsql_BindRowAsStrings()\n",0,0,0);*/
- rc=SQLNumResultCols(sth,&row->ncols);
- if (rc != SQL_SUCCESS)
- {
-  /*Debug(LDAP_DEBUG_TRACE,"_SQLBindRowAsStrings(): SQLNumResultCols() failed:\n",0,0,0);*/
-  backsql_PrintErrors(SQL_NULL_HENV,SQL_NULL_HDBC,sth,rc);
- }
- else
- {
-  /*Debug(LDAP_DEBUG_TRACE,"backsql_BindRowAsStrings: ncols=%d\n",(int)row->ncols,0,0);*/
-  row->col_names=(char**)ch_calloc(row->ncols,sizeof(char*));
-  row->cols=(char**)ch_calloc(row->ncols,sizeof(char*));
-  row->col_prec=(UDWORD*)ch_calloc(row->ncols,sizeof(UDWORD));
-  row->is_null=(SQLINTEGER*)ch_calloc(row->ncols,sizeof(SQLINTEGER));
-  for (i=1;i<=row->ncols;i++)
-  {
-   rc=SQLDescribeCol(sth,(SQLSMALLINT)i,&colname[0],(SQLUINTEGER)sizeof(colname)-1,&name_len,&col_type,
-          (UDWORD*) &col_prec,&col_scale,&col_null);
-   row->col_names[i-1]=ch_strdup(colname);
-   /*Debug(LDAP_DEBUG_TRACE,"backsql_BindRowAsStrings: col_name=%s, col_prec[%d]=%d\n",colname,(int)i,(int)col_prec);*/
-   if (col_type == SQL_LONGVARCHAR || col_type== SQL_LONGVARBINARY)
-   {
-	/*row->cols[i-1]=NULL;
-         *row->col_prec[i-1]=-1;
-	 *such fields must be handled in some other way since they return 2G 
-	 *as their precision (at least it does so with MS SQL Server w/native driver)
-	 *for now, we just set fixed precision for such fields - dirty hack, but...
-	 *no time to deal with SQLGetData()
-        */
-	col_prec=MAX_ATTR_LEN;
-	row->cols[i-1]=(char*)ch_calloc((col_prec+1),sizeof(char));
-    row->col_prec[i-1]=col_prec;
-	rc=SQLBindCol(sth,(SQLUSMALLINT)i,SQL_C_CHAR,(SQLPOINTER)row->cols[i-1],col_prec+1,
-			                               &row->is_null[i-1]);
-   }
-   else
-   {
-    row->cols[i-1]=(char*)ch_calloc((col_prec+1),sizeof(char));
-    row->col_prec[i-1]=col_prec;
-	rc=SQLBindCol(sth,(SQLUSMALLINT)i,SQL_C_CHAR,(SQLPOINTER)row->cols[i-1],col_prec+1,
-			                               &row->is_null[i-1]);
-   }
-  }
- }
- /*Debug(LDAP_DEBUG_TRACE,"<== backsql_BindRowAsStrings()\n",0,0,0);*/
- return rc;
+	RETCODE		rc;
+	SQLCHAR		colname[ 64 ];
+	SQLSMALLINT	name_len, col_type, col_scale, col_null;
+	UDWORD		col_prec;
+	int		i;
+
+	if ( row == NULL ) {
+		return SQL_ERROR;
+	}
+
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "==> backsql_BindRowAsStrings()\n", 0, 0, 0 );
+#endif
+	
+	rc = SQLNumResultCols( sth, &row->ncols );
+	if ( rc != SQL_SUCCESS ) {
+#if 0
+		Debug( LDAP_DEBUG_TRACE, "_SQLBindRowAsStrings(): "
+			"SQLNumResultCols() failed:\n", 0, 0, 0 );
+#endif
+		
+		backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC, sth, rc );
+	} else {
+#if 0
+		Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
+			"ncols=%d\n", (int)row->ncols, 0, 0 );
+#endif
+
+		row->col_names = (char **)ch_calloc( row->ncols, 
+				sizeof( char * ) );
+		row->cols = (char **)ch_calloc( row->ncols, sizeof( char * ) );
+		row->col_prec = (UDWORD *)ch_calloc( row->ncols,
+				sizeof( UDWORD ) );
+		row->is_null = (SQLINTEGER *)ch_calloc( row->ncols,
+				sizeof( SQLINTEGER ) );
+		for ( i = 1; i <= row->ncols; i++ ) {
+			rc = SQLDescribeCol( sth, (SQLSMALLINT)i, &colname[ 0 ],
+					(SQLUINTEGER)sizeof( colname ) - 1,
+					&name_len, &col_type,
+					&col_prec, &col_scale, &col_null );
+			row->col_names[ i - 1 ] = ch_strdup( colname );
+#if 0
+			Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
+				"col_name=%s, col_prec[%d]=%d\n",
+				colname, (int)i, (int)col_prec );
+#endif
+			if ( col_type == SQL_LONGVARCHAR 
+					|| col_type == SQL_LONGVARBINARY) {
+#if 0
+				row->cols[ i - 1 ] = NULL;
+				row->col_prec[ i - 1 ] = -1;
+
+				/*
+				 * such fields must be handled 
+				 * in some other way since they return 2G 
+				 * as their precision (at least it does so 
+				 * with MS SQL Server w/native driver)
+				 * for now, we just set fixed precision 
+				 * for such fields - dirty hack, but...
+				 * no time to deal with SQLGetData()
+				 */
+#endif
+				col_prec = MAX_ATTR_LEN;
+				row->cols[ i - 1 ] = (char *)ch_calloc( col_prec + 1, sizeof( char ) );
+				row->col_prec[ i - 1 ] = col_prec;
+				rc = SQLBindCol( sth, (SQLUSMALLINT)i,
+						SQL_C_CHAR,
+						(SQLPOINTER)row->cols[ i - 1 ],
+						col_prec + 1,
+						&row->is_null[ i - 1 ] );
+			} else {
+				row->cols[ i - 1 ] = (char *)ch_calloc( col_prec + 1, sizeof( char ) );
+				row->col_prec[ i - 1 ] = col_prec;
+				rc = SQLBindCol( sth, (SQLUSMALLINT)i,
+						SQL_C_CHAR,
+						(SQLPOINTER)row->cols[ i - 1 ],
+						col_prec + 1,
+						&row->is_null[ i - 1 ] );
+			}
+		}
+	}
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "<== backsql_BindRowAsStrings()\n", 0, 0, 0 );
+#endif
+
+	return rc;
 }
 
-RETCODE backsql_FreeRow(BACKSQL_ROW_NTS *row)
+RETCODE
+backsql_FreeRow( BACKSQL_ROW_NTS *row )
 {
- int i;
- 
- if (row->cols == NULL)
-  return SQL_ERROR;
- for(i=0;i<row->ncols;i++)
-  {
-   free(row->cols[i]);
-  }
- free(row->col_names);
- free(row->col_prec);
- free(row->cols);
- free(row->is_null);
- return SQL_SUCCESS;
+	int	i;
+
+	if ( row->cols == NULL ) {
+		return SQL_ERROR;
+	}
+
+	for ( i = 0; i < row->ncols; i++ ) {
+		/*
+		 * FIXME: we need to free the col_names as well, don't we?
+		 */
+		free( row->cols[ i ] );
+	}
+
+	free( row->col_names );
+	free( row->col_prec );
+	free( row->cols );
+	free( row->is_null );
+
+	return SQL_SUCCESS;
 }
 
-int backsql_cmp_connid(backsql_db_conn *c1,backsql_db_conn *c2)
+int
+backsql_cmp_connid( backsql_db_conn *c1, backsql_db_conn *c2 )
 {
- if (c1->ldap_cid > c2->ldap_cid)
-  return 1; 
- if (c1->ldap_cid < c2->ldap_cid)
-  return -1; 
- return 0;
+	if ( c1->ldap_cid > c2->ldap_cid ) {
+		return 1;
+	}
+	
+	if ( c1->ldap_cid < c2->ldap_cid ) {
+		return -1;
+	}
+	
+	return 0;
 }
 
-
-int backsql_close_db_conn(backsql_db_conn *conn)
+int
+backsql_close_db_conn( backsql_db_conn *conn )
 {
- Debug(LDAP_DEBUG_TRACE,"==>backsql_close_db_conn()\n",0,0,0);
- SQLTransact(NULL, conn->dbh, SQL_COMMIT);  /* TimesTen */
- SQLDisconnect(conn->dbh);
- SQLFreeConnect(conn->dbh);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_close_db_conn()\n",0,0,0);
- return 1;
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_close_db_conn()\n", 0, 0, 0 );
+
+	/* TimesTen */
+	SQLTransact( SQL_NULL_HENV, conn->dbh, SQL_COMMIT );
+	SQLDisconnect( conn->dbh );
+	SQLFreeConnect( conn->dbh );
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_close_db_conn()\n", 0, 0, 0 );
+	return 1;
 }
 
-int backsql_init_db_env(backsql_info *si)
+int
+backsql_init_db_env( backsql_info *si )
 {
- RETCODE rc;
- Debug(LDAP_DEBUG_TRACE,"==>backsql_init_db_env()\n",0,0,0);
- if ((rc=SQLAllocEnv(&si->db_env)) != SQL_SUCCESS)
-  {
-   Debug(LDAP_DEBUG_TRACE,"init_db_env: SQLAllocEnv failed:\n",0,0,0);
-   backsql_PrintErrors(SQL_NULL_HENV,SQL_NULL_HDBC,SQL_NULL_HENV,rc);
-  }
- Debug(LDAP_DEBUG_TRACE,"<==backsql_init_db_env()\n",0,0,0);
- return SQL_SUCCESS;
+	RETCODE		rc;
+	
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_init_db_env()\n", 0, 0, 0 );
+	rc = SQLAllocEnv( &si->db_env );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "init_db_env: SQLAllocEnv failed:\n",
+				0, 0, 0 );
+		backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC,
+				SQL_NULL_HENV, rc );
+	}
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_init_db_env()\n", 0, 0, 0 );
+	return SQL_SUCCESS;
 }
 
-int backsql_free_db_env(backsql_info *si)
+int
+backsql_free_db_env( backsql_info *si )
 {
- Debug(LDAP_DEBUG_TRACE,"==>backsql_free_db_env()\n",0,0,0);
- /*Debug(LDAP_DEBUG_TRACE,"free_db_env(): delete AVL tree here!!!\n",0,0,0);*/
- 
- /*stop, if frontend waits for all threads to shutdown before calling this --
-  *then what we are going to delete?? everything is deleted already...
-*/
- Debug(LDAP_DEBUG_TRACE,"<==backsql_free_db_env()\n",0,0,0);
- return SQL_SUCCESS;
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_free_db_env()\n", 0, 0, 0 );
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "free_db_env(): delete AVL tree here!!!\n",
+			0, 0, 0 );
+#endif
+
+	/*
+	 * stop, if frontend waits for all threads to shutdown 
+	 * before calling this -- then what are we going to delete?? 
+	 * everything is already deleted...
+	 */
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_free_db_env()\n", 0, 0, 0 );
+	return SQL_SUCCESS;
 }
 
-backsql_db_conn* backsql_open_db_conn(backsql_info *si,int ldap_cid)
+backsql_db_conn *
+backsql_open_db_conn( backsql_info *si, int ldap_cid )
 {
- char DBMSName[32]; /* TimesTen*/
-
- backsql_db_conn *dbc=(backsql_db_conn*)ch_calloc(1,sizeof(backsql_db_conn));
- int rc;
- 
- Debug(LDAP_DEBUG_TRACE,"==>backsql_open_db_conn()\n",0,0,0);
- dbc->ldap_cid=ldap_cid;
- if ((rc=SQLAllocConnect(si->db_env,&dbc->dbh)) != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_open_db_conn: SQLAllocConnect() failed:\n",0,0,0);
-   backsql_PrintErrors(si->db_env,SQL_NULL_HDBC,SQL_NULL_HENV,rc);
-   return NULL;
-  }
- if ((rc=SQLConnect(dbc->dbh,si->dbname,SQL_NTS,si->dbuser,SQL_NTS,
-                      si->dbpasswd,SQL_NTS) != SQL_SUCCESS))
-  {
-   if (rc != SQL_SUCCESS_WITH_INFO)
-    Debug(LDAP_DEBUG_TRACE,"backsql_open_db_conn: SQLConnect() failed:\n",0,0,0);
-   else
-	Debug(LDAP_DEBUG_TRACE,"backsql_open_db_conn: SQLConnect() succeeded with info:\n",0,0,0);
-   backsql_PrintErrors(si->db_env,dbc->dbh,SQL_NULL_HENV,rc);
-   if (rc != SQL_SUCCESS_WITH_INFO)
-    return NULL;
-  }
-
- /* TimesTen : Turn off autocommit.  We must explicitly commit any transactions. */
-
- SQLSetConnectOption(dbc->dbh, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
-
- /* See if this connection is to TimesTen.  If it is,
-    remember that fact for later use. */
-
- si->isTimesTen = 0;        /* Assume until proven otherwise */
-
- DBMSName[0] = '\0';
- rc = SQLGetInfo(dbc->dbh, SQL_DBMS_NAME, (PTR) &DBMSName,
-         sizeof(DBMSName), NULL);
- if (rc == SQL_SUCCESS) {
-   if (strcmp(DBMSName, "TimesTen") == 0 ||
-       strcmp(DBMSName, "Front-Tier") == 0) {
-     Debug(LDAP_DEBUG_TRACE,"backsql_open_db_conn: TimesTen database!\n",0,0,0);
-     si->isTimesTen = 1;
-   }
- }
- else {
-   Debug(LDAP_DEBUG_TRACE,"backsql_open_db_conn: SQLGetInfo() failed:\n",0,0,0);
-   backsql_PrintErrors(si->db_env,dbc->dbh,SQL_NULL_HENV,rc);
- }  
- /* end TimesTen */
+	/* TimesTen */
+	char			DBMSName[ 32 ];
+	backsql_db_conn		*dbc;
+	int			rc;
  
- Debug(LDAP_DEBUG_TRACE,"backsql_open_db_conn(): connected, adding to tree\n",0,0,0);
- ldap_pvt_thread_mutex_lock(&si->dbconn_mutex);
- avl_insert(&si->db_conns,dbc,(AVL_CMP)backsql_cmp_connid,backsql_dummy);
- ldap_pvt_thread_mutex_unlock(&si->dbconn_mutex);
- Debug(LDAP_DEBUG_TRACE,"<==backsql_open_db_conn()\n",0,0,0);
- return dbc;
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_conn()\n", 0, 0, 0 );
+	dbc = (backsql_db_conn *)ch_calloc( 1, sizeof( backsql_db_conn ) );
+	dbc->ldap_cid = ldap_cid;
+	rc = SQLAllocConnect( si->db_env, &dbc->dbh );
+	if (!BACKSQL_SUCCESS( rc ) ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
+			"SQLAllocConnect() failed:\n", 0, 0, 0 );
+		backsql_PrintErrors( si->db_env, SQL_NULL_HDBC,
+				SQL_NULL_HENV, rc );
+		return NULL;
+	}
+
+	rc = SQLConnect( dbc->dbh, si->dbname, SQL_NTS, si->dbuser, 
+			SQL_NTS, si->dbpasswd, SQL_NTS );
+	if ( rc != SQL_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
+			"SQLConnect() to database '%s' as user '%s' "
+			"%s:\n", si->dbname, si->dbuser,
+			rc == SQL_SUCCESS_WITH_INFO ?
+			"succeeded with info" : "failed" );
+		backsql_PrintErrors( si->db_env, dbc->dbh, SQL_NULL_HENV, rc );
+		if ( rc != SQL_SUCCESS_WITH_INFO ) {
+			return NULL;
+		}
+	}
+
+	/* 
+	 * TimesTen : Turn off autocommit.  We must explicitly
+	 * commit any transactions. 
+	 */
+	SQLSetConnectOption( dbc->dbh, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF );
+
+	/* 
+	 * See if this connection is to TimesTen.  If it is,
+	 * remember that fact for later use.
+	 */
+	si->isTimesTen = 0;	/* Assume until proven otherwise */
+	DBMSName[ 0 ] = '\0';
+	rc = SQLGetInfo( dbc->dbh, SQL_DBMS_NAME, (PTR)&DBMSName,
+			sizeof( DBMSName ), NULL );
+	if ( rc == SQL_SUCCESS ) {
+		if ( strcmp( DBMSName, "TimesTen" ) == 0 ||
+				strcmp( DBMSName, "Front-Tier" ) == 0 ) {
+			Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
+				"TimesTen database!\n", 0, 0, 0 );
+			si->isTimesTen = 1;
+		}
+	} else {
+		Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
+			"SQLGetInfo() failed:\n", 0, 0, 0 );
+		backsql_PrintErrors( si->db_env, dbc->dbh, SQL_NULL_HENV, rc );
+	}
+	/* end TimesTen */
+
+	Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(): "
+		"connected, adding to tree\n", 0, 0, 0 );
+	ldap_pvt_thread_mutex_lock( &si->dbconn_mutex );
+	avl_insert( &si->db_conns, dbc, (AVL_CMP)backsql_cmp_connid,
+			backsql_dummy );
+	ldap_pvt_thread_mutex_unlock( &si->dbconn_mutex );
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_conn()\n", 0, 0, 0 );
+
+	return dbc;
 }
 
-int backsql_free_db_conn(Backend *be,Connection *ldapc)
+int
+backsql_free_db_conn( Backend *be, Connection *ldapc )
 {
- backsql_info *si=(backsql_info*)be->be_private;
- backsql_db_conn tmp,*conn;
- 
- Debug(LDAP_DEBUG_TRACE,"==>backsql_free_db_conn()\n",0,0,0);
- tmp.ldap_cid=ldapc->c_connid;
- ldap_pvt_thread_mutex_lock(&si->dbconn_mutex);
- conn=(backsql_db_conn*)avl_delete(&si->db_conns,&tmp,(AVL_CMP)backsql_cmp_connid);
- ldap_pvt_thread_mutex_unlock(&si->dbconn_mutex);
- /*we have one thread per connection, as I understand -- so we can
-  *get this out of critical section
-*/
- if (conn!=NULL)
-  { 
-   Debug(LDAP_DEBUG_TRACE,"backsql_free_db_conn(): closing db connection\n",0,0,0);
-   backsql_close_db_conn(conn);
-  }
- Debug(LDAP_DEBUG_TRACE,"<==backsql_free_db_conn()\n",0,0,0);
- return SQL_SUCCESS;
+	backsql_info		*si = (backsql_info *)be->be_private;
+	backsql_db_conn		tmp, *conn;
+
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_free_db_conn()\n", 0, 0, 0 );
+	tmp.ldap_cid = ldapc->c_connid;
+	ldap_pvt_thread_mutex_lock( &si->dbconn_mutex );
+	conn = (backsql_db_conn *)avl_delete( &si->db_conns, &tmp,
+			(AVL_CMP)backsql_cmp_connid );
+	ldap_pvt_thread_mutex_unlock( &si->dbconn_mutex );
+
+	/*
+	 * we have one thread per connection, as I understand -- so we can
+	 * get this out of critical section
+	 */
+	if ( conn != NULL ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_free_db_conn(): "
+			"closing db connection\n", 0, 0, 0 );
+		backsql_close_db_conn( conn );
+	}
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_free_db_conn()\n", 0, 0, 0 );
+	return SQL_SUCCESS;
 }
 
-SQLHDBC backsql_get_db_conn(Backend *be,Connection *ldapc)
+SQLHDBC
+backsql_get_db_conn( Backend *be, Connection *ldapc )
 {
- backsql_info *si=(backsql_info*)be->be_private;
- backsql_db_conn *dbc;
- backsql_db_conn tmp;
- 
- Debug(LDAP_DEBUG_TRACE,"==>backsql_get_db_conn()\n",0,0,0);
- 
- tmp.ldap_cid=ldapc->c_connid;
- /*we have one thread per connection, as I understand -- so we do not need
-  * locking here
-*/
- dbc=(backsql_db_conn*)avl_find(si->db_conns,&tmp,(AVL_CMP)backsql_cmp_connid);
- if (!dbc)
-  dbc=backsql_open_db_conn(si,ldapc->c_connid);
- 
- if (!dbc)
- {
-   Debug(LDAP_DEBUG_TRACE,"backsql_get_db_conn(): could not get connection handle -- returning NULL\n",0,0,0);
-   return NULL;
- }
- ldap_pvt_thread_mutex_lock(&si->schema_mutex);
- if (!si->schema_loaded)
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_get_db_conn(): first call -- reading schema map\n",0,0,0);
-   backsql_load_schema_map(si,dbc->dbh);
-  }
- ldap_pvt_thread_mutex_unlock(&si->schema_mutex);
+	backsql_info		*si = (backsql_info *)be->be_private;
+	backsql_db_conn		*dbc;
+	backsql_db_conn		tmp;
+
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_get_db_conn()\n", 0, 0, 0 );
+
+	tmp.ldap_cid = ldapc->c_connid;
+
+	/*
+	 * we have one thread per connection, as I understand -- 
+	 * so we do not need locking here
+	 */
+	dbc = (backsql_db_conn *)avl_find( si->db_conns, &tmp,
+			(AVL_CMP)backsql_cmp_connid );
+	if ( !dbc ) {
+		dbc = backsql_open_db_conn( si, ldapc->c_connid );
+	}
  
- Debug(LDAP_DEBUG_TRACE,"<==backsql_get_db_conn()\n",0,0,0);
- return dbc->dbh;
+	if ( !dbc ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
+			"could not get connection handle -- returning NULL\n",
+			0, 0, 0 );
+		return SQL_NULL_HDBC;
+	}
+	ldap_pvt_thread_mutex_lock( &si->schema_mutex );
+	if ( !si->schema_loaded ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
+			"first call -- reading schema map\n", 0, 0, 0 );
+		backsql_load_schema_map( si, dbc->dbh );
+	}
+	ldap_pvt_thread_mutex_unlock( &si->schema_mutex );
+
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_get_db_conn()\n", 0, 0, 0 );
+	return dbc->dbh;
 }
 
 #endif /* SLAPD_SQL */
diff --git a/servers/slapd/back-sql/sql-wrap.h b/servers/slapd/back-sql/sql-wrap.h
index 6bf738ce09..00edc26b6e 100644
--- a/servers/slapd/back-sql/sql-wrap.h
+++ b/servers/slapd/back-sql/sql-wrap.h
@@ -13,17 +13,28 @@
 #include "back-sql.h"
 #include "sql-types.h"
 
-RETCODE backsql_Prepare(SQLHDBC dbh,SQLHSTMT *sth,char* query,int timeout);
-RETCODE backsql_BindParamStr(SQLHSTMT sth,int par_ind,char *str,int maxlen);
-RETCODE backsql_BindParamID(SQLHSTMT sth,int par_ind,unsigned long *id);
-RETCODE backsql_BindRowAsStrings(SQLHSTMT sth,BACKSQL_ROW_NTS *row);
-RETCODE backsql_FreeRow(BACKSQL_ROW_NTS *row);
-void backsql_PrintErrors(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth,int rc);
-
-int backsql_init_db_env(backsql_info *si);
-int backsql_free_db_env(backsql_info *si);
-SQLHDBC backsql_get_db_conn(Backend *be,Connection *ldapc);
-int backsql_free_db_conn(Backend *be,Connection *ldapc);
-
-#endif
+RETCODE backsql_Prepare( SQLHDBC dbh, SQLHSTMT *sth, char* query, int timeout );
+
+#define backsql_BindParamStr( sth, par_ind, str, maxlen ) 		\
+	SQLBindParameter( (sth), (SQLUSMALLINT)(par_ind), 		\
+			SQL_PARAM_INPUT,				\
+			SQL_C_CHAR, SQL_VARCHAR,			\
+         		(SQLUINTEGER)(maxlen), 0, (SQLPOINTER)(str),	\
+			(SQLUINTEGER)(maxlen), NULL )
+
+#define backsql_BindParamID( sth, par_ind, id )				\
+	SQLBindParameter( (sth), (SQLUSMALLINT)(par_ind),		\
+			SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,	\
+			0, 0, (SQLPOINTER)(id), 0, (SQLINTEGER*)NULL )
+
+RETCODE backsql_BindRowAsStrings( SQLHSTMT sth, BACKSQL_ROW_NTS *row );
+RETCODE backsql_FreeRow( BACKSQL_ROW_NTS *row );
+void backsql_PrintErrors( SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth, int rc );
+
+int backsql_init_db_env( backsql_info *si );
+int backsql_free_db_env( backsql_info *si );
+SQLHDBC backsql_get_db_conn( Backend *be, Connection *ldapc );
+int backsql_free_db_conn( Backend *be, Connection *ldapc );
+
+#endif /* __BACKSQL_SQL_WRAP_H__ */
 
diff --git a/servers/slapd/back-sql/util.c b/servers/slapd/back-sql/util.c
index 00e1d33889..e7458b7296 100644
--- a/servers/slapd/back-sql/util.c
+++ b/servers/slapd/back-sql/util.c
@@ -13,158 +13,231 @@
 
 #include <stdio.h>
 #include <sys/types.h>
-#include <string.h>
-#include <stdarg.h>
+#include "ac/string.h"
+#include "ac/ctype.h"
+#include "ac/stdarg.h"
 #include "slap.h"
 #include "back-sql.h"
 #include "schema-map.h"
 #include "util.h"
 
 
-char backsql_def_oc_query[]="SELECT id,name,keytbl,keycol,create_proc,delete_proc,expect_return FROM ldap_oc_mappings";
-char backsql_def_at_query[]="SELECT name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return,sel_expr_u FROM ldap_attr_mappings WHERE oc_map_id=?";
-char backsql_def_delentry_query[]="DELETE FROM ldap_entries WHERE id=?";
-char backsql_def_insentry_query[]="INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)";
-char backsql_def_subtree_cond[]="ldap_entries.dn LIKE CONCAT('%',?)";
-char backsql_id_query[]="SELECT id,keyval,oc_map_id FROM ldap_entries WHERE ";
-
-/* TimesTen*/
+char backsql_def_oc_query[] = 
+	"SELECT id,name,keytbl,keycol,create_proc,delete_proc,expect_return "
+	"FROM ldap_oc_mappings";
+char backsql_def_at_query[] = 
+	"SELECT name,sel_expr,from_tbls,join_where,add_proc,delete_proc,"
+	"param_order,expect_return,sel_expr_u FROM ldap_attr_mappings "
+	"WHERE oc_map_id=?";
+char backsql_def_delentry_query[] = "DELETE FROM ldap_entries WHERE id=?";
+char backsql_def_insentry_query[] = 
+	"INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) "
+	"VALUES (?,?,?,?)";
+char backsql_def_subtree_cond[] = "ldap_entries.dn LIKE CONCAT('%',?)";
+char backsql_def_upper_subtree_cond[] = "(ldap_entries.dn) LIKE CONCAT('%',?)";
+char backsql_id_query[] = "SELECT id,keyval,oc_map_id FROM ldap_entries WHERE ";
+
+/* TimesTen */
 char backsql_check_dn_ru_query[] = "SELECT dn_ru from ldap_entries";
 
-char* backsql_strcat(char* dest,int *buflen, ...)
+struct berval *
+backsql_strcat( struct berval *dest, int *buflen, ... )
 {
- va_list strs;
- int cdlen,cslen,grow;
- char *cstr;
+	va_list		strs;
+	int		cdlen, cslen, grow;
+	char		*cstr;
+
+	assert( dest );
+	assert( dest->bv_val == NULL 
+			|| dest->bv_len == strlen( dest->bv_val ) );
  
- /*Debug(LDAP_DEBUG_TRACE,"==>my_strcat()\n");*/
- va_start(strs,buflen);
- if (dest==NULL || *buflen<=0)
-  {
-   dest=(char*)ch_calloc(BACKSQL_STR_GROW,sizeof(char));
-   *buflen=BACKSQL_STR_GROW;
-  }
- cdlen=strlen(dest)+1;
- while ((cstr=va_arg(strs,char*)) != NULL)
-  {
-   cslen=strlen(cstr);
-   grow=BACKSQL_MAX(BACKSQL_STR_GROW,cslen);
-   if (*buflen-cdlen < cslen)
-    {
-     /*Debug(LDAP_DEBUG_TRACE,"my_strcat(): buflen=%d, cdlen=%d, cslen=%d -- reallocating dest\n",
-                           *buflen,cdlen,cslen); */
-     dest=(char*)ch_realloc(dest,(*buflen)+grow*sizeof(char));
-     if (dest == NULL)
-      {
-       Debug(LDAP_DEBUG_ANY,"my_strcat(): could not reallocate string buffer.\n",0,0,0);
-      }
-     *buflen+=grow;
-     /*Debug(LDAP_DEBUG_TRACE,"my_strcat(): new buflen=%d, dest=%p\n",*buflen,dest,0);*/
-    }
-   strcat(dest,cstr);
-   cdlen+=cslen;
-  }
- va_end(strs);
- /*Debug(LDAP_DEBUG_TRACE,"<==my_strcat() (dest='%s')\n",dest,0,0);*/
- return dest;
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_strcat()\n" );
+#endif
+
+	va_start( strs, buflen );
+	if ( dest->bv_val == NULL || *buflen <= 0 ) {
+		dest->bv_val = (char *)ch_calloc( BACKSQL_STR_GROW, 
+				sizeof( char ) );
+		dest->bv_len = 0;
+		*buflen = BACKSQL_STR_GROW;
+	}
+	cdlen = dest->bv_len;
+	while ( ( cstr = va_arg( strs, char * ) ) != NULL ) {
+		cslen = strlen( cstr );
+		grow = BACKSQL_MAX( BACKSQL_STR_GROW, cslen );
+		if ( *buflen - cdlen <= cslen ) {
+			char	*tmp_dest;
+
+#if 0
+			Debug( LDAP_DEBUG_TRACE, "backsql_strcat(): "
+				"buflen=%d, cdlen=%d, cslen=%d "
+				"-- reallocating dest\n",
+				*buflen, cdlen + 1, cslen );
+#endif
+			tmp_dest = (char *)ch_realloc( dest->bv_val,
+					( *buflen ) + grow * sizeof( char ) );
+			if ( tmp_dest == NULL ) {
+				Debug( LDAP_DEBUG_ANY, "backsql_strcat(): "
+					"could not reallocate string buffer.\n",
+					0, 0, 0 );
+				return NULL;
+			}
+			dest->bv_val = tmp_dest;
+			*buflen += grow;
+#if 0
+			Debug( LDAP_DEBUG_TRACE, "backsql_strcat(): "
+				"new buflen=%d, dest=%p\n", *buflen, dest, 0 );
+#endif
+		}
+		AC_MEMCPY( dest->bv_val + cdlen, cstr, cslen + 1 );
+		cdlen += cslen;
+	}
+	va_end( strs );
+
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_strcat() (dest='%s')\n", 
+			dest, 0, 0 );
+#endif
+
+	dest->bv_len = cdlen;
+
+	return dest;
 } 
 
-int backsql_entry_addattr(Entry *e,char *at_name,char *at_val,unsigned int at_val_len)
+int
+backsql_entry_addattr(
+	Entry		*e,
+	char		*at_name,
+	char		*at_val, 
+	unsigned int	at_val_len )
 {
- Attribute *c_at=e->e_attrs;
- struct berval* add_val[2];
- struct berval cval;
- AttributeDescription *ad;
- int rc;
- const char *text;
- 
- Debug(LDAP_DEBUG_TRACE,"backsql_entry_addattr(): at_name='%s', at_val='%s'\n",at_name,at_val,0);
- cval.bv_val=at_val;
- cval.bv_len=at_val_len;
- add_val[0]=&cval;
- add_val[1]=NULL;
- 
- ad=NULL;
- rc = slap_str2ad( at_name, &ad, &text );
- if( rc != LDAP_SUCCESS ) 
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_entry_addattr(): failed to find AttributeDescription for '%s'\n",at_name,0,0);
-   return 0;
-  }
-  
- rc = attr_merge(e,ad,add_val);
-
- if( rc != 0 )
-  {
-   Debug(LDAP_DEBUG_TRACE,"backsql_entry_addattr(): failed to merge value '%s' for attribute '%s'\n",at_val,at_name,0);
-   return 0;
-  }
- 
- Debug(LDAP_DEBUG_TRACE,"<==backsql_query_addattr()\n",0,0,0);
- return 1;
+	struct berval		add_val[ 2 ];
+	AttributeDescription	*ad;
+	int			rc;
+	const char		*text;
+
+	Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(): "
+		"at_name='%s', at_val='%s'\n", at_name, at_val, 0 );
+	add_val[ 0 ].bv_val = at_val;
+	add_val[ 0 ].bv_len = at_val_len;
+	add_val[ 1 ].bv_val = NULL;
+	add_val[ 1 ].bv_len = 0;
+
+	ad = NULL;
+	rc = slap_str2ad( at_name, &ad, &text );
+	if ( rc != LDAP_SUCCESS ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(): "
+			"failed to find AttributeDescription for '%s'\n",
+			at_name, 0, 0 );
+		return 0;
+	}
+
+	rc = attr_merge( e, ad, add_val );
+
+	if ( rc != 0 ) {
+		Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(): "
+			"failed to merge value '%s' for attribute '%s'\n",
+			at_val, at_name, 0 );
+		return 0;
+	}
+	
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_query_addattr()\n", 0, 0, 0 );
+	return 1;
 }
 
-char* backsql_get_table_spec(char **p)
+char *
+backsql_get_table_spec( char **p )
 {
- char *s,*q;
- char *res=NULL;
- int res_len=0;
-
- s=*p;
- while(**p && **p!=',') (*p)++;
- if (**p)
-  *(*p)++='\0';
-
+	char		*s, *q;
+	struct berval	res = { 0, NULL };
+	int		res_len = 0;
+
+	s = *p;
+	while ( **p && **p != ',' ) {
+		(*p)++;
+	}
+
+	if ( **p ) {
+		*(*p)++ = '\0';
+	}
+	
 #define BACKSQL_NEXT_WORD { \
-  while (*s && isspace((unsigned char)*s)) s++; \
-  if (!*s) return res; \
-  q=s; \
-  while (*q && !isspace((unsigned char)*q)) q++; \
-  if (*q) *q++='\0'; \
- }
-
- BACKSQL_NEXT_WORD;
- res=backsql_strcat(res,&res_len,s,NULL);/*table name*/
- s=q;
-
- BACKSQL_NEXT_WORD;
- if (!strcasecmp(s,"as"))
- {
-  s=q;
-  BACKSQL_NEXT_WORD;
- }
- /*res=backsql_strcat(res,&res_len," AS ",s,NULL);
-  *oracle doesn't understand AS :(
-  */
- res=backsql_strcat(res,&res_len," ",s,NULL);/*table alias*/
- return res;
+		while ( *s && isspace( (unsigned char)*s ) ) s++; \
+		if ( !*s ) return res.bv_val; \
+		q = s; \
+		while ( *q && !isspace( (unsigned char)*q ) ) q++; \
+		if ( *q ) *q++='\0'; \
+	}
+
+	BACKSQL_NEXT_WORD;
+	/* table name */
+	backsql_strcat( &res, &res_len, s, NULL );
+	s = q;
+
+	BACKSQL_NEXT_WORD;
+	if ( !strcasecmp( s, "as" ) ) {
+		s = q;
+		BACKSQL_NEXT_WORD;
+	}
+#if 0
+	backsql_strcat( &res, &res_len, " AS ", s, NULL );
+	/* oracle doesn't understand AS :( */
+#endif
+	/* table alias */
+	backsql_strcat( &res, &res_len, " ", s, NULL);
+	return res.bv_val;
 }
 
-int backsql_merge_from_clause(char **dest_from,int *dest_len,char *src_from)
+int
+backsql_merge_from_clause( char **dest_from, int *dest_len, char *src_from )
 {
- char *s,*p,*srcc,*pos,e;
-
- /*Debug(LDAP_DEBUG_TRACE,"==>backsql_merge_from_clause(): dest_from='%s',src_from='%s'\n",
- 				dest_from,src_from,0); */
- srcc=ch_strdup(src_from);
- p=srcc;
- while(*p)
- {
-  s=backsql_get_table_spec(&p);
- /* Debug(LDAP_DEBUG_TRACE,"backsql_merge_from_clause(): p='%s' s='%s'\n",p,s,0);  */
-  if (*dest_from==NULL)
-   *dest_from=backsql_strcat(*dest_from,dest_len,s,NULL);
-  else
-	if((pos=strstr(*dest_from,s))==NULL)
-     *dest_from=backsql_strcat(*dest_from,dest_len,",",s,NULL);
-    else if((e=pos[strlen(s)])!='\0' && e!=',')
-      *dest_from=backsql_strcat(*dest_from,dest_len,",",s,NULL);
-  if (s)
-	ch_free(s);
- }
-/* Debug(LDAP_DEBUG_TRACE,"<==backsql_merge_from_clause()\n",0,0,0);*/
- free(srcc);
- return 1;
+	char		*s, *p, *srcc, *pos, e;
+	struct berval	res = { 0 , NULL };
+
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "==>backsql_merge_from_clause(): "
+		"dest_from='%s',src_from='%s'\n",
+ 		dest_from, src_from, 0 );
+#endif
+	srcc = ch_strdup( src_from );
+	p = srcc;
+
+	if ( *dest_from != NULL ) {
+		res.bv_val = *dest_from;
+		res.bv_len = strlen( *dest_from );
+	}
+	
+	while ( *p ) {
+		s = backsql_get_table_spec( &p );
+#if 0
+		Debug( LDAP_DEBUG_TRACE, "backsql_merge_from_clause(): "
+			"p='%s' s='%s'\n", p, s, 0 );
+#endif
+		if ( res.bv_val == NULL ) {
+			backsql_strcat( &res, dest_len, s, NULL );
+
+		} else {
+			pos = strstr( res.bv_val, s );
+			if ( pos == NULL ) {
+				backsql_strcat( &res, dest_len, ",", s, NULL );
+			} else if ( ( e = pos[ strlen( s ) ] ) != '\0' && e != ',' ) {
+				backsql_strcat( &res, dest_len, ",", s, NULL );
+			}
+		}
+		
+		if ( s ) {
+			ch_free( s );
+		}
+	}
+#if 0
+	Debug( LDAP_DEBUG_TRACE, "<==backsql_merge_from_clause()\n", 0, 0, 0 );
+#endif
+	free( srcc );
+	*dest_from = res.bv_val;
+
+	return 1;
 }
 
 #endif /* SLAPD_SQL */
+
diff --git a/servers/slapd/back-sql/util.h b/servers/slapd/back-sql/util.h
index d75eba3799..baa600af32 100644
--- a/servers/slapd/back-sql/util.h
+++ b/servers/slapd/back-sql/util.h
@@ -19,46 +19,58 @@
 
 #define BACKSQL_STR_GROW 64
 
-char* backsql_strcat(char* dest,int *buflen, ...);
+struct berval *backsql_strcat( struct berval *dest, int *buflen, ... );
 
-int backsql_entry_addattr(Entry *e,char *at_name,char *at_val,unsigned int at_val_len);
+int backsql_entry_addattr( Entry *e, char *at_name, char *at_val,
+		unsigned int at_val_len );
 
-typedef struct __backsql_srch_info
-{
- char *base_dn;
- int scope;
- Filter *filter;
- int slimit,tlimit;
- time_t	stoptime;
- backsql_entryID *id_list,*c_eid;
- int abandon;
- backsql_info *bi;
- backsql_oc_map_rec *oc;
- char *sel,*from,*join_where,*flt_where;
- int sel_len,from_len,jwhere_len,fwhere_len;
- SQLHDBC dbh;
- int status;
- Backend *be;
- Connection *conn;
- Operation *op;
- char **attrs;
- Entry *e;
- int isTimesTen; /* 1 if the db is TimesTen; 0 if it's not */
-}backsql_srch_info;
+typedef struct __backsql_srch_info {
+	struct berval		*base_dn;
+	int			scope;
+	Filter			*filter;
+	int			slimit, tlimit;
+	time_t			stoptime;
+	backsql_entryID		*id_list, *c_eid;
+	int			n_candidates;
+	int			abandon;
+	backsql_info		*bi;
+	backsql_oc_map_rec	*oc;
+	struct berval		sel, from, join_where, flt_where;
+	int			sel_len, from_len, jwhere_len, fwhere_len;
+	SQLHDBC			dbh;
+	int			status;
+	Backend			*be;
+	Connection		*conn;
+	Operation		*op;
+	char			**attrs;
+	Entry			*e;
+	/* 1 if the db is TimesTen; 0 if it's not */
+	int			isTimesTen; 
+} backsql_srch_info;
 
-int backsql_process_filter(backsql_srch_info *bsi,Filter *f);
-void backsql_init_search(backsql_srch_info *bsi,backsql_info *bi,char *nbase,int scope,
-						 int slimit,int tlimit,time_t stoptime,Filter *filter,
-						 SQLHDBC dbh,Backend *be,Connection *conn,Operation *op,struct berval **attrs);
-Entry* backsql_id2entry(backsql_srch_info *bsi,Entry* e,backsql_entryID* id);
+int backsql_process_filter( backsql_srch_info *bsi, Filter *f );
+void backsql_init_search( backsql_srch_info *bsi, backsql_info *bi,
+		struct berval *nbase, int scope, int slimit, int tlimit,
+		time_t stoptime, Filter *filter, SQLHDBC dbh,
+		BackendDB *be, Connection *conn, Operation *op,
+		AttributeName *attrs );
+Entry *backsql_id2entry( backsql_srch_info *bsi, Entry *e, 
+		backsql_entryID *id );
 
-extern char backsql_def_oc_query[],backsql_def_at_query[],
-			backsql_def_delentry_query[],backsql_def_insentry_query[],
-			backsql_def_subtree_cond[],backsql_id_query[];
-extern char backsql_check_dn_ru_query[];
+extern char 
+	backsql_def_oc_query[],
+	backsql_def_at_query[],
+	backsql_def_delentry_query[],
+	backsql_def_insentry_query[],
+	backsql_def_subtree_cond[],
+	backsql_def_upper_subtree_cond[],
+	backsql_id_query[];
+extern char 
+	backsql_check_dn_ru_query[];
 
-int backsql_merge_from_clause(char **dest_from,int *dest_len,char *src_from);
+int backsql_merge_from_clause( char **dest_from, int *dest_len, 
+		char *src_from );
 
 
-#endif
+#endif /* __BACKSQL_UTIL_H__ */
 
-- 
GitLab