From: Pierangelo Masarati Date: Tue, 13 Aug 2002 17:12:27 +0000 (+0000) Subject: changes: X-Git-Tag: NO_SLAP_OP_BLOCKS~1225 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=115408986c62fea339b99f93dafc820bd8c94062;p=openldap 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 - ... --- 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 #include -#include +#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;i0) - { - 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;iexpect_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 #include -#include +#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 : "", 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:"",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;i0) - { - 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 #include -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 -#include +#include "ac/string.h" #include +#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;incols;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 #include -#include -#include +#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__ */