-#ifndef __BACKSQL_H__
-#define __BACKSQL_H__
-
/*
* Copyright 1999, Dmitry Kovalev <mit@openldap.org>, All rights reserved.
*
* license is available at http://www.OpenLDAP.org/license.html or
* in file LICENSE in the top-level directory of the distribution.
*/
+/*
+ * Copyright 2002, Pierangelo Masarati <ando@OpenLDAP.org>.
+ * All rights reserved.
+ *
+ * This is a modified version of back-sql; the same conditions
+ * of the above reported Copyright statement, and sigificantly
+ * the OpenLDAP Public License apply. Credits go to Dmitry
+ * Kovalev for the initial development of the backend.
+ *
+ * This copyright statement cannot be altered.
+ */
+/*
+ * The following changes have been addressed:
+ *
+ * Enhancements:
+ * - re-styled code for better readability
+ * - upgraded backend API to reflect recent changes
+ * - LDAP schema is checked when loading SQL/LDAP mapping
+ * - AttributeDescription/ObjectClass pointers used for more efficient
+ * mapping lookup
+ * - bervals used where string length is required often
+ * - atomized write operations by committing at the end of each operation
+ * and defaulting connection closure to rollback
+ * - added LDAP access control to write operations
+ * - fully implemented modrdn (with rdn attrs change, deleteoldrdn,
+ * access check, parent/children check and more)
+ * - added parent access control, children control to delete operation
+ * - added structuralObjectClass operational attribute check and
+ * value return on search
+ * - added hasSubordinate operational attribute on demand
+ * - search limits are appropriately enforced
+ * - function backsql_strcat() has been made more efficient
+ * - concat function has been made configurable by means of a pattern
+ * - added config switches:
+ * - fail_if_no_mapping write operations fail if there is no mapping
+ * - has_ldapinfo_dn_ru overrides autodetect
+ * - concat_pattern a string containing two '?' is used
+ * (note that "?||?" should be more portable
+ * than builtin function "CONCAT(?,?)")
+ * - strcast_func cast of string constants in "SELECT DISTINCT
+ * statements (needed by PostgreSQL)
+ * - upper_needs_cast cast the argument of upper when required
+ * (basically when building dn substring queries)
+ *
+ * Todo:
+ * - add security checks for SQL statements that can be injected (?)
+ * - re-test with previously supported RDBMs
+ * - replace dn_ru and so with normalized dn (no need for upper() and so
+ * in dn match)
+ * - implement a backsql_normalize() function to replace the upper()
+ * conversion routines
+ * - note that subtree deletion, subtree renaming and so could be easily
+ * implemented (rollback and consistency checks are available :)
+ * - implement "lastmod" and other operational stuff (ldap_entries table ?)
+ * - check how to allow multiple operations with one statement, to remove
+ * BACKSQL_REALLOC_STMT from modify.c (a more recent unixODBC lib?)
+ */
+
+#ifndef __BACKSQL_H__
+#define __BACKSQL_H__
#include "external.h"
#include "sql-types.h"
*/
#define BACKSQL_MAX_DN_LEN 255
+/*
+ * define to enable very extensive trace logging (debug only)
+ */
+#undef BACKSQL_TRACE
+
+
typedef struct {
char *dbhost;
int dbport;
char *dbname;
/*
* SQL condition for subtree searches differs in syntax:
- * "LIKE CONCAT('%',?)" or "LIKE '%'+?" or smth else
+ * "LIKE CONCAT('%',?)" or "LIKE '%'+?" or "LIKE '%'||?"
+ * or smth else
*/
- char *subtree_cond;
- char *oc_query,*at_query;
+ struct berval subtree_cond;
+ struct berval children_cond;
+ char *oc_query, *at_query;
char *insentry_query,*delentry_query;
char *id_query;
- char *upper_func;
- char *strcast_func;
+ char *has_children_query;
+ struct berval upper_func;
+ struct berval upper_func_open;
+ struct berval upper_func_close;
+ BerVarray concat_func;
+
+ unsigned int bsql_flags;
+#define BSQLF_SCHEMA_LOADED 0x0001
+#define BSQLF_UPPER_NEEDS_CAST 0x0002
+#define BSQLF_CREATE_NEEDS_SELECT 0x0004
+#define BSQLF_FAIL_IF_NO_MAPPING 0x0008
+#define BSQLF_HAS_LDAPINFO_DN_RU 0x0010
+#define BSQLF_DONTCHECK_LDAPINFO_DN_RU 0x0020
+#define BSQLF_USE_REVERSE_DN 0x0040
+
+#define BACKSQL_SCHEMA_LOADED(si) \
+ ((si)->bsql_flags & BSQLF_SCHEMA_LOADED)
+#define BACKSQL_UPPER_NEEDS_CAST(si) \
+ ((si)->bsql_flags & BSQLF_UPPER_NEEDS_CAST)
+#define BACKSQL_CREATE_NEEDS_SELECT(si) \
+ ((si)->bsql_flags & BSQLF_CREATE_NEEDS_SELECT)
+#define BACKSQL_FAIL_IF_NO_MAPPING(si) \
+ ((si)->bsql_flags & BSQLF_FAIL_IF_NO_MAPPING)
+#define BACKSQL_HAS_LDAPINFO_DN_RU(si) \
+ ((si)->bsql_flags & BSQLF_HAS_LDAPINFO_DN_RU)
+#define BACKSQL_DONTCHECK_LDAPINFO_DN_RU(si) \
+ ((si)->bsql_flags & BSQLF_DONTCHECK_LDAPINFO_DN_RU)
+#define BACKSQL_USE_REVERSE_DN(si) \
+ ((si)->bsql_flags & BSQLF_USE_REVERSE_DN)
+
+ struct berval strcast_func;
Avlnode *db_conns;
Avlnode *oc_by_oc;
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 ) \
#include "slap.h"
#include "back-sql.h"
#include "sql-wrap.h"
+#include "util.h"
int
backsql_db_config(
if ( argc < 2 ) {
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): "
- "missing hostname in dbhost directive\n",
+ "missing hostname in \"dbhost\" directive\n",
fname, lineno, 0 );
return 1;
}
if ( argc < 2 ) {
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): "
- "missing username in dbuser directive\n",
+ "missing username in \"dbuser\" directive\n",
fname, lineno, 0 );
return 1;
}
if ( argc < 2 ) {
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): "
- "missing password in dbpasswd directive\n",
+ "missing password in \"dbpasswd\" directive\n",
fname, lineno, 0 );
return 1;
}
if ( argc < 2 ) {
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): "
- "missing database name in dbname directive\n",
- fname, lineno, 0 );
+ "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 ], "concat_pattern" ) ) {
+ if ( argc < 2 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<==backsql_db_config (%s line %d): "
+ "missing pattern"
+ "in \"concat_pattern\" directive\n",
+ fname, lineno, 0 );
+ return 1;
+ }
+ if ( backsql_split_pattern( argv[ 1 ], &si->concat_func, 2 ) ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<==backsql_db_config (%s line %d): "
+ "unable to parse pattern \"%s\"\n"
+ "in \"concat_pattern\" directive\n",
+ fname, lineno, argv[ 1 ] );
+ return 1;
+ }
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+ "concat_pattern=\"%s\"\n", argv[ 1 ], 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",
+ "in \"subtree_cond\" directive\n",
fname, lineno, 0 );
return 1;
}
- si->subtree_cond = ch_strdup( argv[ 1 ] );
+ ber_str2bv( argv[ 1 ], 0, 1, &si->subtree_cond );
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
- "subtree_cond=%s\n", si->subtree_cond, 0, 0 );
+ "subtree_cond=%s\n", si->subtree_cond.bv_val, 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",
+ "in \"oc_query\" directive\n",
fname, lineno, 0 );
return 1;
}
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): "
"missing SQL statement "
- "in at_query directive\n",
+ "in \"at_query\" directive\n",
fname, lineno, 0 );
return 1;
}
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): "
"missing SQL statement "
- "in insentry_query directive\n",
+ "in \"insentry_query\" directive\n",
fname, lineno, 0 );
return 1;
}
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
"insentry_query=%s\n", si->insentry_query, 0, 0 );
+ } else if ( !strcasecmp( argv[ 0 ], "create_needs_select" ) ) {
+ if ( argc < 2 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<==backsql_db_config (%s line %d): "
+ "missing { yes | no }"
+ "in \"create_needs_select\" directive\n",
+ fname, lineno, 0 );
+ return 1;
+ }
+
+ if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+ si->bsql_flags |= BSQLF_CREATE_NEEDS_SELECT;
+
+ } else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+ si->bsql_flags &= ~BSQLF_CREATE_NEEDS_SELECT;
+
+ } else {
+ Debug( LDAP_DEBUG_TRACE,
+ "<==backsql_db_config (%s line %d): "
+ "\"create_needs_select\" directive arg "
+ "must be \"yes\" or \"no\"\n",
+ fname, lineno, 0 );
+ return 1;
+
+ }
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+ "create_needs_select =%s\n",
+ BACKSQL_CREATE_NEEDS_SELECT( si ) ? "yes" : "no",
+ 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",
+ "in \"upper_func\" directive\n",
fname, lineno, 0 );
return 1;
}
- si->upper_func = ch_strdup( argv[ 1 ] );
+ ber_str2bv( argv[ 1 ], 0, 1, &si->upper_func );
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
- "upper_func=%s\n", si->upper_func, 0, 0 );
+ "upper_func=%s\n", si->upper_func.bv_val, 0, 0 );
+
+ } else if ( !strcasecmp( argv[ 0 ], "upper_needs_cast" ) ) {
+ if ( argc < 2 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<==backsql_db_config (%s line %d): "
+ "missing { yes | no }"
+ "in \"upper_needs_cast\" directive\n",
+ fname, lineno, 0 );
+ return 1;
+ }
+
+ if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+ si->bsql_flags |= BSQLF_UPPER_NEEDS_CAST;
+
+ } else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+ si->bsql_flags &= ~BSQLF_UPPER_NEEDS_CAST;
+
+ } else {
+ Debug( LDAP_DEBUG_TRACE,
+ "<==backsql_db_config (%s line %d): "
+ "\"upper_needs_cast\" directive arg "
+ "must be \"yes\" or \"no\"\n",
+ fname, lineno, 0 );
+ return 1;
+
+ }
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+ "upper_needs_cast =%s\n",
+ BACKSQL_UPPER_NEEDS_CAST( si ) ? "yes" : "no", 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",
+ "in \"strcast_func\" directive\n",
fname, lineno, 0 );
return 1;
}
- si->strcast_func = ch_strdup( argv[ 1 ] );
+ ber_str2bv( argv[ 1 ], 0, 1, &si->strcast_func );
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
- "strcast_func=%s\n", si->strcast_func, 0, 0 );
+ "strcast_func=%s\n", si->strcast_func.bv_val, 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",
+ "in \"delentry_query\" directive\n",
fname, lineno, 0 );
return 1;
}
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): "
"missing { yes | no }"
- "in has_ldapinfo_dn_ru directive\n",
+ "in \"has_ldapinfo_dn_ru\" directive\n",
fname, lineno, 0 );
return 1;
}
if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
- si->has_ldapinfo_dn_ru = 1;
+ si->bsql_flags |= BSQLF_HAS_LDAPINFO_DN_RU;
+ si->bsql_flags |= BSQLF_DONTCHECK_LDAPINFO_DN_RU;
+
} else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
- si->has_ldapinfo_dn_ru = 0;
+ si->bsql_flags &= ~BSQLF_HAS_LDAPINFO_DN_RU;
+ si->bsql_flags |= BSQLF_DONTCHECK_LDAPINFO_DN_RU;
+
} else {
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): "
- "has_ldapinfo_dn_ru directive arg "
+ "\"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 );
+ BACKSQL_HAS_LDAPINFO_DN_RU( si ) ? "yes" : "no", 0, 0 );
+
+ } else if ( !strcasecmp( argv[ 0 ], "fail_if_no_mapping") ) {
+ if ( argc < 2 ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "<==backsql_db_config (%s line %d): "
+ "missing { yes | no }"
+ "in \"fail_if_no_mapping\" directive\n",
+ fname, lineno, 0 );
+ return 1;
+ }
+
+ if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+ si->bsql_flags |= BSQLF_FAIL_IF_NO_MAPPING;
+
+ } else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+ si->bsql_flags &= ~BSQLF_FAIL_IF_NO_MAPPING;
+
+ } else {
+ Debug( LDAP_DEBUG_TRACE,
+ "<==backsql_db_config (%s line %d): "
+ "\"fail_if_no_mapping\" directive arg "
+ "must be \"yes\" or \"no\"\n",
+ fname, lineno, 0 );
+ return 1;
+
+ }
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): "
+ "fail_if_no_mapping=%s\n",
+ BACKSQL_FAIL_IF_NO_MAPPING( si ) ? "yes" : "no", 0, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): "
- "unknown directive '%s' (ignored)\n",
+ "unknown directive \"%s\" (ignored)\n",
fname, lineno, argv[ 0 ] );
}
return next;
}
-/*
- * 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,
{
SQLHSTMT sth;
BACKSQL_ROW_NTS row;
-#if 0
- SQLINTEGER nrows = 0;
-#endif
RETCODE rc;
int res;
return LDAP_OTHER;
}
- if ( bi->has_ldapinfo_dn_ru ) {
+ if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
/*
* Prepare an upper cased, byte reversed version
* that can be searched using indexes
upperdn, 0, 0 );
toBind = upperdn;
} else {
- if ( bi->isTimesTen ) {
+ if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
AC_MEMCPY( upperdn, dn->bv_val, dn->bv_len + 1 );
ldap_pvt_str2upper( upperdn );
Debug( LDAP_DEBUG_TRACE,
if ( rc != SQL_SUCCESS) {
/* end TimesTen */
Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
- "error binding dn=\"%s\" parameter:\n", toBind, 0, 0 );
+ "error binding dn=\"%s\" parameter:\n",
+ toBind, 0, 0 );
backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
SQLFreeStmt( sth, SQL_DROP );
return LDAP_OTHER;
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 ] );
+ id->id = strtol( row.cols[ 0 ], NULL, 0 );
+ id->keyval = strtol( row.cols[ 1 ], NULL, 0 );
+ id->oc_id = strtol( row.cols[ 2 ], NULL, 0 );
ber_dupbv( &id->dn, dn );
id->next = NULL;
return res;
}
+int
+backsql_has_children(
+ backsql_info *bi,
+ SQLHDBC dbh,
+ struct berval *dn )
+{
+ SQLHSTMT sth;
+ BACKSQL_ROW_NTS row;
+ RETCODE rc;
+ int res;
+
+ Debug( LDAP_DEBUG_TRACE, "==>backsql_has_children(): dn='%s'\n",
+ dn->bv_val, 0, 0 );
+
+ if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_has_children(): 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, "children id query '%s'\n",
+ bi->has_children_query, 0, 0);
+ assert( bi->has_children_query );
+ rc = backsql_Prepare( dbh, &sth, bi->has_children_query, 0 );
+ if ( rc != SQL_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_has_children(): error preparing SQL:\n%s",
+ bi->has_children_query, 0, 0);
+ backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
+ SQLFreeStmt( sth, SQL_DROP );
+ return LDAP_OTHER;
+ }
+
+ rc = backsql_BindParamStr( sth, 1, dn->bv_val, BACKSQL_MAX_DN_LEN );
+ if ( rc != SQL_SUCCESS) {
+ /* end TimesTen */
+ Debug( LDAP_DEBUG_TRACE, "backsql_has_children(): "
+ "error binding dn=\"%s\" parameter:\n",
+ dn->bv_val, 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_has_children(): "
+ "error executing query (\"%s\", \"%s\"):\n",
+ bi->has_children_query, dn->bv_val, 0 );
+ backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
+ SQLFreeStmt( sth, SQL_DROP );
+ return LDAP_OTHER;
+ }
+
+ backsql_BindRowAsStrings( sth, &row );
+
+ rc = SQLFetch( sth );
+ if ( BACKSQL_SUCCESS( rc ) ) {
+ if ( strtol( row.cols[ 0 ], NULL, 0 ) > 0 ) {
+ res = LDAP_COMPARE_TRUE;
+ } else {
+ res = LDAP_COMPARE_FALSE;
+ }
+
+ } else {
+ res = LDAP_OTHER;
+ }
+ backsql_FreeRow( &row );
+
+ SQLFreeStmt( sth, SQL_DROP );
+
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_has_children(): %s\n",
+ res == LDAP_COMPARE_TRUE ? "yes" : "no", 0, 0 );
+
+ return res;
+}
+
int
backsql_get_attr_vals( backsql_at_map_rec *at, backsql_srch_info *bsi )
{
Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
"oc='%s' attr='%s' keyval=%ld\n",
- bsi->oc->name.bv_val, at->name.bv_val, bsi->c_eid->keyval );
+ // bsi->oc->name.bv_val, at->name.bv_val,
+ bsi->oc->oc->soc_names[0], at->ad->ad_cname.bv_val,
+ bsi->c_eid->keyval );
rc = backsql_Prepare( bsi->dbh, &sth, at->query, 0 );
if ( rc != SQL_SUCCESS ) {
backsql_entry_addattr( bsi->e,
&row.col_names[ i ], &bv );
-#if 0
+#ifdef BACKSQL_TRACE
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 ].bv_val, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
}
}
}
int i;
backsql_at_map_rec *at;
int rc;
+ AttributeDescription *ad_oc = slap_schema.si_ad_objectClass;
Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );
for ( i = 0; bsi->attrs[ i ].an_name.bv_val; i++ ) {
AttributeName *attr = &bsi->attrs[ i ];
- if ( attr->an_desc == slap_schema.si_ad_objectClass
+ if ( attr->an_desc == ad_oc
#if 0 /* FIXME: what is 0.10 ? */
|| !BACKSQL_NCMP( &attr->an_name, &bv_n_0_10 )
#endif
bsi->oc->name.bv_val, 0 );
}
}
+
} else {
Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
"retrieving all attributes\n", 0, 0, 0 );
bsi, 0, AVL_INORDER );
}
- backsql_entry_addattr( bsi->e, &bv_n_objectclass, &bsi->oc->name );
+ if ( attr_merge_one( bsi->e, ad_oc, &bsi->oc->name ) ) {
+ entry_free( e );
+ return NULL;
+ }
+
+ if ( global_schemacheck ) {
+ const char *text = NULL;
+ char textbuf[ 1024 ];
+ size_t textlen = sizeof( textbuf );
+ struct berval bv[ 2 ] = { bsi->oc->name, { 0, NULL } };
+ struct berval soc;
+ AttributeDescription *ad_soc
+ = slap_schema.si_ad_structuralObjectClass;
+
+ int rc = structural_class( bv, &soc, NULL,
+ &text, textbuf, textlen );
+ if ( rc != LDAP_SUCCESS ) {
+ entry_free( e );
+ return NULL;
+ }
+
+ if ( bsi->attr_flags | BSQL_SF_ALL_OPER
+ || an_find( bsi->attrs, &AllOper ) ) {
+ if ( attr_merge_one( bsi->e, ad_soc, &soc ) ) {
+ entry_free( e );
+ return NULL;
+ }
+ }
+ }
Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
int backsql_dn2id( backsql_info *bi, backsql_entryID *id,
SQLHDBC dbh, struct berval *dn );
+int backsql_has_children( backsql_info *bi, SQLHDBC dbh, struct berval *dn );
+
/* returns next */
backsql_entryID *backsql_free_entryID( backsql_entryID *id, int freeit );
--- /dev/null
+/* $OpenLDAP$ */
+#ifndef _SQL_EXTERNAL_H
+#define _SQL_EXTERNAL_H
+
+/*
+ * Copyright 1999, Dmitry Kovalev <mit@openldap.org>, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License. A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+
+LDAP_BEGIN_DECL
+
+extern BI_init sql_back_initialize;
+extern BI_destroy backsql_destroy;
+
+extern BI_db_init backsql_db_init;
+extern BI_db_open backsql_db_open;
+extern BI_db_close backsql_db_close;
+extern BI_db_destroy backsql_db_destroy;
+
+extern BI_db_config backsql_db_config;
+
+extern BI_op_bind backsql_bind;
+extern BI_op_unbind backsql_unbind;
+extern BI_op_search backsql_search;
+extern BI_op_compare backsql_compare;
+extern BI_op_modify backsql_modify;
+extern BI_op_modrdn backsql_modrdn;
+extern BI_op_add backsql_add;
+extern BI_op_delete backsql_delete;
+extern BI_op_abandon backsql_abandon;
+
+extern BI_operational backsql_operational;
+
+extern BI_connection_destroy backsql_connection_destroy;
+
+LDAP_END_DECL
+
+#endif /* _SQL_EXTERNAL_H */
bi->bi_acl_group = 0;
bi->bi_acl_attribute = 0;
bi->bi_chk_referrals = 0;
+ bi->bi_operational = backsql_operational;
bi->bi_connection_init = 0;
bi->bi_connection_destroy = backsql_connection_destroy;
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_init()\n", 0, 0, 0 );
si = (backsql_info *)ch_calloc( 1, sizeof( backsql_info ) );
+ memset( si, '\0', 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 );
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_destroy( &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 ) {
if ( si->dbhost ) {
free( si->dbhost );
}
- if ( si->upper_func ) {
- free( si->upper_func );
+ if ( si->upper_func.bv_val ) {
+ free( si->upper_func.bv_val );
+ free( si->upper_func_open.bv_val );
+ free( si->upper_func_close.bv_val );
}
- free( si->subtree_cond );
+ free( si->subtree_cond.bv_val );
free( si->oc_query );
free( si->at_query );
free( si->insentry_query );
backsql_info *si = (backsql_info*)bd->be_private;
Connection tmp;
SQLHDBC dbh;
- int idq_len;
+ ber_len_t idq_len;
struct berval bv;
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): "
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 );
+ "(use \"dbname\" directive in slapd.conf)\n", 0, 0, 0 );
return 1;
}
+
+ if ( si->concat_func == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "concat func not specified (use \"concat_pattern\" "
+ "directive in slapd.conf)\n", 0, 0, 0 );
+
+ if ( backsql_split_pattern( backsql_def_concat_func,
+ &si->concat_func, 2 ) ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "unable to parse pattern '%s'",
+ backsql_def_concat_func, 0, 0 );
+ return 1;
+ }
+ }
+
+ /*
+ * Prepare cast string as required
+ */
+ if ( si->upper_func.bv_val ) {
+ char buf[1024];
+
+ if ( BACKSQL_UPPER_NEEDS_CAST( si ) ) {
+ snprintf( buf, sizeof( buf ),
+ "%s(cast (" /* ? as varchar(%d))) */ ,
+ si->upper_func.bv_val );
+ ber_str2bv( buf, 0, 1, &si->upper_func_open );
+
+ snprintf( buf, sizeof( buf ),
+ /* (cast(? */ " as varchar(%d)))",
+ BACKSQL_MAX_DN_LEN );
+ ber_str2bv( buf, 0, 1, &si->upper_func_close );
+
+ } else {
+ snprintf( buf, sizeof( buf ), "%s(" /* ?) */ ,
+ si->upper_func.bv_val );
+ ber_str2bv( buf, 0, 1, &si->upper_func_open );
+
+ ber_str2bv( /* (? */ ")", 0, 1, &si->upper_func_close );
+ }
+ }
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 );
+ "(use \"dbuser\" directive in slapd.conf)\n", 0, 0, 0 );
return 1;
}
- if ( si->subtree_cond == NULL ) {
+ if ( si->subtree_cond.bv_val == NULL ) {
+ /*
+ * Prepare concat function for subtree search condition
+ */
+ struct berval concat;
+ ber_len_t len = 0;
+ struct berval values[] = {
+ { sizeof( "'%'" ) - 1, "'%'" },
+ { sizeof( "?" ) - 1, "?" },
+ { 0, NULL }
+ };
+
+ if ( backsql_prepare_pattern( si->concat_func, values,
+ &concat ) ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "unable to prepare CONCAT pattern", 0, 0, 0 );
+ return 1;
+ }
+
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"subtree search SQL condition not specified "
- "(use subtree_cond directive in slapd.conf)\n",
+ "(use \"subtree_cond\" directive in slapd.conf)\n",
+ 0, 0, 0);
+
+ si->subtree_cond.bv_val = NULL;
+ si->subtree_cond.bv_len = 0;
+
+ if ( si->upper_func.bv_val ) {
+
+ /*
+ * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%',?))
+ */
+
+ backsql_strfcat( &si->subtree_cond, &len, "blbbb",
+ &si->upper_func,
+ (ber_len_t)sizeof( "(ldap_entries.dn) LIKE " ) - 1,
+ "(ldap_entries.dn) LIKE ",
+ &si->upper_func_open,
+ &concat,
+ &si->upper_func_close );
+
+ } else {
+
+ /*
+ * ldap_entries.dn LIKE CONCAT('%',?)
+ */
+
+ backsql_strfcat( &si->subtree_cond, &len, "lb",
+ (ber_len_t)sizeof( "ldap_entries.dn LIKE " ) - 1,
+ "ldap_entries.dn LIKE ",
+ &concat );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "setting '%s' as default\n",
+ si->subtree_cond.bv_val, 0, 0 );
+ }
+
+ if ( si->children_cond.bv_val == NULL ) {
+ /*
+ * Prepare concat function for children search condition
+ */
+ struct berval concat;
+ ber_len_t len = 0;
+ struct berval values[] = {
+ { sizeof( "'%,'" ) - 1, "'%,'" },
+ { sizeof( "?" ) - 1, "?" },
+ { 0, NULL }
+ };
+
+ if ( backsql_prepare_pattern( si->concat_func, values,
+ &concat ) ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "unable to prepare CONCAT pattern", 0, 0, 0 );
+ return 1;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
+ "children search SQL condition not specified "
+ "(use \"children_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;
+ si->children_cond.bv_val = NULL;
+ si->children_cond.bv_len = 0;
+
+ if ( si->upper_func.bv_val ) {
+
+ /*
+ * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?))
+ */
+
+ backsql_strfcat( &si->children_cond, &len, "blbbb",
+ &si->upper_func,
+ (ber_len_t)sizeof( "(ldap_entries.dn) LIKE " ) - 1,
+ "(ldap_entries.dn) LIKE ",
+ &si->upper_func_open,
+ &concat,
+ &si->upper_func_close );
+
} else {
- si->subtree_cond = ch_strdup( backsql_def_subtree_cond );
+
+ /*
+ * ldap_entries.dn LIKE CONCAT('%,',?)
+ */
+
+ backsql_strfcat( &si->children_cond, &len, "lb",
+ (ber_len_t)sizeof( "ldap_entries.dn LIKE " ) - 1,
+ "ldap_entries.dn LIKE ",
+ &concat );
}
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting '%s' as default\n",
- si->subtree_cond, 0, 0 );
+ si->children_cond.bv_val, 0, 0 );
}
if ( si->oc_query == NULL ) {
+ if ( BACKSQL_CREATE_NEEDS_SELECT( si ) ) {
+ si->oc_query =
+ ch_strdup( backsql_def_needs_select_oc_query );
+
+ } else {
+ si->oc_query = ch_strdup( backsql_def_oc_query );
+ }
+
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"objectclass mapping SQL statement not specified "
- "(use oc_query directive in slapd.conf)\n", 0, 0, 0 );
+ "(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 );
+ "setting '%s' by default\n", si->oc_query, 0, 0 );
}
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",
+ "(use \"at_query\" directive in slapd.conf)\n",
0, 0, 0 );
Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting '%s' by default\n",
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",
+ "(use \"insentry_query\" directive in slapd.conf)\n",
0, 0, 0 );
Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting '%s' by default\n",
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",
+ "(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;
if ( backsql_get_db_conn( bd, &tmp, &dbh ) != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
return 1;
}
+ /*
+ * Prepare ID selection query
+ */
si->id_query = NULL;
idq_len = 0;
bv.bv_val = NULL;
bv.bv_len = 0;
- if ( si->upper_func == NULL ) {
+ if ( si->upper_func.bv_val == NULL ) {
backsql_strcat( &bv, &idq_len, backsql_id_query,
"dn=?", NULL );
} else {
- if ( si->has_ldapinfo_dn_ru ) {
+ if ( BACKSQL_HAS_LDAPINFO_DN_RU( si ) ) {
backsql_strcat( &bv, &idq_len, backsql_id_query,
"dn_ru=?", NULL );
} else {
- if ( si->isTimesTen ) {
- backsql_strcat( &bv, &idq_len,
+ if ( BACKSQL_USE_REVERSE_DN( si ) ) {
+ backsql_strfcat( &bv, &idq_len, "sbl",
backsql_id_query,
- si->upper_func, "(dn)=?",
- NULL );
+ &si->upper_func,
+ (ber_len_t)sizeof( "(dn)=?" ) - 1, "(dn)=?" );
} else {
- backsql_strcat( &bv, &idq_len,
+ backsql_strfcat( &bv, &idq_len, "sblbcb",
backsql_id_query,
- si->upper_func, "(dn)=",
- si->upper_func, "(?)", NULL );
+ &si->upper_func,
+ (ber_len_t)sizeof( "(dn)=" ) - 1, "(dn)=",
+ &si->upper_func_open,
+ '?',
+ &si->upper_func_close );
}
}
}
si->id_query = bv.bv_val;
+
+ /*
+ * Prepare children ID selection query
+ */
+ si->has_children_query = NULL;
+ idq_len = 0;
+
+ bv.bv_val = NULL;
+ bv.bv_len = 0;
+ backsql_strfcat( &bv, &idq_len, "sb",
+ "select count(*) from ldap_entries where ",
+ &si->children_cond );
+ si->has_children_query = bv.bv_val;
backsql_free_db_conn( bd, &tmp );
- if ( !si->schema_loaded ) {
+ if ( !BACKSQL_SCHEMA_LOADED( si ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"test failed, schema map not loaded - exiting\n",
0, 0, 0 );
#include "util.h"
/*
- * PostgreSQL doesn't work without :(
+ * PostgreSQL 7.0 doesn't work without :(
*/
#define BACKSQL_REALLOC_STMT
+/*
+ * Skip:
+ * - the first occurrence of objectClass, which is used
+ * to determine how to bulid the SQL entry (FIXME ?!?)
+ * - operational attributes
+ * empty attributes (FIXME ?!?)
+ */
+#define backsql_attr_skip(ad,vals) \
+ ( \
+ ( (ad) == slap_schema.si_ad_objectClass \
+ && (vals)[ 1 ].bv_val == NULL ) \
+ || is_at_operational( (ad)->ad_type ) \
+ || ( (vals)[ 0 ].bv_val == NULL ) \
+ )
+
static int
backsql_modify_internal(
backsql_info *bi,
SQLHDBC dbh,
backsql_oc_map_rec *oc,
backsql_entryID *e_id,
- Modifications *modlist )
+ Modifications *modlist,
+ const char **text )
{
RETCODE rc;
SQLHSTMT sth;
Modifications *ml;
+ int res = LDAP_SUCCESS;
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
"traversing modifications list\n", 0, 0, 0 );
+
+ *text = NULL;
+
#ifndef BACKSQL_REALLOC_STMT
SQLAllocStmt( dbh, &sth );
#endif /* BACKSQL_REALLOC_STMT */
+
for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
- AttributeDescription *ad;
+ AttributeDescription *ad;
backsql_at_map_rec *at = NULL;
struct berval *at_val;
Modification *c_mod;
#endif /* BACKSQL_REALLOC_STMT */
c_mod = &ml->sml_mod;
-
ad = c_mod->sm_desc;
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): attribute '%s'\n",
- ad->ad_cname.bv_val, 0, 0 );
+
+ Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
+ "modifying attribute '%s'\n",
+ ad->ad_cname.bv_val, 0, 0 );
+
+ if ( backsql_attr_skip( ad, c_mod->sm_bvalues ) ) {
+ continue;
+ }
+
at = backsql_ad2at( oc, ad );
if ( at == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
"attribute provided is not registered "
- "in objectclass '%s'\n",
+ "in objectClass '%s'\n",
ad->ad_cname.bv_val, 0, 0 );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ res = LDAP_UNWILLING_TO_PERFORM;
+ *text = "operation not permitted "
+ "within namingContext";
+ goto done;
+ }
+
continue;
}
case LDAP_MOD_REPLACE: {
SQLHSTMT asth;
BACKSQL_ROW_NTS row;
-
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+
+ Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
"replacing values for attribute '%s'\n",
- at->name.bv_val, 0, 0 );
+ at->ad->ad_cname.bv_val, 0, 0 );
if ( at->add_proc == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modify_internal(): "
"add procedure is not defined "
"for attribute '%s' "
"- unable to perform replacements\n",
- at->name.bv_val, 0, 0 );
+ at->ad->ad_cname.bv_val, 0, 0 );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ res = LDAP_UNWILLING_TO_PERFORM;
+ *text = "operation not permitted "
+ "within namingContext";
+ goto done;
+ }
+
break;
}
if ( at->delete_proc == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modify_internal(): "
"delete procedure is not defined "
"for attribute '%s' "
"- adding only\n",
- at->name.bv_val, 0, 0 );
+ at->ad->ad_cname.bv_val, 0, 0 );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ res = LDAP_UNWILLING_TO_PERFORM;
+ *text = "operation not permitted "
+ "within namingContext";
+ goto done;
+ }
+
goto add_only;
}
del_all:
rc = backsql_Prepare( dbh, &asth, at->query, 0 );
if ( rc != SQL_SUCCESS ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modify_internal(): "
"error preparing query\n", 0, 0, 0 );
backsql_PrintErrors( bi->db_env, dbh,
asth, rc );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ res = LDAP_OTHER;
+ *text = "SQL-backend error";
+ goto done;
+ }
+
break;
}
rc = backsql_BindParamID( asth, 1, &e_id->keyval );
if ( rc != SQL_SUCCESS ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modify_internal(): "
"error binding key value parameter\n",
0, 0, 0 );
backsql_PrintErrors( bi->db_env, dbh,
asth, rc );
SQLFreeStmt( asth, SQL_DROP );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ res = LDAP_OTHER;
+ *text = "SQL-backend error";
+ goto done;
+ }
+
break;
}
rc = SQLExecute( asth );
if ( !BACKSQL_SUCCESS( rc ) ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modify_internal(): "
"error executing attribute query\n",
0, 0, 0 );
backsql_PrintErrors( bi->db_env, dbh,
asth, rc );
SQLFreeStmt( asth, SQL_DROP );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ res = LDAP_OTHER;
+ *text = "SQL-backend error";
+ goto done;
+ }
+
break;
}
strlen( row.cols[ i ] ), 0 );
Debug( LDAP_DEBUG_TRACE,
- "backsql_modify(): "
+ "backsql_modify_internal(): "
"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(): "
+ "backsql_modify_internal(): "
"delete_proc "
"execution failed\n",
0, 0, 0 );
backsql_PrintErrors( bi->db_env,
dbh, sth, rc );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ res = LDAP_OTHER;
+ *text = "SQL-backend error";
+ goto done;
+ }
}
#ifdef BACKSQL_REALLOC_STMT
SQLFreeStmt( sth, SQL_DROP );
case SLAP_MOD_SOFTADD:
add_only:;
if ( at->add_proc == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modify_internal(): "
"add procedure is not defined "
"for attribute '%s'\n",
- at->name.bv_val, 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.bv_val, 0, 0 );
+ at->ad->ad_cname.bv_val, 0, 0 );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ res = LDAP_UNWILLING_TO_PERFORM;
+ *text = "operation not permitted "
+ "within namingContext";
+ goto done;
+ }
+
break;
}
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
"adding new values for attribute '%s'\n",
- at->name.bv_val, 0, 0 );
+ at->ad->ad_cname.bv_val, 0, 0 );
for ( i = 0, at_val = c_mod->sm_bvalues;
at_val->bv_val != NULL;
i++, at_val++ ) {
0, 0, at_val->bv_val,
at_val->bv_len, 0 );
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modify_internal(): "
"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(): "
+ "backsql_modify_internal(): "
"add_proc execution failed\n",
0, 0, 0 );
backsql_PrintErrors( bi->db_env,
dbh, sth, rc );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ res = LDAP_OTHER;
+ *text = "SQL-backend error";
+ goto done;
+ }
}
#ifdef BACKSQL_REALLOC_STMT
SQLFreeStmt( sth, SQL_DROP );
case LDAP_MOD_DELETE:
if ( at->delete_proc == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modify_internal(): "
"delete procedure is not defined "
"for attribute '%s'\n",
- at->name.bv_val, 0, 0 );
+ at->ad->ad_cname.bv_val, 0, 0 );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ res = LDAP_UNWILLING_TO_PERFORM;
+ *text = "operation not permitted "
+ "within namingContext";
+ goto done;
+ }
+
break;
}
if ( c_mod->sm_bvalues == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modify_internal(): "
"no values given to delete "
"for attribute '%s' "
"-- deleting all values\n",
- at->name.bv_val, 0, 0 );
+ at->ad->ad_cname.bv_val, 0, 0 );
goto del_all;
}
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
"deleting values for attribute '%s'\n",
- at->name.bv_val, 0, 0 );
+ at->ad->ad_cname.bv_val, 0, 0 );
+
for ( i = 0, at_val = c_mod->sm_bvalues;
at_val->bv_val != NULL;
i++, at_val++ ) {
0, 0, at_val->bv_val,
at_val->bv_len, 0 );
- Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
+ Debug( LDAP_DEBUG_TRACE,
+ "backsql_modify_internal(): "
"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(): "
+ "backsql_modify_internal(): "
"delete_proc execution "
"failed\n", 0, 0, 0 );
backsql_PrintErrors( bi->db_env,
dbh, sth, rc );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ res = LDAP_OTHER;
+ *text = "SQL-backend error";
+ goto done;
+ }
}
#ifdef BACKSQL_REALLOC_STMT
SQLFreeStmt( sth, SQL_DROP );
#endif /* BACKSQL_REALLOC_STMT */
}
+done:;
+
#ifndef BACKSQL_REALLOC_STMT
SQLFreeStmt( sth, SQL_DROP );
#endif /* BACKSQL_REALLOC_STMT */
/*
* FIXME: should fail in case one change fails?
*/
- return LDAP_SUCCESS;
+ return res;
}
int
SQLHDBC dbh;
backsql_oc_map_rec *oc = NULL;
backsql_entryID e_id;
+ Entry e;
int res;
+ const char *text = NULL;
/*
* FIXME: in case part of the operation cannot be performed
return 1;
}
- res = backsql_modify_internal( bi, dbh, oc, &e_id, modlist );
+ e.e_attrs = NULL;
+ e.e_name = *dn;
+ e.e_nname = *ndn;
+ if ( !acl_check_modlist( be, conn, op, &e, modlist )) {
+ res = LDAP_INSUFFICIENT_ACCESS;
+
+ } else {
+ res = backsql_modify_internal( bi, dbh, oc, &e_id,
+ modlist, &text );
+ }
+
if ( res == LDAP_SUCCESS ) {
/*
* Commit only if all operations succeed
*/
SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
}
- send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
+ send_ldap_result( conn, op, res, "", text, NULL, NULL );
Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n", 0, 0, 0 );
return 0;
const char *text = NULL;
LDAPRDN *new_rdn = NULL;
LDAPRDN *old_rdn = NULL;
+ Entry e;
Modifications *mod;
Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry '%s', "
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): entry id is %ld\n",
e_id.id, 0, 0 );
+ if ( backsql_has_children( bi, dbh, ndn ) == LDAP_COMPARE_TRUE ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+ "entry \"%s\" has children\n", dn->bv_val, 0, 0 );
+ send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
+ NULL, "subtree delete not supported",
+ NULL, NULL );
+ return 1;
+ }
+
dnParent( dn, &p_dn );
dnParent( ndn, &p_ndn );
+ /*
+ * namingContext "" is not supported
+ */
+ if ( p_dn.bv_len == 0 ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
+ "parent is \"\" - aborting\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
+ "", "not allowed within namingContext",
+ NULL, NULL );
+ goto modrdn_return;
+ }
+
+ /*
+ * Check for children access to parent
+ */
+ e.e_attrs = NULL;
+ e.e_name = p_dn;
+ e.e_nname = p_ndn;
+ if ( !access_allowed( be, conn, op, &e, slap_schema.si_ad_children,
+ NULL, ACL_WRITE, NULL ) ) {
+ Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 );
+ res = LDAP_INSUFFICIENT_ACCESS;
+ goto modrdn_return;
+ }
+
if ( newSuperior ) {
/*
* namingContext "" is not supported
new_pdn = newSuperior;
new_npdn = nnewSuperior;
+ e.e_name = *new_pdn;
+ e.e_nname = *new_npdn;
+
+ /*
+ * Check for children access to new parent
+ */
+ if ( !access_allowed( be, conn, op, &e,
+ slap_schema.si_ad_children,
+ NULL, ACL_WRITE, NULL ) ) {
+ Debug( LDAP_DEBUG_TRACE, "no access to new parent\n",
+ 0, 0, 0 );
+ res = LDAP_INSUFFICIENT_ACCESS;
+ goto modrdn_return;
+ }
+
} else {
new_pdn = &p_dn;
new_npdn = &p_ndn;
goto modrdn_return;
}
- /* Get attribute type and attribute value of our new rdn, we will
- * need to add that to our new entry
+ /*
+ * Get attribute type and attribute value of our new rdn,
+ * we will need to add that to our new entry
*/
if ( ldap_bv2rdn( newrdn, &new_rdn, (char **)&text,
LDAP_DN_FORMAT_LDAP ) ) {
}
}
- res = slap_modrdn2mods( NULL, NULL, NULL, NULL, old_rdn, new_rdn,
+ e.e_name = new_dn;
+ e.e_nname = new_ndn;
+ res = slap_modrdn2mods( be, conn, op, &e, old_rdn, new_rdn,
deleteoldrdn, &mod );
if ( res != LDAP_SUCCESS ) {
goto modrdn_return;
}
- oc = backsql_id2oc( bi, e_id.oc_id );
- res = backsql_modify_internal( bi, dbh, oc, &e_id, mod );
-
- if ( res != LDAP_SUCCESS ) {
+ if ( !acl_check_modlist( be, conn, op, &e, mod )) {
+ res = LDAP_INSUFFICIENT_ACCESS;
goto modrdn_return;
}
- /*
- * Commit only if all operations succeed
- *
- * FIXME: backsql_modify_internal() does not fail
- * if add/delete operations are not available, or
- * if a multiple value add actually results in a replace,
- * or if a single operation on an attribute fails for any
- * reason
- */
- SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
+ oc = backsql_id2oc( bi, e_id.oc_id );
+ res = backsql_modify_internal( bi, dbh, oc, &e_id, mod, &text );
+
+ if ( res == LDAP_SUCCESS ) {
+
+ /*
+ * Commit only if all operations succeed
+ *
+ * FIXME: backsql_modify_internal() does not fail
+ * if add/delete operations are not available, or
+ * if a multiple value add actually results in a replace,
+ * or if a single operation on an attribute fails for any
+ * reason
+ */
+ SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
+ }
modrdn_return:
SQLFreeStmt( sth, SQL_DROP );
}
}
- send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
+ send_ldap_result( conn, op, res, "", text, NULL, NULL );
Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );
return 0;
backsql_oc_map_rec *oc = NULL;
backsql_at_map_rec *at_rec = NULL;
backsql_entryID e_id, parent_id;
+ Entry p;
int res;
Attribute *at;
struct berval *at_val;
struct berval pdn;
- /* first parameter no, parameter order */
+ /* first parameter #, 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 );
+ e->e_name.bv_val, 0, 0 );
for ( at = e->e_attrs; at != NULL; at = at->a_next ) {
if ( at->a_desc == slap_schema.si_ad_objectClass ) {
- /*
- * FIXME: only the objectClass provided first
- * is considered when creating a new entry
- */
- oc = backsql_name2oc( bi, &at->a_vals[ 0 ] );
- break;
+ if ( global_schemacheck ) {
+ const char *text = NULL;
+ char textbuf[ 1024 ];
+ size_t textlen = sizeof( textbuf );
+ struct berval soc;
+
+ int rc = structural_class( at->a_vals, &soc,
+ NULL, &text, textbuf, textlen );
+ if ( rc != LDAP_SUCCESS ) {
+ break;
+ }
+ oc = backsql_name2oc( bi, &soc );
+
+ } else {
+
+ /*
+ * FIXME: only the objectClass provided first
+ * is considered when creating a new entry
+ */
+ oc = backsql_name2oc( bi, &at->a_vals[ 0 ] );
+ }
+ break;
}
}
"operation not permitted within namingContext",
NULL, NULL );
return 1;
+
+ } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
+ && oc->create_keyval == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+ "create procedure needs select, but none is defined"
+ "- aborting\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
+ "operation not permitted within namingContext",
+ NULL, NULL );
+ return 1;
}
prc = backsql_get_db_conn( be, conn, &dbh );
* is expected to return the id as the first column of a select
*/
+ p.e_attrs = NULL;
+ p.e_name = pdn;
+ dnParent( &e->e_nname, &p.e_nname );
+ if ( !access_allowed( be, conn, op, &p, slap_schema.si_ad_children,
+ NULL, ACL_WRITE, NULL ) ) {
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ return 1;
+ }
+
#ifndef BACKSQL_REALLOC_STMT
rc = SQLAllocStmt( dbh, &sth );
#else /* BACKSQL_REALLOC_STMT */
SWORD ncols;
SQLINTEGER is_null;
+ if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
+#ifndef BACKSQL_REALLOC_STMT
+ SQLFreeStmt( sth, SQL_RESET_PARAMS );
+#else /* BACKSQL_REALLOC_STMT */
+ SQLFreeStmt( sth, SQL_DROP );
+ rc = SQLAllocStmt( dbh, &sth );
+ if ( rc != SQL_SUCCESS ) {
+ send_ldap_result( conn, op, LDAP_OTHER, "",
+ "SQL-backend error", NULL, NULL );
+ return 1;
+ }
+#endif /* BACKSQL_REALLOC_STMT */
+
+ rc = SQLExecDirect( sth, oc->create_keyval, SQL_NTS );
+ if ( rc != SQL_SUCCESS ) {
+ send_ldap_result( conn, op, LDAP_OTHER, "",
+ "SQL-backend error", NULL, NULL );
+ return 1;
+ }
+ }
+
/*
* the query to know the id of the inserted entry
* must be embedded in the create procedure
} else if ( ncols != 1 ) {
Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
- "create_proc result is bogus\n",
- 0, 0, 0 );
+ "create_proc result is bogus (ncols=%d)\n",
+ ncols, 0, 0 );
backsql_PrintErrors( bi->db_env, dbh, sth, rc);
SQLFreeStmt( sth, SQL_DROP );
send_ldap_result( conn, op, LDAP_OTHER, "",
for ( at = e->e_attrs; at != NULL; at = at->a_next ) {
SQLUSMALLINT currpos;
- if ( at->a_vals[ 0 ].bv_val == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
+ "adding attribute '%s'\n",
+ at->a_desc->ad_cname.bv_val, 0, 0 );
+
+ /*
+ * Skip:
+ * - the first occurrence of objectClass, which is used
+ * to determine how to bulid the SQL entry (FIXME ?!?)
+ * - operational attributes
+ * empty attributes (FIXME ?!?)
+ */
+ if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
continue;
}
"in objectclass '%s'\n",
at->a_desc->ad_cname.bv_val,
oc->name.bv_val, 0 );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ send_ldap_result( conn, op,
+ LDAP_UNWILLING_TO_PERFORM, "",
+ "operation not permitted "
+ "within namingContext",
+ NULL, NULL );
+ return 1;
+ }
+
continue;
}
"add procedure is not defined "
"for attribute '%s'\n",
at->a_desc->ad_cname.bv_val, 0, 0 );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ send_ldap_result( conn, op,
+ LDAP_UNWILLING_TO_PERFORM, "",
+ "operation not permitted "
+ "within namingContext",
+ NULL, NULL );
+ return 1;
+ }
+
continue;
}
#ifdef BACKSQL_REALLOC_STMT
rc = backsql_Prepare( dbh, &sth, at_rec->add_proc, 0 );
if ( rc != SQL_SUCCESS ) {
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ send_ldap_result( conn, op,
+ LDAP_OTHER, "",
+ "SQL-backend error",
+ NULL, NULL );
+ return 1;
+ }
+
continue;
}
#endif /* BACKSQL_REALLOC_STMT */
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;
+ for ( i = 0, at_val = &at->a_vals[ i ];
+ at_val->bv_val != NULL;
i++, at_val = &at->a_vals[ i ] ) {
+ /*
+ * Do not deal with the objectClass that is used
+ * to build the entry
+ */
+ if ( at->a_desc == slap_schema.si_ad_objectClass ) {
+ if ( ber_bvcmp( at_val, &oc->name ) == 0 ) {
+ continue;
+ }
+ }
+
/*
* check for syntax needed here
* maybe need binary bind?
"add_proc execution failed\n",
0, 0, 0 );
backsql_PrintErrors( bi->db_env, dbh, sth, rc );
+
+ if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
+ send_ldap_result( conn, op,
+ LDAP_OTHER, "",
+ "SQL-backend error",
+ NULL, NULL );
+ return 1;
+ }
}
}
#ifndef BACKSQL_REALLOC_STMT
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 );
RETCODE rc;
backsql_oc_map_rec *oc = NULL;
backsql_entryID e_id;
+ Entry e;
int res;
/* first parameter no */
SQLUSMALLINT pno;
Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry '%s'\n",
ndn->bv_val, 0, 0 );
+
+ dnParent( dn, &e.e_name );
+ dnParent( ndn, &e.e_nname );
+ e.e_attrs = NULL;
+
+ /* check parent for "children" acl */
+ if ( !access_allowed( be, conn, op, &e, slap_schema.si_ad_children,
+ NULL, ACL_WRITE, NULL ) ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+ "no write access to parent\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ "", NULL, NULL, NULL );
+ return 1;
+
+ }
+
res = backsql_get_db_conn( be, conn, &dbh );
if ( res != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
return 1;
}
+ res = backsql_has_children( bi, dbh, ndn );
+ switch ( res ) {
+ case LDAP_COMPARE_TRUE:
+ Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
+ "entry \"%s\" has children\n", dn->bv_val, 0, 0 );
+ send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
+ NULL, "subtree delete not supported",
+ NULL, NULL );
+ return 1;
+
+ case LDAP_COMPARE_FALSE:
+ break;
+
+ default:
+ send_ldap_result( conn, op, res, NULL, NULL, NULL, NULL );
+ return 1;
+ }
+
oc = backsql_id2oc( 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 );
+ send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
+ "operation not permitted within namingContext",
+ NULL, NULL );
return 1;
}
"delete procedure is not defined "
"for this objectclass - aborting\n", 0, 0, 0 );
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
- "operation not supported for required DN",
+ "operation not permitted within namingContext",
NULL, NULL );
return 1;
}
#include "slap.h"
#include "back-sql.h"
#include "sql-wrap.h"
+#include "entry-id.h"
int
backsql_compare(
return 0;
}
+
+/*
+ * sets the supported operational attributes (if required)
+ */
+
+int
+backsql_operational(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ AttributeName *attrs,
+ int opattrs,
+ Attribute **a )
+{
+
+ backsql_info *bi = (backsql_info*)be->be_private;
+ SQLHDBC dbh = SQL_NULL_HDBC;
+ Attribute **aa = a;
+ int rc;
+
+ Debug( LDAP_DEBUG_TRACE, "==>backsql_operational(): entry '%s'\n",
+ e->e_nname.bv_val, 0, 0 );
+
+
+ if ( opattrs || ad_inlist( slap_schema.si_ad_hasSubordinates, attrs ) ) {
+ rc = backsql_get_db_conn( be, conn, &dbh );
+ if ( rc != LDAP_SUCCESS ) {
+ goto no_connection;
+ }
+
+ rc = backsql_has_children( bi, dbh, &e->e_nname );
+
+ switch( rc ) {
+ case LDAP_COMPARE_TRUE:
+ case LDAP_COMPARE_FALSE:
+ *aa = slap_operational_hasSubordinate( rc == LDAP_COMPARE_TRUE );
+ if ( *aa != NULL ) {
+ aa = &(*aa)->a_next;
+ }
+ rc = 0;
+ break;
+
+ default:
+ Debug(LDAP_DEBUG_TRACE,
+ "backsql_operational(): "
+ "has_children failed( %d)\n",
+ rc, 0, 0 );
+ rc = 1;
+ break;
+ }
+ }
+
+ return rc;
+
+no_connection:;
+ Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
+ "could not get connection handle - exiting\n",
+ 0, 0, 0 );
+ send_ldap_result( conn, op, rc, "",
+ rc == LDAP_OTHER ? "SQL-backend error" : "",
+ NULL, NULL );
+ return 1;
+}
+
#endif /* SLAPD_SQL */
keytbl varchar(64) not null,
keycol varchar(64) not null,
create_proc varchar(255),
+ create_keyval varchar(255),
delete_proc varchar(255),
expect_return integer not null
);
subtree_cond "upper(ldap_entries.dn) LIKE CONCAT('%',?)"
insentry_query "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select max(id)+1 from ldap_entries),?,?,?,?)"
upper_func "upper"
+upper_needs_cast "yes"
+create_needs_select "yes"
+has_ldapinfo_dn_ru "no"
drop table persons;
CREATE TABLE persons (
id int NOT NULL,
- name varchar(255) NOT NULL
+ name varchar(255) NOT NULL,
+ surname varchar(255) NOT NULL
);
drop table institutes;
insert into institutes (id,name) values (1,'sql');
-insert into persons (id,name) values (1,'Mitya Kovalev');
-insert into persons (id,name) values (2,'Torvlobnor Puzdoy');
-insert into persons (id,name) values (3,'Akakiy Zinberstein');
+insert into persons (id,name,surname) values (1,'Mitya','Kovalev');
+insert into persons (id,name,surname) values (2,'Torvlobnor','Puzdoy');
+insert into persons (id,name,surname) values (3,'Akakiy','Zinberstein');
insert into phones (id,phone,pers_id) values (1,'332-2334',1);
insert into phones (id,phone,pers_id) values (2,'222-3234',1);
--mappings
-insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return)
-values (1,'inetOrgPerson','persons','id','insert into persons (name) values ('''');\n select last_insert_id();',NULL,0);
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,create_keyval,delete_proc,expect_return)
+values (1,'inetOrgPerson','persons','id','insert into persons (id,name,surname) values ((select max(id)+1 from persons),'''','''')','select max(id) from persons',NULL,0);
-insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return)
-values (2,'document','documents','id',NULL,NULL,0);
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,create_keyval,delete_proc,expect_return)
+values (2,'document','documents','id',NULL,NULL,NULL,0);
-insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return)
-values (3,'organization','institutes','id',NULL,NULL,0);
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,create_keyval,delete_proc,expect_return)
+values (3,'organization','institutes','id',NULL,NULL,NULL,0);
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return)
-values (1,1,'cn','persons.name','persons',NULL,NULL,NULL,3,0);
+values (1,1,'cn','case when persons.name!='''' and persons.surname!='''' then persons.name||'' ''||persons.surname when persons.surname!='''' then persons.surname when persons.name!='''' then persons.name else '''' end','persons',NULL,NULL,NULL,3,0);
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return)
values (2,1,'telephoneNumber','phones.phone','persons,phones',
'phones.pers_id=persons.id',NULL,NULL,3,0);
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return)
-values (3,1,'sn','persons.name','persons',NULL,NULL,NULL,3,0);
+values (3,1,'sn','persons.surname','persons',NULL,'update persons set surname=? where id=?',NULL,3,0);
+
+insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return)
+values (6,1,'givenName','persons.name','persons',NULL,'update persons set name=? where id=?',NULL,3,0);
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return)
values (4,2,'description','documents.abstract','documents',NULL,NULL,NULL,3,0);
values (7,3,'o','institutes.name','institutes',NULL,NULL,NULL,3,0);
insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,add_proc,delete_proc,param_order,expect_return)
-values (8,1,'documentDN','ldap_entries.dn','ldap_entries,documents,authors_docs,persons',
+values (8,1,'documentAuthor','ldap_entries.dn','ldap_entries,documents,authors_docs,persons',
'ldap_entries.keyval=documents.id AND ldap_entries.oc_map_id=2 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',
NULL,NULL,3,0);
dbname PostgreSQL
dbuser postgres
dbpasswd postgres
-subtree_cond "upper(ldap_entries.dn) LIKE '%'||?"
insentry_query "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select max(id)+1 from ldap_entries),?,?,?,?)"
upper_func "upper"
strcast_func "text"
+concat_pattern "?||?"
has_ldapinfo_dn_ru no
backsql_at_map_rec *at_map )
{
struct berval tmps = { 0, NULL };
- int tmpslen = 0;
-
- backsql_strcat( &tmps, &tmpslen, "SELECT ", at_map->sel_expr,
- " AS ", at_map->name.bv_val,
- " 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 );
+ ber_len_t tmpslen = 0;
+
+ backsql_strfcat( &tmps, &tmpslen, "lblblblbcbl",
+ (ber_len_t)sizeof( "SELECT " ) - 1, "SELECT ",
+ &at_map->sel_expr,
+ (ber_len_t)sizeof( " AS " ) - 1, " AS ",
+ &at_map->ad->ad_cname,
+ (ber_len_t)sizeof( " FROM " ) - 1, " FROM ",
+ &at_map->from_tbls,
+ (ber_len_t)sizeof( " WHERE " ) - 1, " WHERE ",
+ &oc_map->keytbl,
+ '.',
+ &oc_map->keycol,
+ (ber_len_t)sizeof( "=?" ) - 1, "=?" );
+
+ if ( at_map->join_where.bv_val != NULL ) {
+ backsql_strfcat( &tmps, &tmpslen, "lb",
+ (ber_len_t)sizeof( " AND ") - 1, " AND ",
+ &at_map->join_where );
}
at_map->query = tmps.bv_val;
backsql_add_sysmaps( backsql_oc_map_rec *oc_map )
{
backsql_at_map_rec *at_map;
- int len;
- char s[ 30 ];
- struct berval bv;
+ char s[ 30 ];
+ ber_len_t len, slen;
+
snprintf( s, sizeof( s ), "%ld", oc_map->id );
+ slen = strlen( s );
at_map = (backsql_at_map_rec *)ch_calloc(1,
sizeof( backsql_at_map_rec ) );
at_map->ad = slap_schema.si_ad_objectClass;
- ber_dupbv( &at_map->name, &at_map->ad->ad_cname );
- 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 );
+ ber_str2bv( "ldap_entry_objclasses.oc_name", 0, 1, &at_map->sel_expr );
+ ber_str2bv( "ldap_entry_objclasses,ldap_entries", 0, 1,
+ &at_map->from_tbls );
+ len = at_map->from_tbls.bv_len + 1;
+ 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->join_where.bv_val = NULL;
+ at_map->join_where.bv_len = 0;
+ backsql_strfcat( &at_map->join_where, &len, "lbcbll",
+ (ber_len_t)sizeof( "ldap_entries.id=ldap_entry_objclasses.entry_id and ldap_entries.keyval=" ) - 1,
+ "ldap_entries.id=ldap_entry_objclasses.entry_id and ldap_entries.keyval=",
+ &oc_map->keytbl,
+ '.',
+ &oc_map->keycol,
+ (ber_len_t)sizeof( " and ldap_entries.oc_map_id=" ) - 1,
+ " and ldap_entries.oc_map_id=",
+ slen, s );
at_map->add_proc = NULL;
at_map->delete_proc = NULL;
at_map = (backsql_at_map_rec *)ch_calloc( 1,
sizeof( backsql_at_map_rec ) );
at_map->ad = slap_schema.si_ad_ref;
- ber_dupbv( &at_map->name, &at_map->ad->ad_cname );
- 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 );
+ ber_str2bv( "ldap_referrals.url", 0, 1, &at_map->sel_expr );
+ ber_str2bv( "ldap_referrals,ldap_entries", 0, 1, &at_map->from_tbls );
+ len = at_map->from_tbls.bv_len + 1;
+ 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_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->join_where.bv_val = NULL;
+ at_map->join_where.bv_len = 0;
+ backsql_strfcat( &at_map->join_where, &len, "lbcbll",
+ (ber_len_t)sizeof( "ldap_entries.id=ldap_referrals.entry_id and ldap_entries.keyval=" ) - 1,
+ "ldap_entries.id=ldap_referrals.entry_id and ldap_entries.keyval=",
+ &oc_map->keytbl,
+ '.',
+ &oc_map->keycol,
+ (ber_len_t)sizeof( " and ldap_entries.oc_map_id=" ) - 1,
+ " and ldap_entries.oc_map_id=",
+ slen, s );
at_map->add_proc = NULL;
at_map->delete_proc = NULL;
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 ) {
+ if ( !BACKSQL_DONTCHECK_LDAPINFO_DN_RU( si ) ) {
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 */
+ /* Yes, the field exists */
+ si->bsql_flags |= BSQLF_HAS_LDAPINFO_DN_RU;
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 */
+ /* No such field exists */
+ si->bsql_flags &= ~BSQLF_HAS_LDAPINFO_DN_RU;
}
SQLFreeStmt( oc_sth, SQL_DROP );
backsql_BindRowAsStrings( oc_sth, &oc_row );
rc = SQLFetch( oc_sth );
for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( oc_sth ) ) {
+ int colnum;
+
oc_map = (backsql_oc_map_rec *)ch_calloc( 1,
sizeof( backsql_oc_map_rec ) );
- oc_map->id = atoi( oc_row.cols[ 0 ] );
+ oc_map->id = strtol( oc_row.cols[ 0 ], NULL, 0 );
ber_str2bv( oc_row.cols[ 1 ], 0, 1, &oc_map->name );
oc_map->oc = oc_bvfind( &oc_map->name );
return LDAP_OTHER; /* undefined objectClass ? */
}
- oc_map->keytbl = ch_strdup( oc_row.cols[ 2 ] );
- oc_map->keycol = ch_strdup( oc_row.cols[ 3 ] );
+ ber_str2bv( oc_row.cols[ 2 ], 0, 1, &oc_map->keytbl );
+ ber_str2bv( oc_row.cols[ 3 ], 0, 1, &oc_map->keycol );
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 ] );
+
+ colnum = 5;
+ if ( BACKSQL_CREATE_NEEDS_SELECT( si ) ) {
+ colnum = 6;
+ oc_map->create_keyval = ( oc_row.is_null[ 5 ] < 0 )
+ ? NULL : ch_strdup( oc_row.cols[ 5 ] );
+ }
+ oc_map->delete_proc = ( oc_row.is_null[ colnum ] < 0 ) ? NULL
+ : ch_strdup( oc_row.cols[ colnum ] );
+ oc_map->expect_return = strtol( oc_row.cols[ colnum + 1 ],
+ NULL, 0 );
/*
* FIXME: first attempt to check for offending
oc_id = oc_map->id;
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"objectClass '%s': keytbl='%s' keycol='%s'\n",
- oc_map->name.bv_val, oc_map->keytbl, oc_map->keycol );
+ oc_map->name.bv_val,
+ oc_map->keytbl.bv_val, oc_map->keycol.bv_val );
if ( oc_map->create_proc ) {
Debug( LDAP_DEBUG_TRACE, "create_proc='%s'\n",
oc_map->create_proc, 0, 0 );
}
+ if ( oc_map->create_keyval ) {
+ Debug( LDAP_DEBUG_TRACE, "create_keyval='%s'\n",
+ oc_map->create_keyval, 0, 0 );
+ }
if ( oc_map->delete_proc ) {
Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n",
oc_map->delete_proc, 0, 0 );
}
Debug( LDAP_DEBUG_TRACE, "expect_return: "
- "add=%s, del=%s; attributes:\n",
+ "add=%d, del=%d; attributes:\n",
BACKSQL_IS_ADD( oc_map->expect_return ),
BACKSQL_IS_DEL( oc_map->expect_return ), 0 );
rc = SQLFetch( at_sth );
for ( ; BACKSQL_SUCCESS(rc); rc = SQLFetch( at_sth ) ) {
const char *text = NULL;
+ struct berval bv;
+ ber_len_t tmpslen;
Debug( LDAP_DEBUG_TRACE, "********'%s'\n",
at_row.cols[ 0 ], 0, 0 );
at_row.cols[ 8 ], 0, 0 );
at_map = (backsql_at_map_rec *)ch_calloc( 1,
sizeof( backsql_at_map_rec ) );
- ber_str2bv( at_row.cols[ 0 ], 0, 1, &at_map->name );
- rc = slap_bv2ad( &at_map->name, &at_map->ad, &text );
+ rc = slap_str2ad( at_row.cols[ 0 ],
+ &at_map->ad, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"attribute '%s' for objectClass '%s' "
"is not defined in schema: %s\n",
- at_map->name.bv_val,
+ at_map->ad->ad_cname.bv_val,
oc_map->name.bv_val, text );
return LDAP_CONSTRAINT_VIOLATION;
}
- 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;
+ ber_str2bv( at_row.cols[ 1 ], 0, 1, &at_map->sel_expr );
+ if ( at_row.is_null[ 8 ] < 0 ) {
+ at_map->sel_expr_u.bv_val = NULL;
+ at_map->sel_expr_u.bv_len = 0;
+ } else {
+ ber_str2bv( at_row.cols[ 8 ], 0, 1,
+ &at_map->sel_expr_u );
+ }
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 ] );
+ ber_str2bv( at_row.cols[ 2 ], 0, 0, &bv );
+ backsql_merge_from_clause( &at_map->from_tbls,
+ &tmpslen, &bv );
+ if ( at_row.is_null[ 3 ] < 0 ) {
+ at_map->join_where.bv_val = NULL;
+ at_map->join_where.bv_len = 0;
+ } else {
+ ber_str2bv( at_row.cols[ 3 ], 0, 1,
+ &at_map->join_where );
+ }
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 ] );
+ at_map->param_order = strtol( at_row.cols[ 6 ],
+ NULL, 0 );
+ at_map->expect_return = strtol( at_row.cols[ 7 ],
+ NULL, 0 );
backsql_make_attr_query( oc_map, at_map );
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"preconstructed query '%s'\n",
backsql_FreeRow( &oc_row );
SQLFreeStmt( at_sth, SQL_DROP );
SQLFreeStmt( oc_sth, SQL_DROP );
- si->schema_loaded = 1;
+ si->bsql_flags |= BSQLF_SCHEMA_LOADED;
Debug( LDAP_DEBUG_TRACE, "<==load_schema_map()\n", 0, 0, 0 );
return LDAP_SUCCESS;
}
{
backsql_oc_map_rec tmp, *res;
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>backsql_oc2oc(): "
"searching for objectclass with name='%s'\n",
objclass, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
tmp.oc = oc;
res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp,
(AVL_CMP)backsql_cmp_oc );
-#if 0
+#ifdef BACKSQL_TRACE
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
"found name='%s', id=%d\n", res->name, res->id, 0 );
Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
"not found\n", 0, 0, 0 );
}
-#endif
+#endif /* BACKSQL_TRACE */
return res;
}
{
backsql_oc_map_rec tmp, *res;
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>oc_with_name(): "
"searching for objectclass with name='%s'\n",
objclass, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
tmp.oc = oc_bvfind( oc_name );
if ( tmp.oc == NULL ) {
res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp,
(AVL_CMP)backsql_cmp_oc );
-#if 0
+#ifdef BACKSQL_TRACE
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
"found name='%s', id=%d\n", res->name, res->id, 0 );
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
"not found\n", 0, 0, 0 );
}
-#endif
+#endif /* BACKSQL_TRACE */
return res;
}
{
backsql_oc_map_rec tmp, *res;
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>oc_with_id(): "
"searching for objectclass with id='%d'\n", id, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
tmp.id = id;
res = (backsql_oc_map_rec *)avl_find( si->oc_by_id, &tmp,
(AVL_CMP)backsql_cmp_oc_id );
-#if 0
+#ifdef BACKSQL_TRACE
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
"found name='%s', id=%d\n", res->name, res->id, 0 );
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
"not found\n", 0, 0, 0 );
}
-#endif
+#endif /* BACKSQL_TRACE */
return res;
}
{
backsql_at_map_rec tmp, *res;
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>backsql_ad2at(): "
"searching for attribute '%s' for objectclass '%s'\n",
attr, objclass->name, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
+
tmp.ad = ad;
res = (backsql_at_map_rec *)avl_find( objclass->attrs, &tmp,
(AVL_CMP)backsql_cmp_attr );
-#if 0
+#ifdef BACKSQL_TRACE
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
"found name='%s', sel_expr='%s'\n",
- res->name, res->sel_expr, 0 );
+ res->name, res->sel_expr.bv_val, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
"not found\n", 0, 0, 0 );
}
-#endif
+#endif /* BACKSQL_TRACE */
return res;
}
backsql_at_map_rec tmp, *res;
const char *text = NULL;
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>backsql_name2at(): "
"searching for attribute '%s' for objectclass '%s'\n",
attr, objclass->name, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
if ( slap_bv2ad( attr, &tmp.ad, &text ) != LDAP_SUCCESS ) {
return NULL;
res = (backsql_at_map_rec *)avl_find( objclass->attrs, &tmp,
(AVL_CMP)backsql_cmp_attr );
-#if 0
+#ifdef BACKSQL_TRACE
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==backsql_name2at(): "
"found name='%s', sel_expr='%s'\n",
- res->name, res->sel_expr, 0 );
+ res->name, res->sel_expr.bv_val, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "<==backsql_name2at(): "
"not found\n", 0, 0, 0 );
}
-#endif
+#endif /* BACKSQL_TRACE */
return res;
}
backsql_free_attr( backsql_at_map_rec *at )
{
Debug( LDAP_DEBUG_TRACE, "==>free_attr(): '%s'\n",
- at->name.bv_val, 0, 0 );
- ch_free( at->name.bv_val );
- ch_free( at->sel_expr );
- if ( at->from_tbls != NULL ) {
- ch_free( at->from_tbls );
+ at->ad->ad_cname.bv_val, 0, 0 );
+ ch_free( at->sel_expr.bv_val );
+ if ( at->from_tbls.bv_val != NULL ) {
+ ch_free( at->from_tbls.bv_val );
}
- if ( at->join_where != NULL ) {
- ch_free( at->join_where );
+ if ( at->join_where.bv_val != NULL ) {
+ ch_free( at->join_where.bv_val );
}
if ( at->add_proc != NULL ) {
ch_free( at->add_proc );
}
/* TimesTen */
- if ( at->sel_expr_u ) {
- ch_free( at->sel_expr_u );
+ if ( at->sel_expr_u.bv_val ) {
+ ch_free( at->sel_expr_u.bv_val );
}
ch_free( at );
oc->name.bv_val, 0, 0 );
avl_free( oc->attrs, (AVL_FREE)backsql_free_attr );
ch_free( oc->name.bv_val );
- ch_free( oc->keytbl );
- ch_free( oc->keycol );
+ ch_free( oc->keytbl.bv_val );
+ ch_free( oc->keycol.bv_val );
if ( oc->create_proc != NULL ) {
ch_free( oc->create_proc );
}
+ if ( oc->create_keyval != NULL ) {
+ ch_free( oc->create_keyval );
+ }
if ( oc->delete_proc != NULL ) {
ch_free( oc->delete_proc );
}
* in file LICENSE in the top-level directory of the distribution.
*/
-
typedef struct {
+ /*
+ * FIXME: we explicitly keep the objectClass name because
+ * the ObjectClass structure does not use bervals (yet?)
+ */
struct berval name;
+ /*
+ * Structure of corresponding LDAP objectClass definition
+ */
ObjectClass *oc;
- char *keytbl;
- char *keycol;
+ struct berval keytbl;
+ struct berval keycol;
/* expected to return keyval of newly created entry */
char *create_proc;
+ /* in case create_proc does not return the keyval of the newly
+ * created row */
+ char *create_keyval;
/* supposed to expect keyval as parameter and delete
* all the attributes as well */
char *delete_proc;
} backsql_oc_map_rec;
typedef struct {
- /* literal name of corresponding LDAP attribute type */
- struct berval name;
+ /* Description of corresponding LDAP attribute type */
AttributeDescription *ad;
- char *from_tbls;
- char *join_where;
- char *sel_expr;
+ struct berval from_tbls;
+ struct berval join_where;
+ struct berval sel_expr;
/* supposed to expect 2 binded values: entry keyval
* and attr. value to add, like "add_name(?,?,?)" */
char *add_proc;
* 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) */
+ * second - for delete_proc) */
/* order of parameters for procedures above;
* 1 means "data then keyval", 0 means "keyval then data" */
int param_order;
* for return code) */
int expect_return;
/* TimesTen */
- char *sel_expr_u;
+ struct berval sel_expr_u;
} backsql_at_map_rec;
/* defines to support bitmasks above */
#include "entry-id.h"
#include "util.h"
-static struct berval AllUser = BER_BVC( LDAP_ALL_USER_ATTRIBUTES );
-static struct berval AllOper = BER_BVC( LDAP_ALL_OPERATIONAL_ATTRIBUTES );
-static struct berval NoAttrs = BER_BVC( LDAP_NO_ATTRS );
-
-#if 0
-static struct berval NoAttrs = BER_BVC( LDAP_NO_ATTRS );
-#endif
-
static int
backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad )
{
bsi->be = be;
bsi->conn = conn;
bsi->op = op;
+ bsi->attr_flags = 0;
/*
* FIXME: need to discover how to deal with 1.1 (NoAttrs)
/*
* ignore "+"
*/
- if ( BACKSQL_NCMP( &p->an_name, &AllOper ) == 0
- || BACKSQL_NCMP( &p->an_name, &NoAttrs ) == 0 ) {
+ if ( BACKSQL_NCMP( &p->an_name, &AllOper ) == 0 ) {
+ continue;
+
+ } else if ( BACKSQL_NCMP( &p->an_name, &NoAttrs ) == 0 ) {
+ bsi->attr_flags |= BSQL_SF_ALL_OPER;
continue;
}
if ( !f ) {
return 0;
}
-
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, "(", NULL );
+
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "c", '(' /* ) */ );
while ( 1 ) {
res = backsql_process_filter( bsi, f );
switch ( op ) {
case LDAP_FILTER_AND:
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
- " AND ", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "l",
+ (ber_len_t)sizeof( " AND " ) - 1,
+ " AND " );
break;
case LDAP_FILTER_OR:
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
- " OR ", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "l",
+ (ber_len_t)sizeof( " OR " ) - 1,
+ " OR " );
break;
}
}
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, /* ( */ ")", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "c", /* ( */ ')' );
return 1;
}
at = backsql_ad2at( bsi->oc, f->f_sub_desc );
+ assert( at );
+
/*
* When dealing with case-sensitive strings
* we may omit normalization; however, normalized
* SQL filters are more liberal.
*/
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, "(" /* ) */ , NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "c", '(' /* ) */ );
/* TimesTen */
- Debug( LDAP_DEBUG_TRACE, "expr: '%s' '%s'\n", at->sel_expr,
- at->sel_expr_u ? at->sel_expr_u : "<NULL>", 0 );
- if ( bsi->bi->upper_func ) {
+ Debug( LDAP_DEBUG_TRACE, "expr: '%s' '%s'\n", at->sel_expr.bv_val,
+ at->sel_expr_u.bv_val ? at->sel_expr_u.bv_val : "<NULL>", 0 );
+ if ( bsi->bi->upper_func.bv_val ) {
/*
* 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);
+ if ( at->sel_expr_u.bv_val ) {
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len,
+ "bl",
+ &at->sel_expr_u,
+ (ber_len_t)sizeof( " LIKE '" ) - 1,
+ " LIKE '" );
} else {
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
- bsi->bi->upper_func,
- "(", at->sel_expr, ")",
- " LIKE '", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len,
+ "bcbcl",
+ &bsi->bi->upper_func,
+ '(',
+ &at->sel_expr,
+ ')',
+ (ber_len_t)sizeof( " LIKE '" ) - 1,
+ " LIKE '" );
}
} else {
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
- at->sel_expr, " LIKE '", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "bl",
+ &at->sel_expr,
+ (ber_len_t)sizeof( " LIKE '" ) - 1, " LIKE '" );
}
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 ) {
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "b",
+ &f->f_sub_initial );
+ if ( bsi->bi->upper_func.bv_val ) {
ldap_pvt_str2upper( &bsi->flt_where.bv_val[ start ] );
}
}
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, "%", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "c", '%' );
if ( f->f_sub_any != NULL ) {
for ( i = 0; f->f_sub_any[ i ].bv_val != NULL; i++ ) {
size_t start;
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE,
"==>backsql_process_sub_filter(): "
"sub_any='%s'\n", f->f_sub_any[ i ].bv_val,
0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
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) {
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len,
+ "bc",
+ &f->f_sub_any[ i ],
+ '%' );
+ if ( bsi->bi->upper_func.bv_val ) {
/*
* Note: toupper('%') = '%'
*/
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 ) {
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "b",
+ &f->f_sub_final );
+ if ( bsi->bi->upper_func.bv_val ) {
ldap_pvt_str2upper( &bsi->flt_where.bv_val[ start ] );
}
}
}
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, /* ( */ "')", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "l",
+ (ber_len_t)sizeof( /* (' */ "')" ) - 1, /* ( */ "')" );
return 1;
}
backsql_process_filter( backsql_srch_info *bsi, Filter *f )
{
backsql_at_map_rec *at;
- backsql_at_map_rec oc_attr = { BER_BVC("objectClass"),
- slap_schema.si_ad_objectClass, "", "", NULL, NULL, NULL, NULL };
+ backsql_at_map_rec oc_attr = {
+ slap_schema.si_ad_objectClass, BER_BVC(""), BER_BVC(""),
+ { 0, NULL }, NULL, NULL, NULL };
AttributeDescription *ad = NULL;
- int done = 0, len = 0;
+ int done = 0;
+ ber_len_t len = 0;
/* TimesTen */
int rc = 0;
break;
case LDAP_FILTER_NOT:
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
- "NOT (", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "l",
+ (ber_len_t)sizeof( "NOT (" /* ) */ ) - 1,
+ "NOT (" /* ) */ );
rc = backsql_process_filter( bsi, f->f_not );
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len, ")", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "c",
+ /* ( */ ')' );
done = 1;
break;
goto done;
}
- if ( strcasecmp( ad->ad_cname.bv_val, "objectclass" ) ) {
+ if ( ad != slap_schema.si_ad_objectClass ) {
at = backsql_ad2at( bsi->oc, ad );
} 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.bv_val,
- "'", NULL );
- at->sel_expr = bv.bv_val;
+ backsql_strfcat( &at->sel_expr, &len, "cbc",
+ '\'',
+ &bsi->oc->name,
+ '\'' );
}
+
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.bv_val, 0 );
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
- " 1=0 ", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "l",
+ (ber_len_t)sizeof( " 1=0 " ) - 1, " 1=0 " );
goto impossible;
}
- backsql_merge_from_clause( &bsi->from.bv_val, &bsi->from_len,
- at->from_tbls );
+ 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, ad );
- 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 ( at->join_where.bv_val != NULL
+ && strstr( bsi->join_where.bv_val, at->join_where.bv_val ) == NULL ) {
+ backsql_strfcat( &bsi->join_where, &bsi->jwhere_len, "lb",
+ (ber_len_t)sizeof( " AND " ) - 1, " AND ",
+ &at->join_where );
}
-#if 0
+#if 0
+ /*
+ * FIXME: this is not required any more; however, note that
+ * attribute name syntax might collide with SQL legal aliases
+ */
if ( at != &oc_attr ) {
- backsql_strcat( &bsi->sel, &bsi->sel_len,
- ",", at->sel_expr, " AS ",
- at->name.bv_val, NULL );
+ backsql_strfcat( &bsi->sel, &bsi->sel_len, "cblb",
+ ',',
+ &at->sel_expr,
+ (ber_len_t)sizeof( " AS " ) - 1, " AS ",
+ &at->name );
}
#endif
* upper_func stuff is made for Oracle, where UPPER is
* safely applicable to NUMBER etc.
*/
- if ( bsi->bi->upper_func ) {
+ if ( bsi->bi->upper_func.bv_val ) {
size_t start;
- if ( at->sel_expr_u ) {
- backsql_strcat( &bsi->flt_where,
- &bsi->fwhere_len, "(",
- at->sel_expr_u, "='", NULL );
+ if ( at->sel_expr_u.bv_val ) {
+ backsql_strfcat( &bsi->flt_where,
+ &bsi->fwhere_len, "cbl",
+ '(',
+ &at->sel_expr_u,
+ (ber_len_t)sizeof( "='" ) - 1,
+ "='" );
} else {
- backsql_strcat( &bsi->flt_where,
- &bsi->fwhere_len, "(",
- bsi->bi->upper_func, "(",
- at->sel_expr, ")='", NULL );
+ backsql_strfcat( &bsi->flt_where,
+ &bsi->fwhere_len, "cbcbl",
+ '(' /* ) */ ,
+ &bsi->bi->upper_func,
+ '(' /* ) */ ,
+ &at->sel_expr,
+ (ber_len_t)sizeof( /* ( */ ")='" ) - 1,
+ /* ( */ ")='" );
}
start = bsi->flt_where.bv_len;
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
- f->f_av_value.bv_val, "')", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len,
+ "bl",
+ &f->f_av_value,
+ (ber_len_t)sizeof( /* (' */ "')" ) - 1,
+ /* (' */ "')" );
ldap_pvt_str2upper( &bsi->flt_where.bv_val[ start ] );
} else {
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
- "(", at->sel_expr, "='",
- f->f_av_value.bv_val, "')", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len,
+ "cblbl",
+ '(',
+ &at->sel_expr,
+ (ber_len_t)sizeof( "='" ) - 1, "='",
+ &f->f_av_value,
+ (ber_len_t)sizeof( /* (' */ "')" ) - 1,
+ /* (' */ "')" );
}
break;
case LDAP_FILTER_GE:
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
- "(", at->sel_expr, ">=",
- f->f_av_value.bv_val, ")", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "cblbc",
+ '(' /* ) */ ,
+ &at->sel_expr,
+ (ber_len_t)sizeof( ">=" ) - 1, ">=",
+ &f->f_av_value,
+ /* ( */ ')' );
break;
case LDAP_FILTER_LE:
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
- "(", at->sel_expr, "<=",
- f->f_av_value.bv_val, ")", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "cblbc",
+ '(' /* ) */ ,
+ &at->sel_expr,
+ (ber_len_t)sizeof( "<=" ) - 1, "<=",
+ &f->f_av_value,
+ /* ( */ ')' );
break;
case LDAP_FILTER_PRESENT:
- backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
- "NOT (", at->sel_expr, " IS NULL)", NULL );
+ backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "lbl",
+ (ber_len_t)sizeof( "NOT (" ) - 1, "NOT (",
+ &at->sel_expr,
+ (ber_len_t)sizeof( " IS NULL)" ) - 1, " IS NULL)" );
break;
case LDAP_FILTER_SUBSTRINGS:
}
done:
- if ( oc_attr.sel_expr != NULL ) {
- free( oc_attr.sel_expr );
+ if ( oc_attr.sel_expr.bv_val != NULL ) {
+ free( oc_attr.sel_expr.bv_val );
}
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 );
+ if ( oc_attr.sel_expr.bv_val != NULL ) {
+ free( oc_attr.sel_expr.bv_val );
}
Debug( LDAP_DEBUG_TRACE, "<==backsql_process_filter() returns -1\n",
0, 0, 0 );
backsql_srch_query( backsql_srch_info *bsi, struct berval *query )
{
backsql_info *bi = (backsql_info *)bsi->be->be_private;
- int q_len = 0;
+ ber_len_t q_len = 0;
int rc;
assert( query );
bsi->flt_where.bv_val = NULL;
bsi->flt_where.bv_len = 0;
bsi->fwhere_len = 0;
+
#if 0
+ /*
+ * FIXME: this query has been split in case a string cast function
+ * is defined; more sophisticated (pattern based) function should
+ * be used
+ */
backsql_strcat( &bsi->sel, &bsi->sel_len,
"SELECT DISTINCT ldap_entries.id,",
- bsi->oc->keytbl, ".", bsi->oc->keycol,
+ bsi->oc->keytbl.bv_val, ".", bsi->oc->keycol.bv_val,
",'", bsi->oc->name.bv_val, "' 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.bv_val, "')", NULL );
+
+ backsql_strfcat( &bsi->sel, &bsi->sel_len, "lbcbc",
+ (ber_len_t)sizeof( "SELECT DISTINCT ldap_entries.id," ) - 1,
+ "SELECT DISTINCT ldap_entries.id,",
+ &bsi->oc->keytbl,
+ '.',
+ &bsi->oc->keycol,
+ ',' );
+
+ if ( bi->strcast_func.bv_val ) {
+ backsql_strfcat( &bsi->sel, &bsi->sel_len, "blbl",
+ &bi->strcast_func,
+ (ber_len_t)sizeof( "('" /* ') */ ) - 1,
+ "('" /* ') */ ,
+ &bsi->oc->name,
+ (ber_len_t)sizeof( /* (' */ "')" ) - 1,
+ /* (' */ "')" );
} else {
- backsql_strcat( &bsi->sel, &bsi->sel_len,
- "'", bsi->oc->name.bv_val, "'", NULL );
+ backsql_strfcat( &bsi->sel, &bsi->sel_len, "cbc",
+ '\'',
+ &bsi->oc->name,
+ '\'' );
}
- 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 );
+ backsql_strfcat( &bsi->sel, &bsi->sel_len, "l",
+ (ber_len_t)sizeof( " AS objectClass,ldap_entries.dn AS dn" ) - 1,
+ " AS objectClass,ldap_entries.dn AS dn" );
+
+ backsql_strfcat( &bsi->from, &bsi->from_len, "lb",
+ (ber_len_t)sizeof( " FROM ldap_entries," ) - 1,
+ " FROM ldap_entries,",
+ &bsi->oc->keytbl );
+
+ backsql_strfcat( &bsi->join_where, &bsi->jwhere_len, "lbcbl",
+ (ber_len_t)sizeof( " WHERE " ) - 1, " WHERE ",
+ &bsi->oc->keytbl,
+ '.',
+ &bsi->oc->keycol,
+ (ber_len_t)sizeof( "=ldap_entries.keyval AND ldap_entries.oc_map_id=? AND " ) - 1,
+ "=ldap_entries.keyval AND ldap_entries.oc_map_id=? AND " );
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 );
+ if ( bsi->bi->upper_func.bv_val ) {
+ backsql_strfcat( &bsi->join_where, &bsi->jwhere_len,
+ "blbcb",
+ &bsi->bi->upper_func,
+ (ber_len_t)sizeof( "(ldap_entries.dn)=" ) - 1,
+ "(ldap_entries.dn)=",
+ &bsi->bi->upper_func_open,
+ '?',
+ &bsi->bi->upper_func_close );
} else {
- backsql_strcat( &bsi->join_where, &bsi->jwhere_len,
- "ldap_entries.dn=?", NULL );
+ backsql_strfcat( &bsi->join_where, &bsi->jwhere_len,
+ "l",
+ (ber_len_t)sizeof( "ldap_entries.dn=?" ) - 1,
+ "ldap_entries.dn=?" );
}
break;
case LDAP_SCOPE_ONELEVEL:
- backsql_strcat( &bsi->join_where, &bsi->jwhere_len,
- "ldap_entries.parent=?", NULL );
+ backsql_strfcat( &bsi->join_where, &bsi->jwhere_len, "l",
+ (ber_len_t)sizeof( "ldap_entries.parent=?" ) - 1,
+ "ldap_entries.parent=?" );
break;
case LDAP_SCOPE_SUBTREE:
- backsql_strcat( &bsi->join_where, &bsi->jwhere_len,
- bsi->bi->subtree_cond, NULL );
+ backsql_strfcat( &bsi->join_where, &bsi->jwhere_len, "b",
+ &bsi->bi->subtree_cond );
break;
default:
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 );
+ backsql_strfcat( query, &q_len, "bbblb",
+ &bsi->sel,
+ &bsi->from,
+ &bsi->join_where,
+ (ber_len_t)sizeof( " AND " ) - 1, " AND ",
+ &bsi->flt_where );
} else if ( rc < 0 ) {
/*
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.bv_val, 0, 0 );
+
+ if ( bsi->n_candidates == -1 ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
+ "unchecked limit has been overcome\n", 0, 0, 0 );
+ return 1;
+ }
+
bsi->oc = oc;
if ( backsql_srch_query( bsi, &query ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
}
break;
- case LDAP_SCOPE_SUBTREE:
+ case LDAP_SCOPE_SUBTREE: {
+
+ /*
+ * + 1 because we need room for '%'; this makes a subtree
+ * search for a DN BACKSQL_MAX_DN_LEN long legal
+ * if it returns that DN only
+ */
+ char temp_base_dn[ BACKSQL_MAX_DN_LEN + 1 + 1 ];
+
+ /*
+ * We do not accept DNs longer than BACKSQL_MAX_DN_LEN;
+ * however this should be handled earlier
+ */
+ assert( bsi->base_dn->bv_len <= BACKSQL_MAX_DN_LEN );
+
/*
* Sets the parameters for the SQL built earlier
* NOTE that all the databases could actually use
* 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 ) {
+ if ( BACKSQL_HAS_LDAPINFO_DN_RU( bsi->bi ) ) {
temp_base_dn[ 0 ] = '\0';
for ( i = 0, j = bsi->base_dn->bv_len - 1;
j >= 0; i++, j--) {
return 1;
}
break;
+ }
case LDAP_SCOPE_ONELEVEL:
res = backsql_dn2id( bsi->bi, &base_id,
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 ) {
- struct berval bv;
-
- ber_str2bv( row.cols[ i ],
- row.col_prec[ i ], 0, &bv );
-
- backsql_entry_addattr( e,
- &row.col_names[ i ], &bv );
-
- 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->id = strtol( row.cols[ 0 ], NULL, 0 );
+ c_id->keyval = strtol( row.cols[ 1 ], NULL, 0 );
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++;
+ 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 ] );
+
+ if ( bsi->n_candidates == -1 ) {
+ break;
+ }
}
backsql_FreeRow( &row );
SQLFreeStmt( sth, SQL_DROP );
"attributes to load: %s\n",
deref, attrsonly, attrs == NULL ? "all" : "custom list" );
+ if ( nbase->bv_len > BACKSQL_MAX_DN_LEN ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
+ "search base length (%ld) exceeds max length (%ld)\n",
+ nbase->bv_len, BACKSQL_MAX_DN_LEN, 0 );
+ /*
+ * FIXME: a LDAP_NO_SUCH_OBJECT could be appropriate
+ * since it is impossible that such a long DN exists
+ * in the backend
+ */
+ send_ldap_result( conn, op, LDAP_ADMINLIMIT_EXCEEDED,
+ "", NULL, NULL, NULL );
+ return 1;
+ }
+
sres = backsql_get_db_conn( be, conn, &dbh );
if ( sres != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
}
/* TimesTen : Pass it along to the lower level routines */
- srch_info.isTimesTen = bi->isTimesTen;
+ srch_info.use_reverse_dn = BACKSQL_USE_REVERSE_DN( bi );
/* if not root, get appropriate limits */
if ( be_isroot( be, &op->o_ndn ) ) {
* of entries matching LDAP query filter and scope (or at least
* candidates), and get the IDs
*/
+ srch_info.n_candidates = ( isroot ? -2 : limit->lms_s_unchecked == -1
+ ? -2 : limit->lms_s_unchecked );
avl_apply( bi->oc_by_oc, (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 ) {
+ if ( srch_info.n_candidates == -1 ) {
send_search_result( conn, op,
LDAP_ADMINLIMIT_EXCEEDED,
NULL, NULL, NULL, NULL, 0 );
* 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 ) {
+ for ( eid = srch_info.id_list; eid != NULL;
+ eid = backsql_free_entryID( eid, 1 ) ) {
/* check for abandon */
if ( op->o_abandon ) {
if ( tlimit != -1 && slap_get_time() > stoptime ) {
send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
NULL, NULL, v2refs, NULL, nentries );
- break;
+ goto end_of_search;
}
Debug(LDAP_DEBUG_TRACE, "backsql_search(): loading data "
== LDAP_COMPARE_TRUE ) {
sres = send_search_entry( be, conn, op, entry,
attrs, attrsonly, NULL );
- if ( sres == -1 ) {
+ switch ( sres ) {
+ case 0:
+ nentries++;
+ break;
+
+ case -1:
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
"connection lost\n", 0, 0, 0 );
+ goto end_of_search;
+
+ default:
+ /*
+ * FIXME: send_search_entry failed;
+ * better stop
+ */
break;
}
- nentries += !sres;
}
entry_free( entry );
- if ( slimit != -1 && nentries > slimit ) {
+ if ( slimit != -1 && nentries >= slimit ) {
send_search_result( conn, op, LDAP_SIZELIMIT_EXCEEDED,
NULL, NULL, v2refs, NULL, nentries );
- break;
+ goto end_of_search;
}
-
}
+end_of_search:;
+
if ( nentries > 0 ) {
send_search_result( conn, op,
v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
}
done:;
- for ( eid = srch_info.id_list; eid != NULL;
- eid = backsql_free_entryID( eid, 1 ) );
-
ch_free( srch_info.attrs );
Debug( LDAP_DEBUG_TRACE, "<==backsql_search()\n", 0, 0, 0 );
return rc;
}
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>_SQLPrepare()\n", 0, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
SQLGetInfo( dbh, SQL_DRIVER_NAME, drv_name, sizeof( drv_name ), &len );
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "_SQLPrepare(): driver name='%s'\n",
drv_name, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
ldap_pvt_str2upper( drv_name );
if ( !strncmp( drv_name, "SQLSRV32.DLL", sizeof( drv_name ) ) ) {
}
}
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "<==_SQLPrepare() calling SQLPrepare()\n",
0, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
return SQLPrepare( *sth, query, SQL_NTS );
}
return SQL_ERROR;
}
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==> backsql_BindRowAsStrings()\n", 0, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
rc = SQLNumResultCols( sth, &row->ncols );
if ( rc != SQL_SUCCESS ) {
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "_SQLBindRowAsStrings(): "
"SQLNumResultCols() failed:\n", 0, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC, sth, rc );
} else {
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"ncols=%d\n", (int)row->ncols, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
row->col_names = (BerVarray)ch_calloc( row->ncols + 1,
sizeof( struct berval ) );
&name_len, &col_type,
&col_prec, &col_scale, &col_null );
ber_str2bv( colname, 0, 1, &row->col_names[ i - 1 ] );
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"col_name=%s, col_prec[%d]=%d\n",
colname, (int)i, (int)col_prec );
-#endif
+#endif /* BACKSQL_TRACE */
if ( col_type == SQL_LONGVARCHAR
|| col_type == SQL_LONGVARBINARY) {
#if 0
row->col_names[ i - 1 ].bv_len = 0;
row->cols[ i - 1 ] = NULL;
}
-#if 0
+
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "<== backsql_BindRowAsStrings()\n", 0, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
return rc;
}
}
ber_bvarray_free( row->col_names );
- charray_free( row->cols );
+ ldap_charray_free( row->cols );
free( row->col_prec );
free( row->is_null );
backsql_free_db_env( backsql_info *si )
{
Debug( LDAP_DEBUG_TRACE, "==>backsql_free_db_env()\n", 0, 0, 0 );
-#if 0
+
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "free_db_env(): delete AVL tree here!!!\n",
0, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
/*
* stop, if frontend waits for all threads to shutdown
* See if this connection is to TimesTen. If it is,
* remember that fact for later use.
*/
- si->isTimesTen = 0; /* Assume until proven otherwise */
+ /* Assume until proven otherwise */
+ si->bsql_flags &= ~BSQLF_USE_REVERSE_DN;
DBMSName[ 0 ] = '\0';
rc = SQLGetInfo( dbc->dbh, SQL_DBMS_NAME, (PTR)&DBMSName,
sizeof( DBMSName ), NULL );
strcmp( DBMSName, "Front-Tier" ) == 0 ) {
Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
"TimesTen database!\n", 0, 0, 0 );
- si->isTimesTen = 1;
+ si->bsql_flags |= BSQLF_USE_REVERSE_DN;
}
} else {
Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
}
ldap_pvt_thread_mutex_lock( &si->schema_mutex );
- if ( !si->schema_loaded ) {
+ if ( !BACKSQL_SCHEMA_LOADED( si ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
"first call -- reading schema map\n", 0, 0, 0 );
rc = backsql_load_schema_map( si, dbc->dbh );
if ( rc != LDAP_SUCCESS ) {
+ ldap_pvt_thread_mutex_unlock( &si->schema_mutex );
backsql_free_db_conn( be, ldapc );
return rc;
}
#include "schema-map.h"
#include "util.h"
+#define BACKSQL_MAX(a,b) ((a)>(b)?(a):(b))
+#define BACKSQL_MIN(a,b) ((a)<(b)?(a):(b))
+
+#define BACKSQL_STR_GROW 256
char backsql_def_oc_query[] =
"SELECT id,name,keytbl,keycol,create_proc,delete_proc,expect_return "
"FROM ldap_oc_mappings";
+char backsql_def_needs_select_oc_query[] =
+ "SELECT id,name,keytbl,keycol,create_proc,create_keyval,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 "
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 ";
+/* better ?||? or cast(?||? as varchar) */
+char backsql_def_concat_func[] = "CONCAT(?,?)";
/* TimesTen */
char backsql_check_dn_ru_query[] = "SELECT dn_ru from ldap_entries";
-/*
- * Frequently used constants
- */
-struct berval
- bv_n_objectclass = BER_BVC("objectclass"),
- bv_n_0_10 = BER_BVC("0.10");
-
struct berval *
-backsql_strcat( struct berval *dest, int *buflen, ... )
+backsql_strcat( struct berval *dest, ber_len_t *buflen, ... )
{
va_list strs;
- int cdlen, cslen, grow;
+ ber_len_t cdlen, cslen, grow;
char *cstr;
assert( dest );
assert( dest->bv_val == NULL
|| dest->bv_len == strlen( dest->bv_val ) );
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>backsql_strcat()\n" );
-#endif
+#endif /* BACKSQL_TRACE */
va_start( strs, buflen );
- if ( dest->bv_val == NULL || *buflen <= 0 ) {
+ if ( dest->bv_val == NULL || *buflen == 0 ) {
dest->bv_val = (char *)ch_calloc( BACKSQL_STR_GROW,
sizeof( char ) );
dest->bv_len = 0;
if ( *buflen - cdlen <= cslen ) {
char *tmp_dest;
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_strcat(): "
"buflen=%d, cdlen=%d, cslen=%d "
"-- reallocating dest\n",
*buflen, cdlen + 1, cslen );
-#endif
+#endif /* BACKSQL_TRACE */
+
tmp_dest = (char *)ch_realloc( dest->bv_val,
( *buflen ) + grow * sizeof( char ) );
if ( tmp_dest == NULL ) {
}
dest->bv_val = tmp_dest;
*buflen += grow;
-#if 0
+
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_strcat(): "
"new buflen=%d, dest=%p\n", *buflen, dest, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
}
AC_MEMCPY( dest->bv_val + cdlen, cstr, cslen + 1 );
cdlen += cslen;
}
va_end( strs );
-#if 0
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "<==backsql_strcat() (dest='%s')\n",
dest, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
+
+ dest->bv_len = cdlen;
+
+ return dest;
+}
+
+struct berval *
+backsql_strfcat( struct berval *dest, ber_len_t *buflen, const char *fmt, ... )
+{
+ va_list strs;
+ ber_len_t cdlen;
+
+ assert( dest );
+ assert( buflen );
+ assert( fmt );
+ assert( *buflen == 0 || *buflen > dest->bv_len );
+ assert( dest->bv_val == NULL
+ || dest->bv_len == strlen( dest->bv_val ) );
+
+#ifdef BACKSQL_TRACE
+ Debug( LDAP_DEBUG_TRACE, "==>backsql_strfcat()\n" );
+#endif /* BACKSQL_TRACE */
+
+ va_start( strs, fmt );
+ 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;
+ for ( ; fmt[0]; fmt++ ) {
+ ber_len_t cslen, grow;
+ char *cstr, cc[ 2 ] = { '\0', '\0' };
+ struct berval *cbv;
+
+ switch ( fmt[ 0 ] ) {
+
+ /* berval */
+ case 'b':
+ cbv = va_arg( strs, struct berval * );
+ cstr = cbv->bv_val;
+ cslen = cbv->bv_len;
+ break;
+
+ /* length + string */
+ case 'l':
+ cslen = va_arg( strs, ber_len_t );
+ cstr = va_arg( strs, char * );
+ break;
+
+ /* string */
+ case 's':
+ cstr = va_arg( strs, char * );
+ cslen = strlen( cstr );
+ break;
+
+ /* char */
+ case 'c':
+ /*
+ * `char' is promoted to `int' when passed through `...'
+ */
+ cc[0] = va_arg( strs, int );
+ cstr = cc;
+ cslen = 1;
+ break;
+
+ default:
+ assert( 0 );
+ }
+
+ grow = BACKSQL_MAX( BACKSQL_STR_GROW, cslen );
+ if ( *buflen - cdlen <= cslen ) {
+ char *tmp_dest;
+
+#ifdef BACKSQL_TRACE
+ Debug( LDAP_DEBUG_TRACE, "backsql_strfcat(): "
+ "buflen=%d, cdlen=%d, cslen=%d "
+ "-- reallocating dest\n",
+ *buflen, cdlen + 1, cslen );
+#endif /* BACKSQL_TRACE */
+
+ tmp_dest = (char *)ch_realloc( dest->bv_val,
+ ( *buflen ) + grow * sizeof( char ) );
+ if ( tmp_dest == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "backsql_strfcat(): "
+ "could not reallocate string buffer.\n",
+ 0, 0, 0 );
+ return NULL;
+ }
+ dest->bv_val = tmp_dest;
+ *buflen += grow * sizeof( char );
+
+#ifdef BACKSQL_TRACE
+ Debug( LDAP_DEBUG_TRACE, "backsql_strfcat(): "
+ "new buflen=%d, dest=%p\n", *buflen, dest, 0 );
+#endif /* BACKSQL_TRACE */
+ }
+
+ AC_MEMCPY( dest->bv_val + cdlen, cstr, cslen + 1 );
+ cdlen += cslen;
+ }
+
+ va_end( strs );
+
+#ifdef BACKSQL_TRACE
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_strfcat() (dest='%s')\n",
+ dest, 0, 0 );
+#endif /* BACKSQL_TRACE */
dest->bv_len = cdlen;
struct berval *at_name,
struct berval *at_val )
{
- struct berval add_val[ 2 ];
AttributeDescription *ad;
int rc;
const char *text;
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(): "
"at_name='%s', at_val='%s'\n",
at_name->bv_val, at_val->bv_val, 0 );
- add_val[ 0 ] = *at_val;
- add_val[ 1 ].bv_val = NULL;
- add_val[ 1 ].bv_len = 0;
+#endif /* BACKSQL_TRACE */
ad = NULL;
rc = slap_bv2ad( at_name, &ad, &text );
return 0;
}
- rc = attr_merge( e, ad, add_val );
+ rc = attr_merge_one( e, ad, at_val );
if ( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(): "
at_val->bv_val, at_name->bv_val, 0 );
return 0;
}
-
+
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "<==backsql_query_addattr()\n", 0, 0, 0 );
+#endif /* BACKSQL_TRACE */
+
return 1;
}
{
char *s, *q;
struct berval res = { 0, NULL };
- int res_len = 0;
+ ber_len_t res_len = 0;
+
+ assert( p );
+ assert( *p );
s = *p;
while ( **p && **p != ',' ) {
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);
+ backsql_strfcat( &res, &res_len, "cs", ' ', s );
+
return res.bv_val;
}
int
-backsql_merge_from_clause( char **dest_from, int *dest_len, char *src_from )
+backsql_merge_from_clause(
+ struct berval *dest_from,
+ ber_len_t *dest_len,
+ struct berval *src_from )
{
char *s, *p, *srcc, *pos, e;
struct berval res = { 0 , NULL };
-#if 0
+#ifdef BACKSQL_TRACE
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 );
+ dest_from ? dest_from->bv_val : "<NULL>", src_from, 0 );
+#endif /* BACKSQL_TRACE */
+
+ srcc = ch_strdup( src_from->bv_val );
p = srcc;
- if ( *dest_from != NULL ) {
- res.bv_val = *dest_from;
- res.bv_len = strlen( *dest_from );
+ if ( dest_from != NULL ) {
+ res = *dest_from;
}
while ( *p ) {
s = backsql_get_table_spec( &p );
-#if 0
+
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_merge_from_clause(): "
"p='%s' s='%s'\n", p, s, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
+
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 );
+ backsql_strfcat( &res, dest_len, "cs", ',', s );
} else if ( ( e = pos[ strlen( s ) ] ) != '\0' && e != ',' ) {
- backsql_strcat( &res, dest_len, ",", s, NULL );
+ backsql_strfcat( &res, dest_len, "cs", ',', s );
}
}
ch_free( s );
}
}
-#if 0
+
+#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "<==backsql_merge_from_clause()\n", 0, 0, 0 );
-#endif
+#endif /* BACKSQL_TRACE */
+
free( srcc );
- *dest_from = res.bv_val;
+ *dest_from = res;
return 1;
}
+/*
+ * splits a pattern in components separated by '?'
+ * (double ?? are turned into single ? and left in the string)
+ * expected contains the number of expected occurrences of '?'
+ * (a negative value means parse as many as possible)
+ */
+
+int
+backsql_split_pattern(
+ const char *_pattern,
+ BerVarray *split_pattern,
+ int expected )
+{
+ char *pattern, *start, *end;
+ struct berval bv;
+ int rc = 0;
+
+#define SPLIT_CHAR '?'
+
+ assert( _pattern );
+ assert( split_pattern );
+
+ pattern = ch_strdup( _pattern );
+
+ start = pattern;
+ end = strchr( start, SPLIT_CHAR );
+ for ( ; start; expected-- ) {
+ char *real_end = end;
+ ber_len_t real_len;
+
+ if ( real_end == NULL ) {
+ real_end = start + strlen( start );
+
+ } else if ( real_end[ 1 ] == SPLIT_CHAR ) {
+ expected++;
+ AC_MEMCPY( real_end, real_end + 1, strlen( real_end ) );
+ end = strchr( real_end + 1, SPLIT_CHAR );
+ continue;
+ }
+
+ real_len = real_end - start;
+ if ( real_len == 0 ) {
+ ber_str2bv( "", 0, 1, &bv );
+ } else {
+ ber_str2bv( start, real_len, 1, &bv );
+ }
+
+ ber_bvarray_add( split_pattern, &bv );
+
+ if ( expected == 0 ) {
+ if ( end != NULL ) {
+ rc = -1;
+ goto done;
+ }
+ break;
+ }
+
+ if ( end != NULL ) {
+ start = end + 1;
+ end = strchr( start, SPLIT_CHAR );
+ }
+ }
+
+done:;
+
+ ch_free( pattern );
+
+ return rc;
+}
+
+int
+backsql_prepare_pattern(
+ BerVarray split_pattern,
+ BerVarray values,
+ struct berval *res )
+{
+ ber_len_t len = 0;
+ int i;
+
+ res->bv_val = NULL;
+ res->bv_len = 0;
+
+ for ( i = 0; values[i].bv_val; i++ ) {
+ if ( split_pattern[i].bv_val == NULL ) {
+ return -1;
+ }
+ backsql_strfcat( res, &len, "b", &split_pattern[ i ] );
+ backsql_strfcat( res, &len, "b", &values[ i ] );
+ }
+
+ if ( split_pattern[ i ].bv_val == NULL ) {
+ return -1;
+ }
+
+ backsql_strfcat( res, &len, "b", &split_pattern[ i ] );
+
+ return 0;
+}
+
#endif /* SLAPD_SQL */
#include "entry-id.h"
#include "schema-map.h"
-#define BACKSQL_MAX(a,b) ((a)>(b)?(a):(b))
-#define BACKSQL_MIN(a,b) ((a)<(b)?(a):(b))
+#define BACKSQL_CONCAT
-#define BACKSQL_STR_GROW 64
-
-extern struct berval
- bv_n_objectclass,
- bv_n_0_10;
-
-struct berval *backsql_strcat( struct berval *dest, int *buflen, ... );
+struct berval * backsql_strcat( struct berval *dest, ber_len_t *buflen, ... );
+struct berval * backsql_strfcat( struct berval *dest, ber_len_t *buflen,
+ const char *fmt, ... );
int backsql_entry_addattr( Entry *e, struct berval *at_name,
struct berval *at_val );
-typedef struct __backsql_srch_info {
+typedef struct backsql_srch_info {
struct berval *base_dn;
int scope;
Filter *filter;
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;
+ ber_len_t sel_len, from_len, jwhere_len, fwhere_len;
SQLHDBC dbh;
int status;
Backend *be;
Connection *conn;
Operation *op;
AttributeName *attrs;
+ int attr_flags;
+#define BSQL_SF_ALL_OPER 0x0001
Entry *e;
/* 1 if the db is TimesTen; 0 if it's not */
- int isTimesTen;
+ int use_reverse_dn;
} backsql_srch_info;
int backsql_process_filter( backsql_srch_info *bsi, Filter *f );
extern char
backsql_def_oc_query[],
+ backsql_def_needs_select_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[];
+ backsql_id_query[],
+ backsql_def_concat_func[];
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( struct berval *dest_from, ber_len_t *dest_len,
+ struct berval *src_from );
+int backsql_split_pattern( const char *pattern, BerVarray *split_pattern,
+ int expected );
+int backsql_prepare_pattern( BerVarray split_pattern, BerVarray values,
+ struct berval *res );
#endif /* __BACKSQL_UTIL_H__ */