Skip to content
Snippets Groups Projects
Commit 05348c5f authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

CHANGES:

- now all write operations appear to work correctly with PostgeSQL 7.0
- all write operations have been made transactional (atomic writes to
  entries are committed separately only in case of complete^1 success
  while all other operations are rolled-back by default)
- more cleanup and handling of exceptional conditions

TODO:
- deen to check with different databases and more up to date versions
  of both unixODBC and PostgreSQL.

^1: attribute add/modify/delete operations silently succeed if the
    appropriate add/delete proc does not exist for each attribute;
    this may be correct to hide undesired/unimplemented correspondence
    between LDAP and SQL databases; however, a more appropriate
    LDAP behavior would be a failure with LDAP_UNAVAILABLE if a
    single write operation cannot be executed for such reason
parent b95ab4ac
No related branches found
No related tags found
No related merge requests found
Showing
with 995 additions and 417 deletions
......@@ -35,7 +35,7 @@ typedef struct {
char *upper_func;
char *strcast_func;
Avlnode *db_conns;
Avlnode *oc_by_name;
Avlnode *oc_by_oc;
Avlnode *oc_by_id;
int schema_loaded;
ldap_pvt_thread_mutex_t dbconn_mutex;
......
......@@ -37,6 +37,7 @@ backsql_bind(
Entry *e, user_entry;
Attribute *a;
backsql_srch_info bsi;
int rc;
Debug( LDAP_DEBUG_TRACE, "==>backsql_bind()\n", 0, 0, 0 );
......@@ -59,13 +60,14 @@ backsql_bind(
/*
* method = LDAP_AUTH_SIMPLE
*/
dbh = backsql_get_db_conn( be, conn );
rc = backsql_get_db_conn( be, conn, &dbh );
if (!dbh) {
Debug( LDAP_DEBUG_TRACE, "backsql_bind(): "
"could not get connection handle - exiting\n",
0, 0, 0 );
send_ldap_result( conn, op, LDAP_OTHER, "",
"SQL-backend error", NULL, NULL );
send_ldap_result( conn, op, rc, "",
rc == LDAP_OTHER ? "SQL-backend error" : "",
NULL, NULL );
return 1;
}
......
......@@ -182,7 +182,7 @@ 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, at->name, bsi->c_eid->keyval );
bsi->oc->name.bv_val, at->name.bv_val, bsi->c_eid->keyval );
rc = backsql_Prepare( bsi->dbh, &sth, at->query, 0 );
if ( rc != SQL_SUCCESS ) {
......@@ -215,26 +215,28 @@ backsql_get_attr_vals( backsql_at_map_rec *at, backsql_srch_info *bsi )
for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
for ( i = 0; i < row.ncols; i++ ) {
if ( row.is_null[ i ] > 0 ) {
backsql_entry_addattr( bsi->e,
row.col_names[ i ],
row.cols[ i ],
struct berval bv;
bv.bv_val = row.cols[ i ];
#if 0
row.col_prec[ i ]
bv.bv_len = row.col_prec[ i ];
#else
/*
* FIXME: what if a binary
* is fetched?
*/
strlen( row.cols[ i ] )
/*
* FIXME: what if a binary
* is fetched?
*/
bv.bv_len = strlen( row.cols[ i ] );
#endif
);
backsql_entry_addattr( bsi->e,
&row.col_names[ i ], &bv );
#if 0
Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
(int)row.col_prec[ i ], 0, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "NULL value "
"in this row for attribute '%s'\n",
row.col_names[ i ], 0, 0 );
row.col_names[ i ].bv_val, 0, 0 );
#endif
}
}
......@@ -250,7 +252,7 @@ backsql_get_attr_vals( backsql_at_map_rec *at, backsql_srch_info *bsi )
Entry *
backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
{
char **c_at_name;
int i;
backsql_at_map_rec *at;
int rc;
......@@ -261,7 +263,7 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
return NULL;
}
bsi->oc = backsql_oc_with_id( bsi->bi, eid->oc_id );
bsi->oc = backsql_id2oc( bsi->bi, eid->oc_id );
bsi->e = e;
bsi->c_eid = eid;
e->e_attrs = NULL;
......@@ -274,24 +276,31 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
if ( bsi->attrs != NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
"custom attribute list\n", 0, 0, 0 );
for ( c_at_name = bsi->attrs; *c_at_name != NULL; c_at_name++ ) {
if ( !strcasecmp( *c_at_name, "objectclass" )
|| !strcasecmp( *c_at_name, "0.10" ) ) {
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 0 /* FIXME: what is 0.10 ? */
|| !BACKSQL_NCMP( &attr->an_name, &bv_n_0_10 )
#endif
) {
#if 0
backsql_entry_addattr( bsi->e, "objectclass",
bsi->oc->name,
strlen( bsi->oc->name ) );
backsql_entry_addattr( bsi->e,
&bv_n_objectclass,
&bsi->oc->name );
#endif
continue;
}
at = backsql_at_with_name( bsi->oc, *c_at_name );
at = backsql_ad2at( bsi->oc, attr->an_desc );
if ( at != NULL ) {
backsql_get_attr_vals( at, bsi );
} else {
Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
"attribute '%s' is not defined "
"for objectlass '%s'\n",
*c_at_name, bsi->oc->name, 0 );
attr->an_name.bv_val,
bsi->oc->name.bv_val, 0 );
}
}
} else {
......@@ -301,8 +310,7 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
bsi, 0, AVL_INORDER );
}
backsql_entry_addattr( bsi->e, "objectclass", bsi->oc->name,
strlen( bsi->oc->name ) );
backsql_entry_addattr( bsi->e, &bv_n_objectclass, &bsi->oc->name );
Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
......
......@@ -14,6 +14,7 @@
#include <stdio.h>
#include <sys/types.h>
#include "slap.h"
#include "ldap_pvt.h"
#include "back-sql.h"
#include "sql-wrap.h"
#include "schema-map.h"
......@@ -238,8 +239,7 @@ backsql_db_open(
}
tmp.c_connid =- 1;
dbh = backsql_get_db_conn( bd, &tmp );
if ( !dbh ) {
if ( backsql_get_db_conn( bd, &tmp, &dbh ) != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"connection failed, exiting\n", 0, 0, 0 );
return 1;
......
This diff is collapsed.
......@@ -17,12 +17,6 @@
#include "back-sql.h"
#include "sql-wrap.h"
int
backsql_dummy( void )
{
return 0;
}
int
backsql_compare(
BackendDB *bd,
......
drop table ldap_oc_mappings;
drop sequence ldap_oc_mappings_id_seq;
create table ldap_oc_mappings
(
id integer not null primary key,
id serial not null primary key,
name varchar(64) not null,
keytbl varchar(64) not null,
keycol varchar(64) not null,
......@@ -11,9 +12,10 @@ create table ldap_oc_mappings
);
drop table ldap_attr_mappings;
drop sequence ldap_attr_mappings_id_seq;
create table ldap_attr_mappings
(
id integer not null primary key,
id serial not null primary key,
oc_map_id integer not null references ldap_oc_mappings(id),
name varchar(255) not null,
sel_expr varchar(255) not null,
......@@ -27,9 +29,10 @@ create table ldap_attr_mappings
);
drop table ldap_entries;
drop sequence ldap_entries_id_seq;
create table ldap_entries
(
id integer not null primary key,
id serial not null primary key,
dn varchar(255) not null,
oc_map_id integer not null references ldap_oc_mappings(id),
parent int NOT NULL,
......@@ -52,9 +55,3 @@ create table ldap_entry_objclasses
oc_name varchar(64)
);
----- Apparently PostgreSQL 7.0 does not know concat(); however,
----- back-sql can be configured to use '||' for string concatenation.
----- Those who can't live without concat() can uncomment this:
-- drop function concat(text, text);
-- create function concat(text, text) returns text as 'select $1 || $2;' language 'sql';
drop table persons;
CREATE TABLE persons (
id int NOT NULL,
name varchar(255) NOT NULL,
PRIMARY KEY ( id )
drop sequence persons_id_seq;
create table persons (
id serial not null primary key,
name varchar(255) not null,
surname varchar(255) not null
);
drop table institutes;
CREATE TABLE institutes (
id int NOT NULL,
name varchar(255),
PRIMARY KEY ( id )
drop sequence institutes_id_seq;
create table institutes (
id serial not null primary key,
name varchar(255)
);
drop table documents;
CREATE TABLE documents (
id int NOT NULL,
title varchar(255) NOT NULL,
abstract varchar(255),
PRIMARY KEY ( id )
drop sequence documents_id_seq;
create table documents (
id serial not null primary key,
title varchar(255) not null,
abstract varchar(255)
);
drop table authors_docs;
CREATE TABLE authors_docs (
pers_id int NOT NULL,
doc_id int NOT NULL,
PRIMARY KEY ( pers_id, doc_id )
create table authors_docs (
pers_id int not null,
doc_id int not null,
primary key ( pers_id, doc_id )
);
drop table phones;
CREATE TABLE phones (
id int NOT NULL ,
phone varchar(255) NOT NULL ,
pers_id int NOT NULL,
PRIMARY KEY ( id )
drop sequence phones_id_seq;
create table phones (
id serial not null primary key,
phone varchar(255) not null ,
pers_id int not null
);
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);
......@@ -14,3 +14,4 @@ insert into documents (id,abstract,title) values (2,'abstract2','book2');
insert into authors_docs (pers_id,doc_id) values (1,1);
insert into authors_docs (pers_id,doc_id) values (1,2);
insert into authors_docs (pers_id,doc_id) values (2,1);
--mappings
insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return) values (1,'inetOrgPerson','persons','id','select create_person()',NULL,0);
insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return) values (1,'inetOrgPerson','persons','id','select create_person()','select delete_person(?)',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,delete_proc,expect_return) values (3,'organization','institutes','id',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,'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 (1,1,'cn','text(persons.name||'' ''||persons.surname)','persons',NULL,'select update_person_cn(?,?)',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 (2,1,'telephoneNumber','phones.phone','persons,phones','phones.pers_id=persons.id','select add_phone(?,?)','select delete_phone(?,?)',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);
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,'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 (6,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 (4,2,'description','documents.abstract','documents',NULL,NULL,NULL,3,0);
......@@ -24,7 +25,7 @@ insert into ldap_attr_mappings (id,oc_map_id,name,sel_expr,from_tbls,join_where,
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 (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','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);
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,'documentIdentifier','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);
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 (9,2,'documentAuthor','ldap_entries.dn','ldap_entries,documents,authors_docs,persons','ldap_entries.keyval=persons.id AND ldap_entries.oc_map_id=1 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',NULL,NULL,3,0);
......@@ -52,7 +53,48 @@ insert into ldap_referrals (entry_id,url) values (4,'http://localhost');
-- procedures
create function create_person () returns int
as 'insert into persons (id,name) values ((select max(id)+1 from persons),'''');
select max(id) from persons'
language 'sql';
as '
select setval (''persons_id_seq'', (select max(id) from persons));
insert into persons (id,name,surname)
values (nextval(''persons_id_seq''),'''','''');
select max(id) from persons
' language 'sql';
create function update_person_cn (varchar, int) returns int
as '
update persons set name = (
select case
when position('' '' in $1) = 0 then $1
else substr($1, 1, position('' '' in $1) - 1)
end
),surname = (
select case
when position('' '' in $1) = 0 then ''''
else substr($1, position('' '' in $1) + 1)
end
) where id = $2;
select $2 as return
' language 'sql';
create function delete_person (int) returns int
as '
delete from phones where pers_id = $1;
delete from authors_docs where pers_id = $1;
delete from persons where id = $1;
select $1 as return
' language 'sql';
create function add_phone (varchar, int) returns int
as '
select setval (''phones_id_seq'', (select max(id) from phones));
insert into phones (id,phone,pers_id)
values (nextval(''phones_id_seq''),$1,$2);
select max(id) from phones
' language 'sql';
create function delete_phone (varchar, int) returns int
as '
delete from phones where phone = $1 and pers_id = $2;
select $2 as result
' language 'sql';
......@@ -15,40 +15,59 @@
#include <sys/types.h>
#include <string.h>
#include "slap.h"
#include "ldap_pvt.h"
#include "back-sql.h"
#include "sql-wrap.h"
#include "schema-map.h"
#include "util.h"
int backsql_dummy( void *, void * );
int
/*
* Deprecated
*/
#if 0
static int
backsql_cmp_oc_name( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
{
return strcasecmp( m1->name, m2->name );
return BACKSQL_NCMP( &m1->name, &m2->name );
}
#endif
int
/*
* Uses the pointer to the ObjectClass structure
*/
static int
backsql_cmp_oc( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
{
return ( m1->oc < m2->oc ? -1 : ( m1->oc > m2->oc ? 1 : 0 ) );
}
static int
backsql_cmp_oc_id( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
{
if ( m1->id < m2->id ) {
return -1;
}
if ( m1->id > m2->id ) {
return 1;
}
return 0;
return ( m1->id < m2->id ? -1 : ( m1->id > m2->id ? 1 : 0 ) );
}
int
backsql_cmp_attr(
backsql_at_map_rec *m1,
backsql_at_map_rec *m2 )
/*
* Deprecated
*/
#if 0
static int
backsql_cmp_attr_name( backsql_at_map_rec *m1, backsql_at_map_rec *m2 )
{
return strcasecmp( m1->name, m2->name );
return BACKSQL_NCMP( &m1->name, &m2->name );
}
#endif
char *
/*
* Uses the pointer to the AttributeDescription structure
*/
static int
backsql_cmp_attr( backsql_at_map_rec *m1, backsql_at_map_rec *m2 )
{
return ( m1->ad < m2->ad ? -1 : ( m1->ad > m2->ad ? 1 : 0 ) );
}
static int
backsql_make_attr_query(
backsql_oc_map_rec *oc_map,
backsql_at_map_rec *at_map )
......@@ -57,7 +76,8 @@ backsql_make_attr_query(
int tmpslen = 0;
backsql_strcat( &tmps, &tmpslen, "SELECT ", at_map->sel_expr,
" AS ", at_map->name, " FROM ", at_map->from_tbls,
" 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 ) {
......@@ -67,10 +87,10 @@ backsql_make_attr_query(
at_map->query = tmps.bv_val;
return at_map->query;
return 0;
}
int
static int
backsql_add_sysmaps( backsql_oc_map_rec *oc_map )
{
backsql_at_map_rec *at_map;
......@@ -82,11 +102,13 @@ backsql_add_sysmaps( backsql_oc_map_rec *oc_map )
at_map = (backsql_at_map_rec *)ch_calloc(1,
sizeof( backsql_at_map_rec ) );
at_map->name = ch_strdup( "objectClass" );
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 );
len = 0;
bv.bv_val = NULL;
bv.bv_len = 0;
......@@ -96,25 +118,24 @@ backsql_add_sysmaps( backsql_oc_map_rec *oc_map )
oc_map->keytbl, ".", oc_map->keycol,
" and ldap_entries.oc_map_id=", s, NULL );
at_map->join_where = bv.bv_val;
at_map->add_proc = NULL;
at_map->delete_proc = NULL;
at_map->param_order = 0;
at_map->expect_return = 0;
backsql_make_attr_query( oc_map, at_map );
avl_insert( &oc_map->attrs, at_map,
(AVL_CMP)backsql_cmp_attr, backsql_dummy );
(AVL_CMP)backsql_cmp_attr, NULL );
at_map = (backsql_at_map_rec *)ch_calloc( 1,
sizeof( backsql_at_map_rec ) );
at_map->name = ch_strdup( "ref" );
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 );
/* FIXME: no free? */
at_map->join_where = NULL;
len = 0;
bv.bv_val = NULL;
bv.bv_len = 0;
......@@ -124,13 +145,14 @@ backsql_add_sysmaps( backsql_oc_map_rec *oc_map )
oc_map->keytbl, ".", oc_map->keycol,
" and ldap_entries.oc_map_id=", s, NULL );
at_map->join_where = bv.bv_val;
at_map->add_proc = NULL;
at_map->delete_proc = NULL;
at_map->param_order = 0;
at_map->expect_return = 0;
backsql_make_attr_query( oc_map, at_map );
avl_insert( &oc_map->attrs, at_map,
(AVL_CMP)backsql_cmp_attr, backsql_dummy );
(AVL_CMP)backsql_cmp_attr, NULL );
return 1;
}
......@@ -173,7 +195,7 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
"error preparing oc_query: '%s'\n",
si->oc_query, 0, 0 );
backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
return -1;
return LDAP_OTHER;
}
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): at_query '%s'\n",
si->at_query, 0, 0 );
......@@ -184,7 +206,7 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
"error preparing at_query: '%s'\n",
si->at_query, 0, 0 );
backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
return -1;
return LDAP_OTHER;
}
rc = backsql_BindParamID( at_sth, 1, &oc_id );
......@@ -192,7 +214,7 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"error binding param for at_query: \n", 0, 0, 0 );
backsql_PrintErrors( si->db_env, dbh, at_sth, rc );
return -1;
return LDAP_OTHER;
}
rc = SQLExecute( oc_sth );
......@@ -200,7 +222,7 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"error executing oc_query: \n", 0, 0, 0 );
backsql_PrintErrors( si->db_env, dbh, oc_sth, rc );
return -1;
return LDAP_OTHER;
}
backsql_BindRowAsStrings( oc_sth, &oc_row );
......@@ -208,8 +230,18 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( oc_sth ) ) {
oc_map = (backsql_oc_map_rec *)ch_calloc( 1,
sizeof( backsql_oc_map_rec ) );
oc_map->id = atoi( oc_row.cols[ 0 ] );
oc_map->name = ch_strdup( oc_row.cols[ 1 ] );
ber_str2bv( oc_row.cols[ 1 ], 0, 1, &oc_map->name );
oc_map->oc = oc_bvfind( &oc_map->name );
if ( oc_map->oc == NULL ) {
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"objectClass '%s' is not defined in schema\n",
oc_map->name.bv_val, 0, 0 );
return LDAP_OTHER; /* undefined objectClass ? */
}
oc_map->keytbl = ch_strdup( oc_row.cols[ 2 ] );
oc_map->keycol = ch_strdup( oc_row.cols[ 3 ] );
oc_map->create_proc = ( oc_row.is_null[ 4 ] < 0 ) ? NULL
......@@ -224,24 +256,26 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
*/
oc_map->attrs = NULL;
avl_insert( &si->oc_by_name, oc_map,
(AVL_CMP)backsql_cmp_oc_name, backsql_dummy );
avl_insert( &si->oc_by_oc, oc_map,
(AVL_CMP)backsql_cmp_oc, NULL );
avl_insert( &si->oc_by_id, oc_map,
(AVL_CMP)backsql_cmp_oc_id, backsql_dummy );
(AVL_CMP)backsql_cmp_oc_id, NULL );
oc_id = oc_map->id;
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"objectClass '%s': keytbl='%s' keycol='%s'\n",
oc_map->name, oc_map->keytbl, oc_map->keycol );
if ( oc_map->delete_proc ) {
Debug( LDAP_DEBUG_TRACE, "delete_proc='%s'\n",
oc_map->delete_proc, 0, 0 );
}
oc_map->name.bv_val, oc_map->keytbl, oc_map->keycol );
if ( oc_map->create_proc ) {
Debug( LDAP_DEBUG_TRACE, "create_proc='%s'\n",
oc_map->create_proc, 0, 0 );
}
Debug( LDAP_DEBUG_TRACE, "expect_return=%d; attributes:\n",
oc_map->expect_return, 0, 0 );
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",
BACKSQL_IS_ADD( oc_map->expect_return ),
BACKSQL_IS_DEL( oc_map->expect_return ), 0 );
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"autoadding 'objectClass' and 'ref' mappings\n",
......@@ -252,12 +286,14 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"error executing at_query: \n", 0, 0, 0 );
backsql_PrintErrors( SQL_NULL_HENV, dbh, at_sth, rc );
return -1;
return LDAP_OTHER;
}
backsql_BindRowAsStrings( at_sth, &at_row );
rc = SQLFetch( at_sth );
for ( ; BACKSQL_SUCCESS(rc); rc = SQLFetch( at_sth ) ) {
const char *text = NULL;
Debug( LDAP_DEBUG_TRACE, "********'%s'\n",
at_row.cols[ 0 ], 0, 0 );
Debug( LDAP_DEBUG_TRACE,
......@@ -274,7 +310,17 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
at_row.cols[ 8 ], 0, 0 );
at_map = (backsql_at_map_rec *)ch_calloc( 1,
sizeof( backsql_at_map_rec ) );
at_map->name = ch_strdup( at_row.cols[ 0 ] );
ber_str2bv( at_row.cols[ 0 ], 0, 1, &at_map->name );
rc = slap_bv2ad( &at_map->name, &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,
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 ] );
......@@ -296,8 +342,7 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
"preconstructed query '%s'\n",
at_map->query, 0, 0 );
avl_insert( &oc_map->attrs, at_map,
(AVL_CMP)backsql_cmp_attr,
backsql_dummy );
(AVL_CMP)backsql_cmp_attr, NULL );
}
backsql_FreeRow( &at_row );
SQLFreeStmt( at_sth, SQL_CLOSE );
......@@ -307,11 +352,41 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
SQLFreeStmt( oc_sth, SQL_DROP );
si->schema_loaded = 1;
Debug( LDAP_DEBUG_TRACE, "<==load_schema_map()\n", 0, 0, 0 );
return 1;
return LDAP_SUCCESS;
}
backsql_oc_map_rec *
backsql_oc_with_name( backsql_info *si, char *objclass )
backsql_oc2oc( backsql_info *si, ObjectClass *oc )
{
backsql_oc_map_rec tmp, *res;
#if 0
Debug( LDAP_DEBUG_TRACE, "==>backsql_oc2oc(): "
"searching for objectclass with name='%s'\n",
objclass, 0, 0 );
#endif
tmp.oc = oc;
res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp,
(AVL_CMP)backsql_cmp_oc );
#if 0
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
"found name='%s', id=%d\n", res->name, res->id, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
"not found\n", 0, 0, 0 );
}
#endif
return res;
}
/*
* Deprecated
*/
backsql_oc_map_rec *
backsql_name2oc( backsql_info *si, struct berval *oc_name )
{
backsql_oc_map_rec tmp, *res;
......@@ -320,10 +395,14 @@ backsql_oc_with_name( backsql_info *si, char *objclass )
"searching for objectclass with name='%s'\n",
objclass, 0, 0 );
#endif
tmp.name = objclass;
res = (backsql_oc_map_rec *)avl_find( si->oc_by_name, &tmp,
(AVL_CMP)backsql_cmp_oc_name );
tmp.oc = oc_bvfind( oc_name );
if ( tmp.oc == NULL ) {
return NULL;
}
res = (backsql_oc_map_rec *)avl_find( si->oc_by_oc, &tmp,
(AVL_CMP)backsql_cmp_oc );
#if 0
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
......@@ -338,7 +417,7 @@ backsql_oc_with_name( backsql_info *si, char *objclass )
}
backsql_oc_map_rec *
backsql_oc_with_id( backsql_info *si, unsigned long id )
backsql_id2oc( backsql_info *si, unsigned long id )
{
backsql_oc_map_rec tmp, *res;
......@@ -365,26 +444,26 @@ backsql_oc_with_id( backsql_info *si, unsigned long id )
}
backsql_at_map_rec *
backsql_at_with_name( backsql_oc_map_rec* objclass, char *attr )
backsql_ad2at( backsql_oc_map_rec* objclass, AttributeDescription *ad )
{
backsql_at_map_rec tmp, *res;
#if 0
Debug( LDAP_DEBUG_TRACE, "==>at_with_name(): "
Debug( LDAP_DEBUG_TRACE, "==>backsql_ad2at(): "
"searching for attribute '%s' for objectclass '%s'\n",
attr, objclass->name, 0 );
#endif
tmp.name = attr;
tmp.ad = ad;
res = (backsql_at_map_rec *)avl_find( objclass->attrs, &tmp,
(AVL_CMP)backsql_cmp_attr );
#if 0
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==at_with_name(): "
Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
"found name='%s', sel_expr='%s'\n",
res->name, res->sel_expr, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "<==at_with_name(): "
Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
"not found\n", 0, 0, 0 );
}
#endif
......@@ -392,11 +471,48 @@ backsql_at_with_name( backsql_oc_map_rec* objclass, char *attr )
return res;
}
int
/*
* Deprecated
*/
backsql_at_map_rec *
backsql_name2at( backsql_oc_map_rec* objclass, struct berval *attr )
{
backsql_at_map_rec tmp, *res;
const char *text = NULL;
#if 0
Debug( LDAP_DEBUG_TRACE, "==>backsql_name2at(): "
"searching for attribute '%s' for objectclass '%s'\n",
attr, objclass->name, 0 );
#endif
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
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==backsql_name2at(): "
"found name='%s', sel_expr='%s'\n",
res->name, res->sel_expr, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "<==backsql_name2at(): "
"not found\n", 0, 0, 0 );
}
#endif
return res;
}
static void
backsql_free_attr( backsql_at_map_rec *at )
{
Debug( LDAP_DEBUG_TRACE, "==>free_attr(): '%s'\n", at->name, 0, 0 );
ch_free( at->name );
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 );
......@@ -413,24 +529,24 @@ backsql_free_attr( backsql_at_map_rec *at )
if ( at->query ) {
ch_free( at->query );
}
ch_free( at );
/* TimesTen */
if ( at->sel_expr_u ) {
ch_free( at->sel_expr_u );
}
Debug( LDAP_DEBUG_TRACE, "<==free_attr()\n", 0, 0, 0 );
ch_free( at );
return 1;
Debug( LDAP_DEBUG_TRACE, "<==free_attr()\n", 0, 0, 0 );
}
int
static void
backsql_free_oc( backsql_oc_map_rec *oc )
{
Debug( LDAP_DEBUG_TRACE, "==>free_oc(): '%s'\n", oc->name, 0, 0 );
Debug( LDAP_DEBUG_TRACE, "==>free_oc(): '%s'\n",
oc->name.bv_val, 0, 0 );
avl_free( oc->attrs, (AVL_FREE)backsql_free_attr );
ch_free( oc->name );
ch_free( oc->name.bv_val );
ch_free( oc->keytbl );
ch_free( oc->keycol );
if ( oc->create_proc != NULL ) {
......@@ -442,15 +558,14 @@ backsql_free_oc( backsql_oc_map_rec *oc )
ch_free( oc );
Debug( LDAP_DEBUG_TRACE, "<==free_oc()\n", 0, 0, 0 );
return 1;
}
int
backsql_destroy_schema_map( backsql_info *si )
{
Debug( LDAP_DEBUG_TRACE, "==>destroy_schema_map()\n", 0, 0, 0 );
avl_free( si->oc_by_oc, NULL );
avl_free( si->oc_by_id, (AVL_FREE)backsql_free_oc );
avl_free( si->oc_by_name, (AVL_FREE)backsql_dummy );
Debug( LDAP_DEBUG_TRACE, "<==destroy_schema_map()\n", 0, 0, 0 );
return 0;
}
......
......@@ -12,7 +12,8 @@
typedef struct {
char *name;
struct berval name;
ObjectClass *oc;
char *keytbl;
char *keycol;
/* expected to return keyval of newly created entry */
......@@ -29,7 +30,8 @@ typedef struct {
typedef struct {
/* literal name of corresponding LDAP attribute type */
char *name;
struct berval name;
AttributeDescription *ad;
char *from_tbls;
char *join_where;
char *sel_expr;
......@@ -56,14 +58,24 @@ typedef struct {
} backsql_at_map_rec;
/* defines to support bitmasks above */
#define BACKSQL_ADD 1
#define BACKSQL_DEL 2
#define BACKSQL_ADD 0x1
#define BACKSQL_DEL 0x2
#define BACKSQL_IS_ADD(x) ( BACKSQL_ADD & (x) )
#define BACKSQL_IS_DEL(x) ( BACKSQL_DEL & (x) )
#define BACKSQL_NCMP(v1,v2) ber_bvcmp((v1),(v2))
int backsql_load_schema_map( backsql_info *si, SQLHDBC dbh );
backsql_oc_map_rec *backsql_oc_with_name( backsql_info *si, char *objclass );
backsql_oc_map_rec *backsql_oc_with_id( backsql_info *si, unsigned long id );
backsql_at_map_rec *backsql_at_with_name( backsql_oc_map_rec *objclass,
char *attr );
/* Deprecated */
backsql_oc_map_rec *backsql_name2oc( backsql_info *si, struct berval *oc_name );
backsql_oc_map_rec *backsql_oc2oc( backsql_info *si, ObjectClass *oc );
backsql_oc_map_rec *backsql_id2oc( backsql_info *si, unsigned long id );
/* Deprecated */
backsql_at_map_rec *backsql_name2at( backsql_oc_map_rec *objclass,
struct berval *at_name );
backsql_at_map_rec *backsql_ad2at( backsql_oc_map_rec *objclass,
AttributeDescription *ad );
int backsql_destroy_schema_map( backsql_info *si );
#endif /* __BACKSQL_SCHEMA_MAP_H__ */
......
......@@ -25,42 +25,53 @@
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, struct berval *at_name )
backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad )
{
int n_attrs = 0;
char **tmp;
int n_attrs = 0;
AttributeName *an = NULL;
if ( bsi->attrs == NULL ) {
return 1;
}
for ( ; bsi->attrs[ n_attrs ]; n_attrs++ ) {
for ( ; bsi->attrs[ n_attrs ].an_name.bv_val; n_attrs++ ) {
an = &bsi->attrs[ n_attrs ];
Debug( LDAP_DEBUG_TRACE, "==>backsql_attrlist_add(): "
"attribute '%s' is in list\n",
bsi->attrs[ n_attrs ], 0, 0 );
an->an_name.bv_val, 0, 0 );
/*
* We can live with strcmp because the attribute
* list has been normalized before calling be_search
*/
if ( !strcmp( bsi->attrs[ n_attrs ], at_name->bv_val ) ) {
if ( !BACKSQL_NCMP( &an->an_name, &ad->ad_cname ) ) {
return 1;
}
}
Debug( LDAP_DEBUG_TRACE, "==>backsql_attrlist_add(): "
"adding '%s' to list\n", at_name->bv_val, 0, 0 );
tmp = (char **)ch_realloc( bsi->attrs, (n_attrs + 2)*sizeof( char * ) );
if ( tmp == NULL ) {
"adding '%s' to list\n", ad->ad_cname.bv_val, 0, 0 );
an = (AttributeName *)ch_realloc( bsi->attrs,
sizeof( AttributeName ) * ( n_attrs + 2 ) );
if ( an == NULL ) {
return -1;
}
bsi->attrs = tmp;
bsi->attrs[ n_attrs ] = ch_strdup( at_name->bv_val );
bsi->attrs[ n_attrs + 1 ] = NULL;
an[ n_attrs ].an_name = ad->ad_cname;
an[ n_attrs ].an_desc = ad;
an[ n_attrs + 1 ].an_name.bv_val = NULL;
an[ n_attrs + 1 ].an_name.bv_len = 0;
bsi->attrs = an;
return 1;
}
......@@ -103,17 +114,21 @@ backsql_init_search(
bsi->attrs = NULL;
} else {
bsi->attrs = (char **)ch_calloc( 1, sizeof( char * ) );
bsi->attrs[ 0 ] = NULL;
bsi->attrs = (AttributeName *)ch_calloc( 1,
sizeof( AttributeName ) );
bsi->attrs[ 0 ].an_name.bv_val = NULL;
bsi->attrs[ 0 ].an_name.bv_len = 0;
for ( p = attrs; p->an_name.bv_val; p++ ) {
/*
* ignore "+"
*/
if ( strcmp( p->an_name.bv_val, AllOper.bv_val ) == 0 ) {
if ( BACKSQL_NCMP( &p->an_name, &AllOper ) == 0
|| BACKSQL_NCMP( &p->an_name, &NoAttrs ) == 0 ) {
continue;
}
backsql_attrlist_add( bsi, &p->an_name );
backsql_attrlist_add( bsi, p->an_desc );
}
}
......@@ -192,7 +207,13 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f )
return 0;
}
at = backsql_at_with_name( bsi->oc, f->f_sub_desc->ad_cname.bv_val );
at = backsql_ad2at( bsi->oc, f->f_sub_desc );
/*
* 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 );
......@@ -273,8 +294,8 @@ int
backsql_process_filter( backsql_srch_info *bsi, Filter *f )
{
backsql_at_map_rec *at;
backsql_at_map_rec oc_attr
= { "objectClass", "", "", NULL, NULL, NULL, NULL };
backsql_at_map_rec oc_attr = { BER_BVC("objectClass"),
slap_schema.si_ad_objectClass, "", "", NULL, NULL, NULL, NULL };
AttributeDescription *ad = NULL;
int done = 0, len = 0;
/* TimesTen */
......@@ -325,7 +346,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
}
if ( strcasecmp( ad->ad_cname.bv_val, "objectclass" ) ) {
at = backsql_at_with_name( bsi->oc, ad->ad_cname.bv_val );
at = backsql_ad2at( bsi->oc, ad );
} else {
struct berval bv;
......@@ -337,13 +358,14 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
*/
bv.bv_val = at->sel_expr;
bv.bv_len = at->sel_expr ? strlen( at->sel_expr ) : 0;
backsql_strcat( &bv, &len, "'", bsi->oc->name, "'", NULL );
backsql_strcat( &bv, &len, "'", bsi->oc->name.bv_val,
"'", NULL );
at->sel_expr = bv.bv_val;
}
if ( at == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_process_filter(): "
"attribute '%s' is not defined for objectclass '%s'\n",
ad->ad_cname.bv_val, bsi->oc->name, 0 );
ad->ad_cname.bv_val, bsi->oc->name.bv_val, 0 );
backsql_strcat( &bsi->flt_where, &bsi->fwhere_len,
" 1=0 ", NULL );
goto impossible;
......@@ -355,7 +377,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
* need to add this attribute to list of attrs to load,
* so that we could do test_filter() later
*/
backsql_attrlist_add( bsi, &ad->ad_cname );
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,
......@@ -365,7 +387,8 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
#if 0
if ( at != &oc_attr ) {
backsql_strcat( &bsi->sel, &bsi->sel_len,
",", at->sel_expr, " AS ", at->name, NULL );
",", at->sel_expr, " AS ",
at->name.bv_val, NULL );
}
#endif
......@@ -472,7 +495,7 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query )
backsql_strcat( &bsi->sel, &bsi->sel_len,
"SELECT DISTINCT ldap_entries.id,",
bsi->oc->keytbl, ".", bsi->oc->keycol,
",'", bsi->oc->name, "' AS objectClass",
",'", bsi->oc->name.bv_val, "' AS objectClass",
",ldap_entries.dn AS dn", NULL );
#endif
backsql_strcat( &bsi->sel, &bsi->sel_len,
......@@ -481,10 +504,10 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query )
if ( bi->strcast_func ) {
backsql_strcat( &bsi->sel, &bsi->sel_len,
bi->strcast_func,
"('", bsi->oc->name, "')", NULL );
"('", bsi->oc->name.bv_val, "')", NULL );
} else {
backsql_strcat( &bsi->sel, &bsi->sel_len,
"'", bsi->oc->name, "'", NULL );
"'", bsi->oc->name.bv_val, "'", NULL );
}
backsql_strcat( &bsi->sel, &bsi->sel_len,
" AS objectClass,ldap_entries.dn AS dn", NULL );
......@@ -577,7 +600,7 @@ backsql_oc_get_candidates( backsql_oc_map_rec *oc, backsql_srch_info *bsi )
char temp_base_dn[ BACKSQL_MAX_DN_LEN + 1 ];
Debug( LDAP_DEBUG_TRACE, "==>backsql_oc_get_candidates(): oc='%s'\n",
oc->name, 0, 0 );
oc->name.bv_val, 0, 0 );
bsi->oc = oc;
if ( backsql_srch_query( bsi, &query ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
......@@ -700,16 +723,21 @@ backsql_oc_get_candidates( backsql_oc_map_rec *oc, backsql_srch_info *bsi )
e = (Entry *)ch_calloc( 1, sizeof( Entry ) );
for ( i = 1; i < row.ncols; i++ ) {
if ( row.is_null[ i ] > 0 ) {
backsql_entry_addattr( e, row.col_names[ i ],
row.cols[ i ],
row.col_prec[ i ] );
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 );
&row.col_names[ i ], 0, 0 );
}
}
#endif
......@@ -770,14 +798,15 @@ backsql_search(
Debug( LDAP_DEBUG_TRACE, " deref=%d, attrsonly=%d, "
"attributes to load: %s\n",
deref, attrsonly, attrs == NULL ? "all" : "custom list" );
dbh = backsql_get_db_conn( be, conn );
if ( !dbh ) {
sres = backsql_get_db_conn( be, conn, &dbh );
if ( sres != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
"could not get connection handle - exiting\n",
0, 0, 0 );
send_ldap_result( conn, op, LDAP_OTHER, "",
"SQL-backend error", NULL, NULL );
send_ldap_result( conn, op, sres, "",
sres == LDAP_OTHER ? "SQL-backend error" : "",
NULL, NULL );
return 1;
}
......@@ -861,7 +890,7 @@ backsql_search(
* of entries matching LDAP query filter and scope (or at least
* candidates), and get the IDs
*/
avl_apply( bi->oc_by_name, (AVL_APPLY)backsql_oc_get_candidates,
avl_apply( bi->oc_by_oc, (AVL_APPLY)backsql_oc_get_candidates,
&srch_info, 0, AVL_INORDER );
if ( !isroot && limit->lms_s_unchecked != -1 ) {
......@@ -951,7 +980,7 @@ done:;
for ( eid = srch_info.id_list; eid != NULL;
eid = backsql_free_entryID( eid, 1 ) );
charray_free( srch_info.attrs );
ch_free( srch_info.attrs );
Debug( LDAP_DEBUG_TRACE, "<==backsql_search()\n", 0, 0, 0 );
return 0;
......
......@@ -15,7 +15,7 @@
typedef struct {
SWORD ncols;
char **col_names;
BerVarray col_names;
UDWORD *col_prec;
char **cols;
SQLINTEGER *is_null;
......
......@@ -14,8 +14,8 @@
#include <stdio.h>
#include "ac/string.h"
#include <sys/types.h>
#include "ldap_pvt.h"
#include "slap.h"
#include "ldap_pvt.h"
#include "back-sql.h"
#include "sql-types.h"
#include "sql-wrap.h"
......@@ -28,8 +28,6 @@ typedef struct backsql_conn {
SQLHDBC dbh;
} backsql_db_conn;
int backsql_dummy( void *, void * );
void
backsql_PrintErrors( SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth, int rc )
{
......@@ -70,14 +68,15 @@ backsql_Prepare( SQLHDBC dbh, SQLHSTMT *sth, char *query, int timeout )
Debug( LDAP_DEBUG_TRACE, "==>_SQLPrepare()\n", 0, 0, 0 );
#endif
SQLGetInfo( dbh, SQL_DRIVER_NAME, drv_name, 30, &len );
SQLGetInfo( dbh, SQL_DRIVER_NAME, drv_name, sizeof( drv_name ), &len );
#if 0
Debug( LDAP_DEBUG_TRACE, "_SQLPrepare(): driver name='%s'\n",
drv_name, 0, 0 );
#endif
if ( !strncmp( ldap_pvt_str2upper( drv_name ), "SQLSRV32.DLL", 30 ) ) {
ldap_pvt_str2upper( drv_name );
if ( !strncmp( drv_name, "SQLSRV32.DLL", sizeof( drv_name ) ) ) {
/*
* stupid default result set in MS SQL Server
* does not support multiple active statements
......@@ -91,7 +90,8 @@ backsql_Prepare( SQLHDBC dbh, SQLHSTMT *sth, char *query, int timeout )
SQL_CONCUR_ROWVER );
if ( rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO ) {
Debug( LDAP_DEBUG_TRACE, "_SQLPrepare(): "
"SQLSetStmtOption(SQL_CONCURRENCY,SQL_CONCUR_ROWVER) failed:\n",
"SQLSetStmtOption(SQL_CONCURRENCY,"
"SQL_CONCUR_ROWVER) failed:\n",
0, 0, 0 );
backsql_PrintErrors( SQL_NULL_HENV, dbh, *sth, rc );
}
......@@ -116,6 +116,9 @@ backsql_Prepare( SQLHDBC dbh, SQLHSTMT *sth, char *query, int timeout )
}
#if 0
/*
* Turned into macros --- see sql-wrap.h
*/
RETCODE
backsql_BindParamStr( SQLHSTMT sth, int par_ind, char *str, int maxlen )
{
......@@ -168,19 +171,20 @@ backsql_BindRowAsStrings( SQLHSTMT sth, BACKSQL_ROW_NTS *row )
"ncols=%d\n", (int)row->ncols, 0, 0 );
#endif
row->col_names = (char **)ch_calloc( row->ncols,
row->col_names = (BerVarray)ch_calloc( row->ncols + 1,
sizeof( struct berval ) );
row->cols = (char **)ch_calloc( row->ncols + 1,
sizeof( char * ) );
row->cols = (char **)ch_calloc( row->ncols, sizeof( char * ) );
row->col_prec = (UDWORD *)ch_calloc( row->ncols,
sizeof( UDWORD ) );
row->is_null = (SQLINTEGER *)ch_calloc( row->ncols,
sizeof( SQLINTEGER ) );
for ( i = 1; i <= row->ncols; i++ ) {
rc = SQLDescribeCol( sth, (SQLSMALLINT)i, &colname[ 0 ],
(SQLUINTEGER)sizeof( colname ) - 1,
(SQLUINTEGER)( sizeof( colname ) - 1 ),
&name_len, &col_type,
&col_prec, &col_scale, &col_null );
row->col_names[ i - 1 ] = ch_strdup( colname );
ber_str2bv( colname, 0, 1, &row->col_names[ i - 1 ] );
#if 0
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"col_name=%s, col_prec[%d]=%d\n",
......@@ -220,6 +224,10 @@ backsql_BindRowAsStrings( SQLHSTMT sth, BACKSQL_ROW_NTS *row )
&row->is_null[ i - 1 ] );
}
}
row->col_names[ i - 1 ].bv_val = NULL;
row->col_names[ i - 1 ].bv_len = 0;
row->cols[ i - 1 ] = NULL;
}
#if 0
Debug( LDAP_DEBUG_TRACE, "<== backsql_BindRowAsStrings()\n", 0, 0, 0 );
......@@ -231,28 +239,19 @@ backsql_BindRowAsStrings( SQLHSTMT sth, BACKSQL_ROW_NTS *row )
RETCODE
backsql_FreeRow( BACKSQL_ROW_NTS *row )
{
int i;
if ( row->cols == NULL ) {
return SQL_ERROR;
}
for ( i = 0; i < row->ncols; i++ ) {
/*
* FIXME: we need to free the col_names as well, don't we?
*/
free( row->cols[ i ] );
}
free( row->col_names );
ber_bvarray_free( row->col_names );
charray_free( row->cols );
free( row->col_prec );
free( row->cols );
free( row->is_null );
return SQL_SUCCESS;
}
int
static int
backsql_cmp_connid( backsql_db_conn *c1, backsql_db_conn *c2 )
{
if ( c1->ldap_cid > c2->ldap_cid ) {
......@@ -266,13 +265,19 @@ backsql_cmp_connid( backsql_db_conn *c1, backsql_db_conn *c2 )
return 0;
}
int
static int
backsql_close_db_conn( backsql_db_conn *conn )
{
Debug( LDAP_DEBUG_TRACE, "==>backsql_close_db_conn()\n", 0, 0, 0 );
/*
* Default transact is SQL_ROLLBACK; commit is required only
* by write operations, and it is explicitly performed after
* each atomic operation succeeds.
*/
/* TimesTen */
SQLTransact( SQL_NULL_HENV, conn->dbh, SQL_COMMIT );
SQLTransact( SQL_NULL_HENV, conn->dbh, SQL_ROLLBACK );
SQLDisconnect( conn->dbh );
SQLFreeConnect( conn->dbh );
Debug( LDAP_DEBUG_TRACE, "<==backsql_close_db_conn()\n", 0, 0, 0 );
......@@ -314,24 +319,27 @@ backsql_free_db_env( backsql_info *si )
return SQL_SUCCESS;
}
backsql_db_conn *
backsql_open_db_conn( backsql_info *si, int ldap_cid )
static int
backsql_open_db_conn( backsql_info *si, int ldap_cid, backsql_db_conn **pdbc )
{
/* TimesTen */
char DBMSName[ 32 ];
backsql_db_conn *dbc;
int rc;
assert( pdbc );
*pdbc = NULL;
Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_conn()\n", 0, 0, 0 );
dbc = (backsql_db_conn *)ch_calloc( 1, sizeof( backsql_db_conn ) );
dbc->ldap_cid = ldap_cid;
rc = SQLAllocConnect( si->db_env, &dbc->dbh );
if (!BACKSQL_SUCCESS( rc ) ) {
if ( !BACKSQL_SUCCESS( rc ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: "
"SQLAllocConnect() failed:\n", 0, 0, 0 );
backsql_PrintErrors( si->db_env, SQL_NULL_HDBC,
SQL_NULL_HENV, rc );
return NULL;
return LDAP_UNAVAILABLE;
}
rc = SQLConnect( dbc->dbh, si->dbname, SQL_NTS, si->dbuser,
......@@ -344,7 +352,7 @@ backsql_open_db_conn( backsql_info *si, int ldap_cid )
"succeeded with info" : "failed" );
backsql_PrintErrors( si->db_env, dbc->dbh, SQL_NULL_HENV, rc );
if ( rc != SQL_SUCCESS_WITH_INFO ) {
return NULL;
return LDAP_UNAVAILABLE;
}
}
......@@ -379,12 +387,13 @@ backsql_open_db_conn( backsql_info *si, int ldap_cid )
Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(): "
"connected, adding to tree\n", 0, 0, 0 );
ldap_pvt_thread_mutex_lock( &si->dbconn_mutex );
avl_insert( &si->db_conns, dbc, (AVL_CMP)backsql_cmp_connid,
backsql_dummy );
avl_insert( &si->db_conns, dbc, (AVL_CMP)backsql_cmp_connid, NULL );
ldap_pvt_thread_mutex_unlock( &si->dbconn_mutex );
Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_conn()\n", 0, 0, 0 );
return dbc;
*pdbc = dbc;
return LDAP_SUCCESS;
}
int
......@@ -413,15 +422,19 @@ backsql_free_db_conn( Backend *be, Connection *ldapc )
return SQL_SUCCESS;
}
SQLHDBC
backsql_get_db_conn( Backend *be, Connection *ldapc )
int
backsql_get_db_conn( Backend *be, Connection *ldapc, SQLHDBC *dbh )
{
backsql_info *si = (backsql_info *)be->be_private;
backsql_db_conn *dbc;
backsql_db_conn tmp;
int rc = LDAP_SUCCESS;
Debug( LDAP_DEBUG_TRACE, "==>backsql_get_db_conn()\n", 0, 0, 0 );
assert( dbh );
*dbh = SQL_NULL_HDBC;
tmp.ldap_cid = ldapc->c_connid;
/*
......@@ -431,25 +444,33 @@ backsql_get_db_conn( Backend *be, Connection *ldapc )
dbc = (backsql_db_conn *)avl_find( si->db_conns, &tmp,
(AVL_CMP)backsql_cmp_connid );
if ( !dbc ) {
dbc = backsql_open_db_conn( si, ldapc->c_connid );
}
if ( !dbc ) {
Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
"could not get connection handle -- returning NULL\n",
0, 0, 0 );
return SQL_NULL_HDBC;
rc = backsql_open_db_conn( si, ldapc->c_connid, &dbc );
if ( rc != LDAP_SUCCESS) {
Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
"could not get connection handle "
"-- returning NULL\n", 0, 0, 0 );
return rc;
}
}
ldap_pvt_thread_mutex_lock( &si->schema_mutex );
if ( !si->schema_loaded ) {
Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): "
"first call -- reading schema map\n", 0, 0, 0 );
backsql_load_schema_map( si, dbc->dbh );
rc = backsql_load_schema_map( si, dbc->dbh );
if ( rc != LDAP_SUCCESS ) {
backsql_free_db_conn( be, ldapc );
return rc;
}
}
ldap_pvt_thread_mutex_unlock( &si->schema_mutex );
*dbh = dbc->dbh;
Debug( LDAP_DEBUG_TRACE, "<==backsql_get_db_conn()\n", 0, 0, 0 );
return dbc->dbh;
return LDAP_SUCCESS;
}
#endif /* SLAPD_SQL */
......@@ -33,7 +33,7 @@ void backsql_PrintErrors( SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth, int rc );
int backsql_init_db_env( backsql_info *si );
int backsql_free_db_env( backsql_info *si );
SQLHDBC backsql_get_db_conn( Backend *be, Connection *ldapc );
int backsql_get_db_conn( Backend *be, Connection *ldapc, SQLHDBC *dbh );
int backsql_free_db_conn( Backend *be, Connection *ldapc );
#endif /* __BACKSQL_SQL_WRAP_H__ */
......
......@@ -17,6 +17,8 @@
#include "ac/ctype.h"
#include "ac/stdarg.h"
#include "slap.h"
#include "lber_pvt.h"
#include "ldap_pvt.h"
#include "back-sql.h"
#include "schema-map.h"
#include "util.h"
......@@ -40,6 +42,13 @@ char backsql_id_query[] = "SELECT id,keyval,oc_map_id FROM ldap_entries WHERE ";
/* TimesTen */
char backsql_check_dn_ru_query[] = "SELECT dn_ru from ldap_entries";
/*
* 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, ... )
{
......@@ -108,9 +117,8 @@ backsql_strcat( struct berval *dest, int *buflen, ... )
int
backsql_entry_addattr(
Entry *e,
char *at_name,
char *at_val,
unsigned int at_val_len )
struct berval *at_name,
struct berval *at_val )
{
struct berval add_val[ 2 ];
AttributeDescription *ad;
......@@ -118,18 +126,18 @@ backsql_entry_addattr(
const char *text;
Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(): "
"at_name='%s', at_val='%s'\n", at_name, at_val, 0 );
add_val[ 0 ].bv_val = at_val;
add_val[ 0 ].bv_len = at_val_len;
"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;
ad = NULL;
rc = slap_str2ad( at_name, &ad, &text );
rc = slap_bv2ad( at_name, &ad, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(): "
"failed to find AttributeDescription for '%s'\n",
at_name, 0, 0 );
at_name->bv_val, 0, 0 );
return 0;
}
......@@ -138,7 +146,7 @@ backsql_entry_addattr(
if ( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(): "
"failed to merge value '%s' for attribute '%s'\n",
at_val, at_name, 0 );
at_val->bv_val, at_name->bv_val, 0 );
return 0;
}
......
......@@ -19,10 +19,14 @@
#define BACKSQL_STR_GROW 64
extern struct berval
bv_n_objectclass,
bv_n_0_10;
struct berval *backsql_strcat( struct berval *dest, int *buflen, ... );
int backsql_entry_addattr( Entry *e, char *at_name, char *at_val,
unsigned int at_val_len );
int backsql_entry_addattr( Entry *e, struct berval *at_name,
struct berval *at_val );
typedef struct __backsql_srch_info {
struct berval *base_dn;
......@@ -42,7 +46,7 @@ typedef struct __backsql_srch_info {
Backend *be;
Connection *conn;
Operation *op;
char **attrs;
AttributeName *attrs;
Entry *e;
/* 1 if the db is TimesTen; 0 if it's not */
int isTimesTen;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment