summaryrefslogtreecommitdiffstats
path: root/servers/slapd/back-sql/rdbms_depend
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:35:32 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:35:32 +0000
commit5ea77a75dd2d2158401331879f3c8f47940a732c (patch)
treed89dc06e9f4850a900f161e25f84e922c4f86cc8 /servers/slapd/back-sql/rdbms_depend
parentInitial commit. (diff)
downloadopenldap-5ea77a75dd2d2158401331879f3c8f47940a732c.tar.xz
openldap-5ea77a75dd2d2158401331879f3c8f47940a732c.zip
Adding upstream version 2.5.13+dfsg.upstream/2.5.13+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'servers/slapd/back-sql/rdbms_depend')
-rw-r--r--servers/slapd/back-sql/rdbms_depend/README189
-rw-r--r--servers/slapd/back-sql/rdbms_depend/ibmdb2/backsql_create.sql59
-rw-r--r--servers/slapd/back-sql/rdbms_depend/ibmdb2/backsql_drop.sql5
-rw-r--r--servers/slapd/back-sql/rdbms_depend/ibmdb2/slapd.conf36
-rw-r--r--servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_create.sql75
-rw-r--r--servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_data.sql18
-rw-r--r--servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_drop.sql5
-rw-r--r--servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_metadata.sql123
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mssql/backsql_create.sql100
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mssql/backsql_drop.sql14
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mssql/slapd.conf30
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mssql/testdb_create.sql74
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mssql/testdb_data.sql24
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mssql/testdb_drop.sql39
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mssql/testdb_metadata.sql198
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mysql/backsql_create.sql58
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mysql/backsql_drop.sql7
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mysql/slapd.conf32
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mysql/testdb_create.sql86
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mysql/testdb_data.sql21
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mysql/testdb_drop.sql5
-rw-r--r--servers/slapd/back-sql/rdbms_depend/mysql/testdb_metadata.sql125
-rw-r--r--servers/slapd/back-sql/rdbms_depend/oracle/backsql_create.sql90
-rw-r--r--servers/slapd/back-sql/rdbms_depend/oracle/backsql_drop.sql8
-rw-r--r--servers/slapd/back-sql/rdbms_depend/oracle/slapd.conf32
-rw-r--r--servers/slapd/back-sql/rdbms_depend/oracle/testdb_create.sql68
-rw-r--r--servers/slapd/back-sql/rdbms_depend/oracle/testdb_data.sql27
-rw-r--r--servers/slapd/back-sql/rdbms_depend/oracle/testdb_drop.sql25
-rw-r--r--servers/slapd/back-sql/rdbms_depend/oracle/testdb_metadata.sql252
-rw-r--r--servers/slapd/back-sql/rdbms_depend/pgsql/backsql_create.sql50
-rw-r--r--servers/slapd/back-sql/rdbms_depend/pgsql/backsql_drop.sql4
-rw-r--r--servers/slapd/back-sql/rdbms_depend/pgsql/slapd.conf35
-rw-r--r--servers/slapd/back-sql/rdbms_depend/pgsql/testdb_create.sql55
-rw-r--r--servers/slapd/back-sql/rdbms_depend/pgsql/testdb_data.sql21
-rw-r--r--servers/slapd/back-sql/rdbms_depend/pgsql/testdb_drop.sql13
-rw-r--r--servers/slapd/back-sql/rdbms_depend/pgsql/testdb_metadata.sql146
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/backsql_create.sql66
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/backsql_drop.sql9
-rwxr-xr-xservers/slapd/back-sql/rdbms_depend/timesten/create_schema.sh4
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/Makefile48
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp387
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/slapd.conf31
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/testdb_create.sql36
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/testdb_data.sql16
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/testdb_drop.sql5
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/testdb_metadata.sql108
-rwxr-xr-xservers/slapd/back-sql/rdbms_depend/timesten/ttcreate_schema.sh4
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_create.sql42
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_data.sql20
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_drop.sql5
-rw-r--r--servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_metadata.sql122
51 files changed, 3052 insertions, 0 deletions
diff --git a/servers/slapd/back-sql/rdbms_depend/README b/servers/slapd/back-sql/rdbms_depend/README
new file mode 100644
index 0000000..2b281f6
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/README
@@ -0,0 +1,189 @@
+Author: Pierangelo Masarati <ando@OpenLDAP.org>
+
+Back-sql can be tested with sql-test000-read; it requires a bit of work
+to get everything up and running appropriately.
+
+This document briefly describes the steps that are required to prepare
+a quick'n'dirty installation of back-sql and of the related RDBMS
+and ODBC; Examples are provided, but by no means they pretent
+to represent an exhaustive source of info about how to setup the ODBC;
+refer to the docs for any problem or detail.
+
+Currently, the system has been tested with IBM db2, PostgreSQL and MySQL;
+basic support and test data for other RDBMSes is in place, but as of
+today (November 2004) it's totally untested. If you succeed in running
+any of the other RDBMSes, please provide feedback about any required
+change either in the code or in the test scripts by means of OpenLDAP's
+Issue Tracking System (http://www.openldap.org/its/).
+
+1) slapd must be compiled with back-sql support, i.e. configure
+with --enable-sql switch. This requires an implementation of the ODBC
+to be installed.
+
+2) The ODBC must be set up appropriately, by editing the odbc.ini file
+in /etc/ (or wherever your installation puts it) and, if appropriate,
+the odbcinst.ini file. Note: you can also use custom odbc.ini and
+odbcinst.ini files, provided you export in ODBCINI the full path to the
+odbc.ini file, and in ODBCSYSINI the directory where the odbcinst.ini
+file resides.
+Relevant info for our test setup is highlighted with '<===' on the right.
+
+2.1) PostgreSQL
+
+2.1.1) Add to the odbc.ini file a block of the form
+
+[example] <===
+Description = Example for OpenLDAP's back-sql
+Driver = PostgreSQL
+Trace = No
+Database = example <===
+Servername = localhost
+UserName = manager <===
+Password = secret <===
+Port = 5432
+;Protocol = 6.4
+ReadOnly = No
+RowVersioning = No
+ShowSystemTables = No
+ShowOidColumn = No
+FakeOidIndex = No
+ConnSettings =
+
+2.1.2) Add to the odbcinst.ini file a block of the form
+
+[PostgreSQL]
+Description = ODBC for PostgreSQL
+Driver = /usr/lib/libodbcpsql.so
+Setup = /usr/lib/libodbcpsqlS.so
+FileUsage = 1
+
+2.2) MySQL
+
+2.2.1) Add to the odbc.ini file a block of the form
+
+[example] <===
+Description = Example for OpenLDAP's back-sql
+Driver = MySQL
+Trace = No
+Database = example <===
+Servername = localhost
+UserName = manager <===
+Password = secret <===
+ReadOnly = No
+RowVersioning = No
+ShowSystemTables = No
+ShowOidColumn = No
+FakeOidIndex = No
+ConnSettings =
+SOCKET = /var/lib/mysql/mysql.sock
+
+2.2.2) Add to the odbcinst.ini file a block of the form
+
+[MySQL]
+Description = ODBC for MySQL
+Driver = /usr/lib/libmyodbc.so
+FileUsage = 1
+
+2.3) IBM db2
+[n.a.]
+
+3) The RDBMS must be setup; examples are provided for my installations
+of PostgreSQL and MySQL, but details may change; other RDBMSes should
+be configured in a similar manner, you need to find out the details by
+reading their documentation.
+
+3.1) PostgreSQL
+
+3.1.1) Start the server
+on RedHat:
+[root@localhost]# service postgresql start
+on other systems: read the docs...
+
+3.1.2) Create the database:
+[root@localhost]# su - postgres
+[postgres@localhost]$ createdb example
+
+3.1.3) Create the user:
+[root@localhost]# su - postgres
+[postgres@localhost]$ psql example
+example=> create user manager with password 'secret';
+example=> <control-D>
+
+3.1.4) Populate the database:
+[root@localhost]# cd $SOURCES/servers/slapd/back-sql/rdbms_depend/pgsql/
+[root@localhost]# psql -U manager -W example
+example=> <control-D>
+[root@localhost]# psql -U manager example < backsql_create.sql
+[root@localhost]# psql -U manager example < testdb_create.sql
+[root@localhost]# psql -U manager example < testdb_data.sql
+[root@localhost]# psql -U manager example < testdb_metadata.sql
+
+3.1.5) Run the test:
+[root@localhost]# cd $SOURCES/tests
+[root@localhost]# SLAPD_USE_SQL=pgsql ./run sql-test000
+
+3.2) MySQL
+
+3.2.1) Start the server
+on RedHat:
+[root@localhost]# service mysqld start
+on other systems: read the docs...
+
+3.2.2) Create the database:
+[root@localhost]# mysqladmin -u root -p create example
+(hit <return> for the empty password).
+
+3.2.3) Create the user:
+[root@localhost]# mysql -u root -p example
+(hit <return> for the empty password)
+mysql> grant all privileges on *.* \
+ to 'manager'@'localhost' identified by 'secret' with grant option;
+mysql> exit;
+
+3.2.4) Populate the database:
+[root@localhost]# cd $SOURCES/servers/slapd/back-sql/rdbms_depend/mysql/
+[root@localhost]# mysql -u manager -p example < backsql_create.sql
+[root@localhost]# mysql -u manager -p example < testdb_create.sql
+[root@localhost]# mysql -u manager -p example < testdb_data.sql
+[root@localhost]# mysql -u manager -p example < testdb_metadata.sql
+
+3.2.5) Run the test:
+[root@localhost]# cd $SOURCES/tests
+[root@localhost]# SLAPD_USE_SQL=mysql ./run sql-test000
+
+3.3) IBM db2
+[n.a.]
+
+3.3.1) Start the server:
+
+3.3.2) Create the database:
+
+3.3.3) Create the user:
+
+3.3.4) Populate the database:
+connect to the database as user manager, and execute the test files
+in auto-commit mode (-c)
+[root@localhost]# su - manager
+[manager@localhost]$ db2 "connect to example user manager using secret"
+[manager@localhost]$ db2 -ctvf backsql_create.sql
+[manager@localhost]$ db2 -ctvf testdb_create.sql
+[manager@localhost]$ db2 -ctvf testdb_data.sql
+[manager@localhost]$ db2 -ctvf testdb_metadata.sql
+[manager@localhost]$ db2 "connect reset"
+
+3.3.5) Run the test:
+[root@localhost]# cd $SOURCES/tests
+[root@localhost]# SLAPD_USE_SQL=ibmdb2 ./run sql-test000
+
+4) Cleanup:
+The test is basically readonly; this can be performed by all RDBMSes
+(listed above).
+
+There is another test, sql-test900-write, which is currently enabled
+only for PostgreSQL and IBM db2. Note that after a successful run
+of the write test, the database is no longer in the correct state
+to restart either of the tests, and step 3.X.4 needs to be re-run first.
+
+More tests are to come; PostgreSQL is known to allow a full reload
+of the test database starting from an empty database.
+
diff --git a/servers/slapd/back-sql/rdbms_depend/ibmdb2/backsql_create.sql b/servers/slapd/back-sql/rdbms_depend/ibmdb2/backsql_create.sql
new file mode 100644
index 0000000..cb2856b
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/ibmdb2/backsql_create.sql
@@ -0,0 +1,59 @@
+drop table ldap_oc_mappings;
+create table ldap_oc_mappings
+ (
+ id integer not null primary key,
+ name varchar(64) not null,
+ 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
+);
+
+drop table ldap_attr_mappings;
+create table ldap_attr_mappings
+ (
+ id integer 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,
+ sel_expr_u varchar(255),
+ from_tbls varchar(255) not null,
+ join_where varchar(255),
+ add_proc varchar(255),
+ delete_proc varchar(255),
+ param_order integer not null,
+ expect_return integer not null
+);
+
+drop table ldap_entries;
+create table ldap_entries
+ (
+ id integer not null primary key,
+ dn varchar(255) not null,
+ oc_map_id integer not null references ldap_oc_mappings(id),
+ parent int NOT NULL ,
+ keyval int NOT NULL
+);
+
+alter table ldap_entries add
+ constraint unq1_ldap_entries unique
+ (
+ oc_map_id,
+ keyval
+ );
+
+alter table ldap_entries add
+ constraint unq2_ldap_entries unique
+ (
+ dn
+ );
+
+drop table ldap_entry_objclasses;
+create table ldap_entry_objclasses
+ (
+ entry_id integer not null references ldap_entries(id),
+ oc_name varchar(64)
+ );
+
diff --git a/servers/slapd/back-sql/rdbms_depend/ibmdb2/backsql_drop.sql b/servers/slapd/back-sql/rdbms_depend/ibmdb2/backsql_drop.sql
new file mode 100644
index 0000000..49e7e3a
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/ibmdb2/backsql_drop.sql
@@ -0,0 +1,5 @@
+DROP TABLE ldap_referrals;
+DROP TABLE ldap_entry_objclasses;
+DROP TABLE ldap_attr_mappings;
+DROP TABLE ldap_entries;
+DROP TABLE ldap_oc_mappings;
diff --git a/servers/slapd/back-sql/rdbms_depend/ibmdb2/slapd.conf b/servers/slapd/back-sql/rdbms_depend/ibmdb2/slapd.conf
new file mode 100644
index 0000000..f6c1613
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/ibmdb2/slapd.conf
@@ -0,0 +1,36 @@
+# $OpenLDAP$
+#
+# See slapd.conf(5) for details on configuration options.
+# This file should NOT be world readable.
+#
+include /usr/local/etc/openldap/schema/core.schema
+include /usr/local/etc/openldap/schema/cosine.schema
+include /usr/local/etc/openldap/schema/inetorgperson.schema
+
+# Define global ACLs to disable default read access.
+
+# Do not enable referrals until AFTER you have a working directory
+# service AND an understanding of referrals.
+#referral ldap://root.openldap.org
+
+pidfile /usr/local/var/slapd.pid
+argsfile /usr/local/var/slapd.args
+
+#######################################################################
+# sql database definitions
+#######################################################################
+
+database sql
+suffix "o=sql,c=RU"
+rootdn "cn=root,o=sql,c=RU"
+rootpw secret
+dbname ldap_db2
+dbuser db2inst1
+dbpasswd ibmdb2
+subtree_cond "upper(ldap_entries.dn) LIKE CONCAT('%',?)"
+insentry_stmt "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"
+
diff --git a/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_create.sql b/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_create.sql
new file mode 100644
index 0000000..b6e850c
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_create.sql
@@ -0,0 +1,75 @@
+drop table persons;
+CREATE TABLE persons (
+ id int NOT NULL,
+ name varchar(255) NOT NULL,
+ surname varchar(255) NOT NULL,
+ password varchar(64)
+);
+
+drop table institutes;
+CREATE TABLE institutes (
+ id int NOT NULL,
+ name varchar(255)
+);
+
+drop table documents;
+CREATE TABLE documents (
+ id int NOT NULL,
+ 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
+);
+
+drop table phones;
+CREATE TABLE phones (
+ id int NOT NULL ,
+ phone varchar(255) NOT NULL ,
+ pers_id int NOT NULL
+);
+
+drop table referrals;
+CREATE TABLE referrals (
+ id int NOT NULL,
+ name varchar(255) NOT NULL,
+ url varchar(255) NOT NULL
+);
+
+
+
+ALTER TABLE authors_docs ADD
+ CONSTRAINT PK_authors_docs PRIMARY KEY
+ (
+ pers_id,
+ doc_id
+ );
+
+ALTER TABLE documents ADD
+ CONSTRAINT PK_documents PRIMARY KEY
+ (
+ id
+ );
+
+ALTER TABLE institutes ADD
+ CONSTRAINT PK_institutes PRIMARY KEY
+ (
+ id
+ );
+
+
+ALTER TABLE persons ADD
+ CONSTRAINT PK_persons PRIMARY KEY
+ (
+ id
+ );
+
+ALTER TABLE phones ADD
+ CONSTRAINT PK_phones PRIMARY KEY
+ (
+ id
+ );
+
diff --git a/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_data.sql b/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_data.sql
new file mode 100644
index 0000000..7bef374
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_data.sql
@@ -0,0 +1,18 @@
+insert into institutes (id,name) values (1,'Example');
+
+insert into persons (id,name,surname,password) values (1,'Mitya','Kovalev','mit');
+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);
+insert into phones (id,phone,pers_id) values (3,'545-4563',2);
+
+insert into documents (id,abstract,title) values (1,'abstract1','book1');
+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);
+
+insert into referrals (id,name,url) values (1,'Referral','ldap://localhost:9012/');
diff --git a/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_drop.sql b/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_drop.sql
new file mode 100644
index 0000000..17b12af
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_drop.sql
@@ -0,0 +1,5 @@
+DROP TABLE persons;
+DROP TABLE institutes;
+DROP TABLE documents;
+DROP TABLE authors_docs;
+DROP TABLE phones;
diff --git a/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_metadata.sql b/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_metadata.sql
new file mode 100644
index 0000000..0b0d1c2
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/ibmdb2/testdb_metadata.sql
@@ -0,0 +1,123 @@
+--mappings
+
+-- objectClass mappings: these may be viewed as structuralObjectClass, the ones that are used to decide how to build an entry
+-- id a unique number identifying the objectClass
+-- name the name of the objectClass; it MUST match the name of an objectClass that is loaded in slapd's schema
+-- keytbl the name of the table that is referenced for the primary key of an entry
+-- keycol the name of the column in "keytbl" that contains the primary key of an entry; the pair "keytbl.keycol" uniquely identifies an entry of objectClass "id"
+-- create_proc a procedure to create the entry
+-- create_keyval a query that returns the id of the last inserted entry
+-- delete_proc a procedure to delete the entry; it takes "keytbl.keycol" of the row to be deleted
+-- expect_return a bitmap that marks whether create_proc (1) and delete_proc (2) return a value or not
+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','DELETE FROM persons WHERE id=?',0);
+
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,create_keyval,delete_proc,expect_return)
+values (2,'document','documents','id','INSERT INTO documents (id,title,abstract) VALUES ((SELECT max(id)+1 FROM documents),'''','''')',
+ 'SELECT max(id) FROM documents','DELETE FROM documents WHERE id=?',0);
+
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,create_keyval,delete_proc,expect_return)
+values (3,'organization','institutes','id','INSERT INTO institutes (id,name) VALUES ((SELECT max(id)+1 FROM institutes),'''')',
+ 'SELECT max(id) FROM institutes','DELETE FROM institutes WHERE id=?',0);
+
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,create_keyval,delete_proc,expect_return)
+values (4,'referral','referrals','id','INSERT INTO referrals (id,name,url) VALUES ((SELECT max(id)+1 FROM referrals),'''','''')',
+ 'SELECT max(id) FROM referrals','DELETE FROM referrals WHERE id=?',0);
+
+-- attributeType mappings: describe how an attributeType for a certain objectClass maps to the SQL data.
+-- id a unique number identifying the attribute
+-- oc_map_id the value of "ldap_oc_mappings.id" that identifies the objectClass this attributeType is defined for
+-- name the name of the attributeType; it MUST match the name of an attributeType that is loaded in slapd's schema
+-- sel_expr the expression that is used to select this attribute (the "select <sel_expr> from ..." portion)
+-- from_tbls the expression that defines the table(s) this attribute is taken from (the "select ... from <from_tbls> where ..." portion)
+-- join_where the expression that defines the condition to select this attribute (the "select ... where <join_where> ..." portion)
+-- add_proc a procedure to insert the attribute; it takes the value of the attribute that is added, and the "keytbl.keycol" of the entry it is associated to
+-- delete_proc a procedure to delete the attribute; it takes the value of the attribute that is added, and the "keytbl.keycol" of the entry it is associated to
+-- param_order a mask that marks if the "keytbl.keycol" value comes before or after the value in add_proc (1) and delete_proc (2)
+-- expect_return a mask that marks whether add_proc (1) and delete_proc(2) are expected to return a value or not
+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.surname','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','INSERT INTO phones (id,phone,pers_id) VALUES ((SELECT max(id)+1 FROM phones),?,?)',
+ 'DELETE FROM phones WHERE phone=? AND pers_id=?',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,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 (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 (5,1,'userPassword','persons.password','persons','persons.password IS NOT NULL','UPDATE persons SET password=? WHERE id=?',
+ 'UPDATE persons SET password=NULL WHERE password=? AND id=?',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,'seeAlso','seeAlso.dn','ldap_entries AS seeAlso,documents,authors_docs,persons',
+ 'seeAlso.keyval=documents.id AND seeAlso.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 (7,2,'description','documents.abstract','documents',NULL,'UPDATE documents SET abstract=? 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 (8,2,'documentTitle','documents.title','documents',NULL,'UPDATE documents SET title=? 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 (9,2,'documentAuthor','documentAuthor.dn','ldap_entries AS documentAuthor,documents,authors_docs,persons',
+ 'documentAuthor.keyval=persons.id AND documentAuthor.oc_map_id=1 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',
+ 'INSERT INTO authors_docs (pers_id,doc_id) VALUES ((SELECT keyval FROM ldap_entries WHERE ucase(cast(? AS VARCHAR(255)))=ucase(dn)),?)',
+ 'DELETE FROM authors_docs WHERE pers_id=(SELECT keyval FROM ldap_entries WHERE ucase(cast(? AS VARCHAR(255))=ucase(dn)) AND doc_id=?',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 (10,2,'documentIdentifier','''document ''||rtrim(cast(documents.id AS CHAR(16)))','documents',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 (11,3,'o','institutes.name','institutes',NULL,'UPDATE institutes 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 (12,3,'dc','lcase(institutes.name)','institutes,ldap_entries AS dcObject,ldap_entry_objclasses as auxObjectClass',
+ 'institutes.id=dcObject.keyval AND dcObject.oc_map_id=3 AND dcObject.id=auxObjectClass.entry_id AND auxObjectClass.oc_name=''dcObject''',
+ 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 (13,4,'ou','referrals.name','referrals',NULL,'UPDATE referrals 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 (14,4,'ref','referrals.url','referrals',NULL,'UPDATE referrals SET url=? WHERE id=?',NULL,3,0);
+
+-- entries mapping: each entry must appear in this table, with a unique DN rooted at the database naming context
+-- id a unique number > 0 identifying the entry
+-- dn the DN of the entry, in "pretty" form
+-- oc_map_id the "ldap_oc_mappings.id" of the main objectClass of this entry (view it as the structuralObjectClass)
+-- parent the "ldap_entries.id" of the parent of this objectClass; 0 if it is the "suffix" of the database
+-- keyval the value of the "keytbl.keycol" defined for this objectClass
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (1,'dc=example,dc=com',3,0,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (2,'cn=Mitya Kovalev,dc=example,dc=com',1,1,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (3,'cn=Torvlobnor Puzdoy,dc=example,dc=com',1,1,2);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (4,'cn=Akakiy Zinberstein,dc=example,dc=com',1,1,3);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (5,'documentTitle=book1,dc=example,dc=com',2,1,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (6,'documentTitle=book2,dc=example,dc=com',2,1,2);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (7,'ou=Referral,dc=example,dc=com',4,1,1);
+
+-- objectClass mapping: entries that have multiple objectClass instances are listed here with the objectClass name (view them as auxiliary objectClass)
+-- entry_id the "ldap_entries.id" of the entry this objectClass value must be added
+-- oc_name the name of the objectClass; it MUST match the name of an objectClass that is loaded in slapd's schema
+insert into ldap_entry_objclasses (entry_id,oc_name) values (1,'dcObject');
+
+insert into ldap_entry_objclasses (entry_id,oc_name) values (7,'extensibleObject');
diff --git a/servers/slapd/back-sql/rdbms_depend/mssql/backsql_create.sql b/servers/slapd/back-sql/rdbms_depend/mssql/backsql_create.sql
new file mode 100644
index 0000000..1f1f6d2
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mssql/backsql_create.sql
@@ -0,0 +1,100 @@
+create table ldap_oc_mappings (
+ id int identity (1, 1) not null ,
+ name varchar (64) not null ,
+ keytbl varchar (64) not null ,
+ keycol varchar (64) not null ,
+ create_proc varchar (255) NULL ,
+ delete_proc varchar (255) NULL,
+ expect_return int not null
+)
+GO
+
+alter table ldap_oc_mappings add
+ constraint pk_ldap_oc_mappings primary key
+ (
+ id
+ )
+GO
+
+
+alter table ldap_oc_mappings add
+ constraint unq1_ldap_oc_mappings unique
+ (
+ name
+ )
+GO
+
+
+create table ldap_attr_mappings (
+ id int identity (1, 1) not null ,
+ oc_map_id int not null references ldap_oc_mappings(id),
+ name varchar (255) not null ,
+ sel_expr varchar (255) not null ,
+ sel_expr_u varchar(255),
+ from_tbls varchar (255) not null ,
+ join_where varchar (255) NULL ,
+ add_proc varchar (255) NULL ,
+ delete_proc varchar (255) NULL ,
+ param_order int not null,
+ expect_return int not null
+)
+GO
+
+alter table ldap_attr_mappings add
+ constraint pk_ldap_attr_mappings primary key
+ (
+ id
+ )
+GO
+
+
+create table ldap_entries (
+ id int identity (1, 1) not null ,
+ dn varchar (255) not null ,
+ oc_map_id int not null references ldap_oc_mappings(id),
+ parent int not null ,
+ keyval int not null
+)
+GO
+
+
+alter table ldap_entries add
+ constraint pk_ldap_entries primary key
+ (
+ id
+ )
+GO
+
+alter table ldap_entries add
+ constraint unq1_ldap_entries unique
+ (
+ oc_map_id,
+ keyval
+ )
+GO
+
+alter table ldap_entries add
+ constraint unq2_ldap_entries unique
+ (
+ dn
+ )
+GO
+
+
+create table ldap_referrals
+ (
+ entry_id int not null references ldap_entries(id),
+ url text not null
+)
+GO
+
+create index entry_idx on ldap_referrals(entry_id);
+
+create table ldap_entry_objclasses
+ (
+ entry_id int not null references ldap_entries(id),
+ oc_name varchar(64)
+ )
+GO
+
+create index entry_idx on ldap_entry_objclasses(entry_id);
diff --git a/servers/slapd/back-sql/rdbms_depend/mssql/backsql_drop.sql b/servers/slapd/back-sql/rdbms_depend/mssql/backsql_drop.sql
new file mode 100644
index 0000000..0e888b3
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mssql/backsql_drop.sql
@@ -0,0 +1,14 @@
+drop table ldap_attr_mappings
+GO
+
+drop table ldap_referrals
+GO
+
+drop table ldap_entry_objclasses
+GO
+
+drop table ldap_entries
+GO
+
+drop table ldap_oc_mappings
+GO
diff --git a/servers/slapd/back-sql/rdbms_depend/mssql/slapd.conf b/servers/slapd/back-sql/rdbms_depend/mssql/slapd.conf
new file mode 100644
index 0000000..c3032f2
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mssql/slapd.conf
@@ -0,0 +1,30 @@
+# $OpenLDAP$
+#
+# See slapd.conf(5) for details on configuration options.
+# This file should NOT be world readable.
+#
+include ./schema/core.schema
+include ./schema/cosine.schema
+include ./schema/inetorgperson.schema
+
+# Define global ACLs to disable default read access.
+
+# Do not enable referrals until AFTER you have a working directory
+# service AND an understanding of referrals.
+#referral ldap://root.openldap.org
+
+pidfile ./slapd.pid
+argsfile ./slapd.args
+
+#######################################################################
+# sql database definitions
+#######################################################################
+
+database sql
+suffix "o=sql,c=RU"
+rootdn "cn=root,o=sql,c=RU"
+rootpw secret
+dbname ldap_mssql
+dbuser ldap
+dbpasswd ldap
+subtree_cond "ldap_entries.dn LIKE '%'+?"
diff --git a/servers/slapd/back-sql/rdbms_depend/mssql/testdb_create.sql b/servers/slapd/back-sql/rdbms_depend/mssql/testdb_create.sql
new file mode 100644
index 0000000..2034afd
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mssql/testdb_create.sql
@@ -0,0 +1,74 @@
+
+CREATE TABLE authors_docs (
+ pers_id int NOT NULL ,
+ doc_id int NOT NULL
+)
+GO
+
+CREATE TABLE documents (
+ id int IDENTITY (1, 1) NOT NULL ,
+ abstract varchar (255) NULL ,
+ title varchar (255) NULL ,
+ body binary (255) NULL
+)
+GO
+
+CREATE TABLE institutes (
+ id int IDENTITY (1, 1) NOT NULL ,
+ name varchar (255) NOT NULL
+)
+GO
+
+
+CREATE TABLE persons (
+ id int IDENTITY (1, 1) NOT NULL ,
+ name varchar (255) NULL ,
+ surname varchar (255) NULL ,
+ password varchar (64) NULL
+)
+GO
+
+CREATE TABLE phones (
+ id int IDENTITY (1, 1) NOT NULL ,
+ phone varchar (255) NOT NULL ,
+ pers_id int NOT NULL
+)
+GO
+
+ALTER TABLE authors_docs WITH NOCHECK ADD
+ CONSTRAINT PK_authors_docs PRIMARY KEY
+ (
+ pers_id,
+ doc_id
+ )
+GO
+
+ALTER TABLE documents WITH NOCHECK ADD
+ CONSTRAINT PK_documents PRIMARY KEY
+ (
+ id
+ )
+GO
+
+ALTER TABLE institutes WITH NOCHECK ADD
+ CONSTRAINT PK_institutes PRIMARY KEY
+ (
+ id
+ )
+GO
+
+
+ALTER TABLE persons WITH NOCHECK ADD
+ CONSTRAINT PK_persons PRIMARY KEY
+ (
+ id
+ )
+GO
+
+ALTER TABLE phones WITH NOCHECK ADD
+ CONSTRAINT PK_phones PRIMARY KEY
+ (
+ id
+ )
+GO
+
diff --git a/servers/slapd/back-sql/rdbms_depend/mssql/testdb_data.sql b/servers/slapd/back-sql/rdbms_depend/mssql/testdb_data.sql
new file mode 100644
index 0000000..21a51ef
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mssql/testdb_data.sql
@@ -0,0 +1,24 @@
+set IDENTITY_INSERT institutes ON
+insert into institutes (id,name) values (1,'Example')
+set IDENTITY_INSERT institutes OFF
+
+set IDENTITY_INSERT persons ON
+insert into persons (id,name,surname,password) values (1,'Mitya','Kovalev','mit')
+insert into persons (id,name,surname) values (2,'Torvlobnor','Puzdoy')
+insert into persons (id,name,surname) values (3,'Akakiy','Zinberstein')
+set IDENTITY_INSERT persons OFF
+
+set IDENTITY_INSERT phones ON
+insert into phones (id,phone,pers_id) values (1,'332-2334',1)
+insert into phones (id,phone,pers_id) values (2,'222-3234',1)
+insert into phones (id,phone,pers_id) values (3,'545-4563',2)
+set IDENTITY_INSERT phones OFF
+
+set IDENTITY_INSERT documents ON
+insert into documents (id,abstract,title) values (1,'abstract1','book1')
+insert into documents (id,abstract,title) values (2,'abstract2','book2')
+set IDENTITY_INSERT documents OFF
+
+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)
diff --git a/servers/slapd/back-sql/rdbms_depend/mssql/testdb_drop.sql b/servers/slapd/back-sql/rdbms_depend/mssql/testdb_drop.sql
new file mode 100644
index 0000000..4842ed8
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mssql/testdb_drop.sql
@@ -0,0 +1,39 @@
+drop procedure create_person
+drop procedure set_person_name
+drop procedure delete_phone
+drop procedure add_phone
+drop procedure make_doc_link
+drop procedure del_doc_link
+drop procedure delete_person
+
+drop procedure create_org
+drop procedure set_org_name
+drop procedure delete_org
+
+drop procedure create_document
+drop procedure set_doc_title
+drop procedure set_doc_abstract
+drop procedure make_author_link
+drop procedure del_author_link
+drop procedure delete_document
+
+if exists (select * from sysobjects where id = object_id(N'authors_docs') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
+drop table authors_docs
+GO
+
+if exists (select * from sysobjects where id = object_id(N'documents') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
+drop table documents
+GO
+
+if exists (select * from sysobjects where id = object_id(N'institutes') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
+drop table institutes
+GO
+
+if exists (select * from sysobjects where id = object_id(N'persons') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
+drop table persons
+GO
+
+if exists (select * from sysobjects where id = object_id(N'phones') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
+drop table phones
+GO
+
diff --git a/servers/slapd/back-sql/rdbms_depend/mssql/testdb_metadata.sql b/servers/slapd/back-sql/rdbms_depend/mssql/testdb_metadata.sql
new file mode 100644
index 0000000..e087523
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mssql/testdb_metadata.sql
@@ -0,0 +1,198 @@
+-- mappings
+
+
+SET IDENTITY_INSERT ldap_oc_mappings ON
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return)
+values (1,'inetOrgPerson','persons','id','{call create_person(?)}','{call delete_person(?)}',0)
+
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return)
+values (2,'document','documents','id','{call create_document(?)}','{call delete_document(?)}',0)
+
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return)
+values (3,'organization','institutes','id','{call create_org(?)}','{call delete_org(?)}',0)
+SET IDENTITY_INSERT ldap_oc_mappings OFF
+
+
+SET IDENTITY_INSERT ldap_attr_mappings ON
+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.surname','persons',NULL,
+ NULL,NULL,0,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','{call add_phone(?,?)}',
+ '{call delete_phone(?,?)}',0,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,
+ '{call set_person_name(?,?)}',NULL,0,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,1,'sn','persons.surname','persons',NULL,
+ '{call set_person_surname(?,?)}',NULL,0,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 (5,1,'userPassword','persons.password','persons','persons.password IS NOT NULL',
+ '{call set_person_password(?,?)}','call del_person_password(?,?)',0,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,'seeAlso','seeAlso.dn','ldap_entries AS seeAlso,documents,authors_docs,persons',
+ 'seeAlso.keyval=documents.id AND seeAlso.oc_map_id=2 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',
+ NULL,NULL,0,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 (7,2,'description','documents.abstract','documents',NULL,'{call set_doc_abstract(?,?)}',
+ NULL,0,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,2,'documentTitle','documents.title','documents',NULL, '{call set_doc_title(?,?)}',
+ NULL,0,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','documentAuthor.dn','ldap_entries AS documentAuthor,documents,authors_docs,persons',
+ 'documentAuthor.keyval=persons.id AND documentAuthor.oc_map_id=1 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',
+ 'INSERT INTO authors_docs (pers_id,doc_id) VALUES ((SELECT ldap_entries.keyval FROM ldap_entries WHERE upper(?)=upper(ldap_entries.dn)),?)',
+ 'DELETE FROM authors_docs WHERE authors_docs.pers_id=(SELECT ldap_entries.keyval FROM ldap_entries WHERE upper(?)=upper(ldap_entries.dn)) AND authors_docs.doc_id=?',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 (10,2,'documentIdentifier','''document ''+text(documents.id)','documents',
+ NULL,NULL,NULL,0,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 (11,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 (12,3,'dc','lower(institutes.name)','institutes,ldap_entries AS dcObject,ldap_entry_objclasses AS auxObjectClass',
+ 'institutes.id=dcObject.keyval AND dcObject.oc_map_id=3 AND dcObject.id=auxObjectClass.entry_id AND auxObjectClass.oc_name=''dcObject''',
+ '{call set_org_name(?,?)}',NULL,3,0);
+
+SET IDENTITY_INSERT ldap_attr_mappings OFF
+
+-- entries
+
+SET IDENTITY_INSERT ldap_entries ON
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (1,'dc=example,dc=com',3,0,1)
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (2,'cn=Mitya Kovalev,dc=example,dc=com',1,1,1)
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (3,'cn=Torvlobnor Puzdoy,dc=example,dc=com',1,1,2)
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (4,'cn=Akakiy Zinberstein,dc=example,dc=com',1,1,3)
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (5,'documentTitle=book1,dc=example,dc=com',2,1,1)
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (6,'documentTitle=book2,dc=example,dc=com',2,1,2)
+
+SET IDENTITY_INSERT ldap_entries OFF
+
+-- referrals
+insert into ldap_entry_objclasses (entry_id,oc_name)
+values (1,'dcObject');
+
+insert into ldap_entry_objclasses (entry_id,oc_name)
+values (4,'referral');
+
+insert into ldap_referrals (entry_id,url)
+values (4,'ldap://localhost:9012/');
+
+-- support procedures
+
+SET QUOTED_IDENTIFIER OFF SET ANSI_NULLS ON
+GO
+
+
+CREATE PROCEDURE create_person @@keyval int OUTPUT AS
+INSERT INTO example.persons (name) VALUES ('');
+set @@keyval=(SELECT MAX(id) FROM example.persons)
+GO
+
+CREATE PROCEDURE delete_person @keyval int AS
+DELETE FROM example.phones WHERE pers_id=@keyval;
+DELETE FROM example.authors_docs WHERE pers_id=@keyval;
+DELETE FROM example.persons WHERE id=@keyval;
+GO
+
+CREATE PROCEDURE create_org @@keyval int OUTPUT AS
+INSERT INTO example.institutes (name) VALUES ('');
+set @@keyval=(SELECT MAX(id) FROM example.institutes)
+GO
+
+CREATE PROCEDURE delete_org @keyval int AS
+DELETE FROM example.institutes WHERE id=@keyval;
+GO
+
+CREATE PROCEDURE create_document @@keyval int OUTPUT AS
+INSERT INTO example.documents (title) VALUES ('');
+set @@keyval=(SELECT MAX(id) FROM example.documents)
+GO
+
+CREATE PROCEDURE delete_document @keyval int AS
+DELETE FROM example.authors_docs WHERE doc_id=@keyval;
+DELETE FROM example.documents WHERE id=@keyval;
+GO
+
+CREATE PROCEDURE add_phone @pers_id int, @phone varchar(255) AS
+INSERT INTO example.phones (pers_id,phone) VALUES (@pers_id,@phone)
+GO
+
+CREATE PROCEDURE delete_phone @keyval int,@phone varchar(64) AS
+DELETE FROM example.phones WHERE pers_id=@keyval AND phone=@phone;
+GO
+
+CREATE PROCEDURE set_person_name @keyval int, @new_name varchar(255) AS
+UPDATE example.persons SET name=@new_name WHERE id=@keyval;
+GO
+
+CREATE PROCEDURE set_person_surname @keyval int, @new_surname varchar(255) AS
+UPDATE example.persons SET surname=@new_surname WHERE id=@keyval;
+GO
+
+CREATE PROCEDURE set_org_name @keyval int, @new_name varchar(255) AS
+UPDATE example.institutes SET name=@new_name WHERE id=@keyval;
+GO
+
+CREATE PROCEDURE set_doc_title @keyval int, @new_title varchar(255) AS
+UPDATE example.documents SET title=@new_title WHERE id=@keyval;
+GO
+
+CREATE PROCEDURE set_doc_abstract @keyval int, @new_abstract varchar(255) AS
+UPDATE example.documents SET abstract=@new_abstract WHERE id=@keyval;
+GO
+
+CREATE PROCEDURE make_author_link @keyval int, @author_dn varchar(255) AS
+DECLARE @per_id int;
+SET @per_id=(SELECT keyval FROM example.ldap_entries
+ WHERE oc_map_id=1 AND dn=@author_dn);
+IF NOT (@per_id IS NULL)
+ INSERT INTO example.authors_docs (doc_id,pers_id) VALUES (@keyval,@per_id);
+GO
+
+CREATE PROCEDURE make_doc_link @keyval int, @doc_dn varchar(255) AS
+DECLARE @doc_id int;
+SET @doc_id=(SELECT keyval FROM example.ldap_entries
+ WHERE oc_map_id=2 AND dn=@doc_dn);
+IF NOT (@doc_id IS NULL)
+ INSERT INTO example.authors_docs (pers_id,doc_id) VALUES (@keyval,@doc_id);
+GO
+
+CREATE PROCEDURE del_doc_link @keyval int, @doc_dn varchar(255) AS
+DECLARE @doc_id int;
+SET @doc_id=(SELECT keyval FROM example.ldap_entries
+ WHERE oc_map_id=2 AND dn=@doc_dn);
+IF NOT (@doc_id IS NULL)
+DELETE FROM example.authors_docs WHERE pers_id=@keyval AND doc_id=@doc_id;
+GO
+
+CREATE PROCEDURE del_author_link @keyval int, @author_dn varchar(255) AS
+DECLARE @per_id int;
+SET @per_id=(SELECT keyval FROM example.ldap_entries
+ WHERE oc_map_id=1 AND dn=@author_dn);
+IF NOT (@per_id IS NULL)
+ DELETE FROM example.authors_docs WHERE doc_id=@keyval AND pers_id=@per_id;
+GO
diff --git a/servers/slapd/back-sql/rdbms_depend/mysql/backsql_create.sql b/servers/slapd/back-sql/rdbms_depend/mysql/backsql_create.sql
new file mode 100644
index 0000000..b2029c4
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mysql/backsql_create.sql
@@ -0,0 +1,58 @@
+drop table if exists ldap_oc_mappings;
+create table ldap_oc_mappings
+ (
+ id integer unsigned not null primary key auto_increment,
+ name varchar(64) not null,
+ keytbl varchar(64) not null,
+ keycol varchar(64) not null,
+ create_proc varchar(255),
+ delete_proc varchar(255),
+ expect_return tinyint not null
+);
+
+drop table if exists ldap_attr_mappings;
+create table ldap_attr_mappings
+ (
+ id integer unsigned not null primary key auto_increment,
+ oc_map_id integer unsigned not null references ldap_oc_mappings(id),
+ name varchar(255) not null,
+ sel_expr varchar(255) not null,
+ sel_expr_u varchar(255),
+ from_tbls varchar(255) not null,
+ join_where varchar(255),
+ add_proc varchar(255),
+ delete_proc varchar(255),
+ param_order tinyint not null,
+ expect_return tinyint not null
+);
+
+drop table if exists ldap_entries;
+create table ldap_entries
+ (
+ id integer unsigned not null primary key auto_increment,
+ dn varchar(255) not null,
+ oc_map_id integer unsigned not null references ldap_oc_mappings(id),
+ parent int NOT NULL ,
+ keyval int NOT NULL
+);
+
+alter table ldap_entries add
+ constraint unq1_ldap_entries unique
+ (
+ oc_map_id,
+ keyval
+ );
+
+alter table ldap_entries add
+ constraint unq2_ldap_entries unique
+ (
+ dn
+ );
+
+drop table if exists ldap_entry_objclasses;
+create table ldap_entry_objclasses
+ (
+ entry_id integer unsigned not null references ldap_entries(id),
+ oc_name varchar(64)
+ );
+
diff --git a/servers/slapd/back-sql/rdbms_depend/mysql/backsql_drop.sql b/servers/slapd/back-sql/rdbms_depend/mysql/backsql_drop.sql
new file mode 100644
index 0000000..a81fa8b
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mysql/backsql_drop.sql
@@ -0,0 +1,7 @@
+DROP TABLE IF EXISTS ldap_entry_objclasses;
+
+DROP TABLE IF EXISTS ldap_attr_mappings;
+
+DROP TABLE IF EXISTS ldap_entries;
+
+DROP TABLE IF EXISTS ldap_oc_mappings;
diff --git a/servers/slapd/back-sql/rdbms_depend/mysql/slapd.conf b/servers/slapd/back-sql/rdbms_depend/mysql/slapd.conf
new file mode 100644
index 0000000..8f6e4e1
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mysql/slapd.conf
@@ -0,0 +1,32 @@
+# $OpenLDAP$
+#
+# See slapd.conf(5) for details on configuration options.
+# This file should NOT be world readable.
+#
+include /usr/local/etc/openldap/schema/core.schema
+include /usr/local/etc/openldap/schema/cosine.schema
+include /usr/local/etc/openldap/schema/inetorgperson.schema
+
+# Define global ACLs to disable default read access.
+
+# Do not enable referrals until AFTER you have a working directory
+# service AND an understanding of referrals.
+#referral ldap://root.openldap.org
+
+pidfile /usr/local/var/slapd.pid
+argsfile /usr/local/var/slapd.args
+
+#######################################################################
+# sql database definitions
+#######################################################################
+
+database sql
+suffix "o=sql,c=RU"
+rootdn "cn=root,o=sql,c=RU"
+rootpw secret
+dbname ldap_mysql
+dbuser root
+dbpasswd
+subtree_cond "ldap_entries.dn LIKE CONCAT('%',?)"
+insentry_stmt "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)"
+has_ldapinfo_dn_ru no
diff --git a/servers/slapd/back-sql/rdbms_depend/mysql/testdb_create.sql b/servers/slapd/back-sql/rdbms_depend/mysql/testdb_create.sql
new file mode 100644
index 0000000..b35261b
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mysql/testdb_create.sql
@@ -0,0 +1,86 @@
+drop table if exists persons;
+CREATE TABLE persons (
+ id int NOT NULL,
+ name varchar(255) NOT NULL,
+ surname varchar(255) NOT NULL,
+ password varchar(64)
+);
+
+drop table if exists institutes;
+CREATE TABLE institutes (
+ id int NOT NULL,
+ name varchar(255)
+);
+
+drop table if exists documents;
+CREATE TABLE documents (
+ id int NOT NULL,
+ title varchar(255) NOT NULL,
+ abstract varchar(255)
+);
+
+drop table if exists authors_docs;
+CREATE TABLE authors_docs (
+ pers_id int NOT NULL,
+ doc_id int NOT NULL
+);
+
+drop table if exists phones;
+CREATE TABLE phones (
+ id int NOT NULL ,
+ phone varchar(255) NOT NULL ,
+ pers_id int NOT NULL
+);
+
+drop table if exists certs;
+CREATE TABLE certs (
+ id int NOT NULL ,
+ cert LONGBLOB NOT NULL,
+ pers_id int NOT NULL
+);
+
+ALTER TABLE authors_docs ADD
+ CONSTRAINT PK_authors_docs PRIMARY KEY
+ (
+ pers_id,
+ doc_id
+ );
+
+ALTER TABLE documents ADD
+ CONSTRAINT PK_documents PRIMARY KEY
+ (
+ id
+ );
+
+ALTER TABLE institutes ADD
+ CONSTRAINT PK_institutes PRIMARY KEY
+ (
+ id
+ );
+
+
+ALTER TABLE persons ADD
+ CONSTRAINT PK_persons PRIMARY KEY
+ (
+ id
+ );
+
+ALTER TABLE phones ADD
+ CONSTRAINT PK_phones PRIMARY KEY
+ (
+ id
+ );
+
+ALTER TABLE certs ADD
+ CONSTRAINT PK_certs PRIMARY KEY
+ (
+ id
+ );
+
+drop table if exists referrals;
+CREATE TABLE referrals (
+ id int NOT NULL,
+ name varchar(255) NOT NULL,
+ url varchar(255) NOT NULL
+);
+
diff --git a/servers/slapd/back-sql/rdbms_depend/mysql/testdb_data.sql b/servers/slapd/back-sql/rdbms_depend/mysql/testdb_data.sql
new file mode 100644
index 0000000..0ccbfb7
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mysql/testdb_data.sql
@@ -0,0 +1,21 @@
+insert into institutes (id,name) values (1,'Example');
+
+insert into persons (id,name,surname,password) values (1,'Mitya','Kovalev','mit');
+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);
+insert into phones (id,phone,pers_id) values (3,'545-4563',2);
+
+insert into documents (id,abstract,title) values (1,'abstract1','book1');
+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);
+
+insert into referrals (id,name,url) values (1,'Referral','ldap://localhost:9012/');
+
+insert into certs (id,cert,pers_id) values (1,UNHEX('3082036b308202d4a003020102020102300d06092a864886f70d01010405003077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311f301d060355040a13164f70656e4c444150204578616d706c652c204c74642e311330110603550403130a4578616d706c65204341311d301b06092a864886f70d010901160e6361406578616d706c652e636f6d301e170d3033313031373136333331395a170d3034313031363136333331395a307e310b3009060355040613025553311330110603550408130a43616c69666f726e6961311f301d060355040a13164f70656e4c444150204578616d706c652c204c74642e311830160603550403130f557273756c612048616d7073746572311f301d06092a864886f70d01090116107568616d406578616d706c652e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100eec60a7910b57d2e687158ca55eea738d36f10413dfecf31435e1aeeb9713b8e2da7dd2dde6bc6cec03b4987eaa7b037b9eb50e11c71e58088cc282883122cd8329c6f24f6045e6be9d21b9190c8292998267a5f7905292de936262747ab4b76a88a63872c41629a69d32e894d44c896a8d06fab0a1bc7de343c6c1458478f290203010001a381ff3081fc30090603551d1304023000302c06096086480186f842010d041f161d4f70656e53534c2047656e657261746564204365727469666963617465301d0603551d0e04160414a323de136c19ae0c479450e882dfb10ad147f45e3081a10603551d2304819930819680144b6f211a3624d290f943b053472d7de1c0e69823a17ba4793077310b3009060355040613025553311330110603550408130a43616c69666f726e6961311f301d060355040a13164f70656e4c444150204578616d706c652c204c74642e311330110603550403130a4578616d706c65204341311d301b06092a864886f70d010901160e6361406578616d706c652e636f6d820100300d06092a864886f70d010104050003818100881470045bdce95660d6e6af59e6a844aec4b9f5eaea88d4eb7a5a47080afa64750f81a3e47d00fd39c69a17a1c66d29d36f06edc537107f8c592239c2d4da55fb3f1d488e7b2387ad2a551cbd1ceb070ae9e020a9467275cb28798abb4cbfff98ddb3f1e7689b067072392511bb08125b5bec2bc207b7b6b275c47248f29acd'),3);
+
diff --git a/servers/slapd/back-sql/rdbms_depend/mysql/testdb_drop.sql b/servers/slapd/back-sql/rdbms_depend/mysql/testdb_drop.sql
new file mode 100644
index 0000000..7c5e9e7
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mysql/testdb_drop.sql
@@ -0,0 +1,5 @@
+DROP TABLE IF EXISTS persons;
+DROP TABLE IF EXISTS institutes;
+DROP TABLE IF EXISTS documents;
+DROP TABLE IF EXISTS authors_docs;
+DROP TABLE IF EXISTS phones;
diff --git a/servers/slapd/back-sql/rdbms_depend/mysql/testdb_metadata.sql b/servers/slapd/back-sql/rdbms_depend/mysql/testdb_metadata.sql
new file mode 100644
index 0000000..d7e88e4
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/mysql/testdb_metadata.sql
@@ -0,0 +1,125 @@
+-- mappings
+
+-- objectClass mappings: these may be viewed as structuralObjectClass, the ones that are used to decide how to build an entry
+-- id a unique number identifying the objectClass
+-- name the name of the objectClass; it MUST match the name of an objectClass that is loaded in slapd's schema
+-- keytbl the name of the table that is referenced for the primary key of an entry
+-- keycol the name of the column in "keytbl" that contains the primary key of an entry; the pair "keytbl.keycol" uniquely identifies an entry of objectClass "id"
+-- create_proc a procedure to create the entry
+-- delete_proc a procedure to delete the entry; it takes "keytbl.keycol" of the row to be deleted
+-- expect_return a bitmap that marks whether create_proc (1) and delete_proc (2) return a value or not
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return)
+values (1,'inetOrgPerson','persons','id',NULL,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,delete_proc,expect_return)
+values (3,'organization','institutes','id',NULL,NULL,0);
+
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return)
+values (4,'referral','referrals','id',NULL,NULL,0);
+
+-- attributeType mappings: describe how an attributeType for a certain objectClass maps to the SQL data.
+-- id a unique number identifying the attribute
+-- oc_map_id the value of "ldap_oc_mappings.id" that identifies the objectClass this attributeType is defined for
+-- name the name of the attributeType; it MUST match the name of an attributeType that is loaded in slapd's schema
+-- sel_expr the expression that is used to select this attribute (the "select <sel_expr> from ..." portion)
+-- from_tbls the expression that defines the table(s) this attribute is taken from (the "select ... from <from_tbls> where ..." portion)
+-- join_where the expression that defines the condition to select this attribute (the "select ... where <join_where> ..." portion)
+-- add_proc a procedure to insert the attribute; it takes the value of the attribute that is added, and the "keytbl.keycol" of the entry it is associated to
+-- delete_proc a procedure to delete the attribute; it takes the value of the attribute that is added, and the "keytbl.keycol" of the entry it is associated to
+-- param_order a mask that marks if the "keytbl.keycol" value comes before or after the value in add_proc (1) and delete_proc (2)
+-- expect_return a mask that marks whether add_proc (1) and delete_proc(2) are expected to return a value or not
+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',"concat(persons.name,' ',persons.surname)",'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,'givenName','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 (4,1,'sn','persons.surname','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 (5,1,'userPassword','persons.password','persons','persons.password IS NOT 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 (6,1,'seeAlso','seeAlso.dn','ldap_entries AS seeAlso,documents,authors_docs,persons',
+ 'seeAlso.keyval=documents.id AND seeAlso.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 (7,2,'description','documents.abstract','documents',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,2,'documentTitle','documents.title','documents',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 (9,2,'documentAuthor','documentAuthor.dn','ldap_entries AS documentAuthor,documents,authors_docs,persons',
+ 'documentAuthor.keyval=persons.id AND documentAuthor.oc_map_id=1 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 (10,2,'documentIdentifier','concat(''document '',documents.id)','documents',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 (11,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 (12,3,'dc','lower(institutes.name)','institutes,ldap_entries AS dcObject,ldap_entry_objclasses as auxObjectClass',
+ 'institutes.id=dcObject.keyval AND dcObject.oc_map_id=3 AND dcObject.id=auxObjectClass.entry_id AND auxObjectClass.oc_name=''dcObject''',
+ 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 (13,4,'ou','referrals.name','referrals',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 (14,4,'ref','referrals.url','referrals',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 (15,1,'userCertificate','certs.cert','persons,certs',
+ 'certs.pers_id=persons.id',NULL,NULL,3,0);
+
+-- entries mapping: each entry must appear in this table, with a unique DN rooted at the database naming context
+-- id a unique number > 0 identifying the entry
+-- dn the DN of the entry, in "pretty" form
+-- oc_map_id the "ldap_oc_mappings.id" of the main objectClass of this entry (view it as the structuralObjectClass)
+-- parent the "ldap_entries.id" of the parent of this objectClass; 0 if it is the "suffix" of the database
+-- keyval the value of the "keytbl.keycol" defined for this objectClass
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (1,'dc=example,dc=com',3,0,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (2,'cn=Mitya Kovalev,dc=example,dc=com',1,1,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (3,'cn=Torvlobnor Puzdoy,dc=example,dc=com',1,1,2);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (4,'cn=Akakiy Zinberstein,dc=example,dc=com',1,1,3);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (5,'documentTitle=book1,dc=example,dc=com',2,1,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (6,'documentTitle=book2,dc=example,dc=com',2,1,2);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (7,'ou=Referral,dc=example,dc=com',4,1,1);
+
+-- objectClass mapping: entries that have multiple objectClass instances are listed here with the objectClass name (view them as auxiliary objectClass)
+-- entry_id the "ldap_entries.id" of the entry this objectClass value must be added
+-- oc_name the name of the objectClass; it MUST match the name of an objectClass that is loaded in slapd's schema
+insert into ldap_entry_objclasses (entry_id,oc_name)
+values (1,'dcObject');
+
+insert into ldap_entry_objclasses (entry_id,oc_name)
+values (4,'pkiUser');
+
+insert into ldap_entry_objclasses (entry_id,oc_name)
+values (7,'extensibleObject');
+
diff --git a/servers/slapd/back-sql/rdbms_depend/oracle/backsql_create.sql b/servers/slapd/back-sql/rdbms_depend/oracle/backsql_create.sql
new file mode 100644
index 0000000..2e4e6ec
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/oracle/backsql_create.sql
@@ -0,0 +1,90 @@
+create table ldap_oc_mappings (
+ id number not null ,
+ name varchar2(64) not null ,
+ keytbl varchar2(64) not null ,
+ keycol varchar2(64) not null ,
+ create_proc varchar2(255),
+ delete_proc varchar2(255),
+ expect_return number not null
+);
+
+alter table ldap_oc_mappings add
+ constraint PK_ldap_oc_mappings primary key
+ (
+ id
+ );
+
+alter table ldap_oc_mappings add
+ constraint unq_ldap_oc_mappings unique
+ (
+ name
+ );
+
+create table ldap_attr_mappings (
+ id number not null,
+ oc_map_id number not null references ldap_oc_mappings(id),
+ name varchar2(255) not null,
+ sel_expr varchar2(255) not null,
+ sel_expr_u varchar2(255),
+ from_tbls varchar2(255) not null,
+ join_where varchar2(255),
+ add_proc varchar2(255),
+ delete_proc varchar2(255),
+ param_order number not null,
+ expect_return number not null
+);
+
+alter table ldap_attr_mappings add
+ constraint pk_ldap_attr_mappings primary key
+ (
+ id
+ );
+
+
+create table ldap_entries (
+ id number not null ,
+ dn varchar2(255) not null ,
+ dn_ru varchar2(255),
+ oc_map_id number not null references ldap_oc_mappings(id),
+ parent number not null ,
+ keyval number not null
+);
+
+alter table ldap_entries add
+ constraint PK_ldap_entries primary key
+ (
+ id
+ );
+
+alter table ldap_entries add
+ constraint unq1_ldap_entries unique
+ (
+ oc_map_id,
+ keyval
+ );
+
+alter table ldap_entries add
+ constraint unq2_ldap_entries unique
+ (
+ dn
+ );
+
+create sequence ldap_objclass_ids start with 1 increment by 1;
+
+create sequence ldap_attr_ids start with 1 increment by 1;
+
+create sequence ldap_entry_ids start with 1 increment by 1;
+
+create table ldap_referrals
+ (
+ entry_id number not null references ldap_entries(id),
+ url varchar(1023) not null
+);
+
+create table ldap_entry_objclasses
+ (
+ entry_id number not null references ldap_entries(id),
+ oc_name varchar(64)
+ );
+
+quit
diff --git a/servers/slapd/back-sql/rdbms_depend/oracle/backsql_drop.sql b/servers/slapd/back-sql/rdbms_depend/oracle/backsql_drop.sql
new file mode 100644
index 0000000..19bb8b6
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/oracle/backsql_drop.sql
@@ -0,0 +1,8 @@
+drop table ldap_attr_mappings;
+drop table ldap_entry_objclasses;
+drop table ldap_referrals;
+drop sequence ldap_entry_ids;
+drop sequence ldap_attr_ids;
+drop sequence ldap_objclass_ids;
+drop table ldap_entries;
+drop table ldap_oc_mappings;
diff --git a/servers/slapd/back-sql/rdbms_depend/oracle/slapd.conf b/servers/slapd/back-sql/rdbms_depend/oracle/slapd.conf
new file mode 100644
index 0000000..cc195d9
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/oracle/slapd.conf
@@ -0,0 +1,32 @@
+# $OpenLDAP$
+#
+# See slapd.conf(5) for details on configuration options.
+# This file should NOT be world readable.
+#
+include /usr/local/etc/openldap/schema/core.schema
+include /usr/local/etc/openldap/schema/cosine.schema
+include /usr/local/etc/openldap/schema/inetorgperson.schema
+
+# Define global ACLs to disable default read access.
+
+# Do not enable referrals until AFTER you have a working directory
+# service AND an understanding of referrals.
+#referral ldap://root.openldap.org
+
+pidfile /usr/local/var/slapd.pid
+argsfile /usr/local/var/slapd.args
+
+#######################################################################
+# sql database definitions
+#######################################################################
+
+database sql
+suffix "o=sql,c=RU"
+rootdn "cn=root,o=sql,c=RU"
+rootpw secret
+dbname ldap_ora8
+dbuser ldap
+dbpasswd ldap
+subtree_cond "UPPER(ldap_entries.dn) LIKE CONCAT('%',UPPER(?))"
+insentry_stmt "INSERT INTO ldap_entries (id,dn,oc_map_id,parent,keyval) VALUES (ldap_entry_ids.nextval,?,?,?,?)"
+upper_func UPPER
diff --git a/servers/slapd/back-sql/rdbms_depend/oracle/testdb_create.sql b/servers/slapd/back-sql/rdbms_depend/oracle/testdb_create.sql
new file mode 100644
index 0000000..710a5fa
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/oracle/testdb_create.sql
@@ -0,0 +1,68 @@
+CREATE TABLE persons (
+ id NUMBER NOT NULL,
+ name varchar2(255) NOT NULL,
+ surname varchar2(255) NOT NULL,
+ password varchar2(64) NOT NULL
+);
+
+CREATE TABLE institutes (
+ id NUMBER NOT NULL,
+ name varchar2(255)
+);
+
+CREATE TABLE documents (
+ id NUMBER NOT NULL,
+ title varchar2(255) NOT NULL,
+ abstract varchar2(255)
+);
+
+CREATE TABLE authors_docs (
+ pers_id NUMBER NOT NULL,
+ doc_id NUMBER NOT NULL
+);
+
+CREATE TABLE phones (
+ id NUMBER NOT NULL ,
+ phone varchar2(255) NOT NULL ,
+ pers_id NUMBER NOT NULL
+);
+
+
+ALTER TABLE authors_docs ADD
+ CONSTRAINT PK_authors_docs PRIMARY KEY
+ (
+ pers_id,
+ doc_id
+ );
+
+ALTER TABLE documents ADD
+ CONSTRAINT PK_documents PRIMARY KEY
+ (
+ id
+ );
+
+ALTER TABLE institutes ADD
+ CONSTRAINT PK_institutes PRIMARY KEY
+ (
+ id
+ );
+
+ALTER TABLE persons ADD
+ CONSTRAINT PK_persons PRIMARY KEY
+ (
+ id
+ );
+
+ALTER TABLE phones ADD
+ CONSTRAINT PK_phones PRIMARY KEY
+ (
+ id
+ );
+
+CREATE SEQUENCE person_ids START WITH 1 INCREMENT BY 1;
+
+CREATE SEQUENCE document_ids START WITH 1 INCREMENT BY 1;
+
+CREATE SEQUENCE institute_ids START WITH 1 INCREMENT BY 1;
+
+CREATE SEQUENCE phone_ids START WITH 1 INCREMENT BY 1;
diff --git a/servers/slapd/back-sql/rdbms_depend/oracle/testdb_data.sql b/servers/slapd/back-sql/rdbms_depend/oracle/testdb_data.sql
new file mode 100644
index 0000000..4fc1977
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/oracle/testdb_data.sql
@@ -0,0 +1,27 @@
+insert into institutes (id,name) values (institute_ids.nextval,'example');
+
+insert into persons (id,name,surname,password) values (person_ids.nextval,'Mitya','Kovalev','mit');
+
+insert into persons (id,name,surname) values (person_ids.nextval,'Torvlobnor','Puzdoy');
+
+insert into persons (id,name,surname) values (person_ids.nextval,'Akakiy','Zinberstein');
+
+
+insert into phones (id,phone,pers_id) values (phone_ids.nextval,'332-2334',1);
+
+insert into phones (id,phone,pers_id) values (phone_ids.nextval,'222-3234',1);
+
+insert into phones (id,phone,pers_id) values (phone_ids.nextval,'545-4563',2);
+
+
+insert into documents (id,abstract,title) values (document_ids.nextval,'abstract1','book1');
+
+insert into documents (id,abstract,title) values (document_ids.nextval,'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);
+
diff --git a/servers/slapd/back-sql/rdbms_depend/oracle/testdb_drop.sql b/servers/slapd/back-sql/rdbms_depend/oracle/testdb_drop.sql
new file mode 100644
index 0000000..0cf4463
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/oracle/testdb_drop.sql
@@ -0,0 +1,25 @@
+DROP TABLE persons;
+DROP TABLE institutes;
+DROP TABLE documents;
+DROP TABLE authors_docs;
+DROP TABLE phones;
+DROP SEQUENCE person_ids;
+DROP SEQUENCE institute_ids;
+DROP SEQUENCE document_ids;
+DROP SEQUENCE phone_ids;
+DROP PROCEDURE create_person;
+DROP PROCEDURE delete_person;
+DROP PROCEDURE add_phone;
+DROP PROCEDURE delete_phone;
+DROP PROCEDURE set_person_name;
+DROP PROCEDURE set_org_name;
+DROP PROCEDURE set_doc_title;
+DROP PROCEDURE set_doc_abstract;
+DROP PROCEDURE create_document;
+DROP PROCEDURE create_org;
+DROP PROCEDURE delete_document;
+DROP PROCEDURE delete_org;
+DROP PROCEDURE make_doc_link;
+DROP PROCEDURE del_doc_link;
+DROP PROCEDURE make_author_link;
+DROP PROCEDURE del_author_link;
diff --git a/servers/slapd/back-sql/rdbms_depend/oracle/testdb_metadata.sql b/servers/slapd/back-sql/rdbms_depend/oracle/testdb_metadata.sql
new file mode 100644
index 0000000..354d7bd
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/oracle/testdb_metadata.sql
@@ -0,0 +1,252 @@
+-- mappings
+
+-- objectClass mappings: these may be viewed as structuralObjectClass, the ones that are used to decide how to build an entry
+-- id a unique number identifying the objectClass
+-- name the name of the objectClass; it MUST match the name of an objectClass that is loaded in slapd's schema
+-- keytbl the name of the table that is referenced for the primary key of an entry
+-- keycol the name of the column in "keytbl" that contains the primary key of an entry; the pair "keytbl.keycol" uniquely identifies an entry of objectClass "id"
+-- create_proc a procedure to create the entry
+-- delete_proc a procedure to delete the entry; it takes "keytbl.keycol" of the row to be deleted
+-- expect_return a bitmap that marks whether create_proc (1) and delete_proc (2) return a value or not
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return)
+values (1,'inetOrgPerson','persons','id','call create_person(?)','call delete_person(?)',0);
+
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return)
+values (2,'document','documents','id','call create_document(?)','call delete_document(?)',0);
+
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return)
+values (3,'organization','institutes','id','call create_org(?)','call delete_org(?)',0);
+
+-- attributeType mappings: describe how an attributeType for a certain objectClass maps to the SQL data.
+-- id a unique number identifying the attribute
+-- oc_map_id the value of "ldap_oc_mappings.id" that identifies the objectClass this attributeType is defined for
+-- name the name of the attributeType; it MUST match the name of an attributeType that is loaded in slapd's schema
+-- sel_expr the expression that is used to select this attribute (the "select <sel_expr> from ..." portion)
+-- from_tbls the expression that defines the table(s) this attribute is taken from (the "select ... from <from_tbls> where ..." portion)
+-- join_where the expression that defines the condition to select this attribute (the "select ... where <join_where> ..." portion)
+-- add_proc a procedure to insert the attribute; it takes the value of the attribute that is added, and the "keytbl.keycol" of the entry it is associated to
+-- delete_proc a procedure to delete the attribute; it takes the value of the attribute that is added, and the "keytbl.keycol" of the entry it is associated to
+-- param_order a mask that marks if the "keytbl.keycol" value comes before or after the value in add_proc (1) and delete_proc (2)
+-- expect_return a mask that marks whether add_proc (1) and delete_proc(2) are expected to return a value or not
+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.surname','persons',NULL,
+ NULL,NULL,0,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','call add_phone(?,?)',
+ 'call delete_phone(?,?)',0,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,'call set_person_name(?,?)',
+ NULL,0,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,1,'sn','persons.surname','persons',NULL,'call set_person_surname(?,?)',
+ NULL,0,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 (5,1,'userPassword','persons.password','persons',
+ 'persons.password IS NOT NULL','call set_person_password(?,?)',
+ NULL,0,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,'seeAlso','seeAlso.dn','ldap_entries seeAlso,documents,authors_docs,persons',
+ 'seeAlso.keyval=documents.id AND seeAlso.oc_map_id=2 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',
+ NULL,NULL,0,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 (7,2,'description','documents.abstract','documents',NULL,'call set_doc_abstract(?,?)',
+ NULL,0,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,2,'documentTitle','documents.title','documents',NULL,'call set_doc_title(?,?)',NULL,0,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','documentAuthor.dn','ldap_entries documentAuthor,documents,authors_docs,persons',
+ 'documentAuthor.keyval=persons.id AND documentAuthor.oc_map_id=1 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',
+ '?=call make_author_link(?,?)','?=call del_author_link(?,?)',0,3);
+
+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 (10,2,'documentIdentifier','''document ''||text(documents.id)','documents',NULL,NULL,NULL,0,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 (11,3,'o','institutes.name','institutes',NULL,'call set_org_name(?,?)',NULL,0,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 (12,3,'dc','lower(institutes.name)','institutes,ldap_entries dcObject,ldap_entry_objclasses auxObjectClass',
+ 'institutes.id=dcObject.keyval AND dcObject.oc_map_id=3 AND dcObject.id=auxObjectClass.entry_id AND auxObjectClass.oc_name=''dcObject''',
+ NULL,NULL,0,0);
+
+-- entries mapping: each entry must appear in this table, with a unique DN rooted at the database naming context
+-- id a unique number > 0 identifying the entry
+-- dn the DN of the entry, in "pretty" form
+-- oc_map_id the "ldap_oc_mappings.id" of the main objectClass of this entry (view it as the structuralObjectClass)
+-- parent the "ldap_entries.id" of the parent of this objectClass; 0 if it is the "suffix" of the database
+-- keyval the value of the "keytbl.keycol" defined for this objectClass
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (ldap_entry_ids.nextval,'dc=example,dc=com',3,0,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (ldap_entry_ids.nextval,'cn=Mitya Kovalev,dc=example,dc=com',1,1,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (ldap_entry_ids.nextval,'cn=Torvlobnor Puzdoy,dc=example,dc=com',1,1,2);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (ldap_entry_ids.nextval,'cn=Akakiy Zinberstein,dc=example,dc=com',1,1,3);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (ldap_entry_ids.nextval,'documentTitle=book1,dc=example,dc=com',2,1,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (ldap_entry_ids.nextval,'documentTitle=book2,dc=example,dc=com',2,1,2);
+
+-- objectClass mapping: entries that have multiple objectClass instances are listed here with the objectClass name (view them as auxiliary objectClass)
+-- entry_id the "ldap_entries.id" of the entry this objectClass value must be added
+-- oc_name the name of the objectClass; it MUST match the name of an objectClass that is loaded in slapd's schema
+insert into ldap_entry_objclasses (entry_id,oc_name)
+values (1,'dcObject');
+
+insert into ldap_entry_objclasses (entry_id,oc_name)
+values (4,'referral');
+
+-- referrals mapping: entries that should be treated as referrals are stored here
+-- entry_id the "ldap_entries.id" of the entry that should be treated as a referral
+-- url the URI of the referral
+insert into ldap_referrals (entry_id,url)
+values (4,'ldap://localhost:9012/');
+
+
+-- procedures
+-- these procedures are specific for this RDBMS and are used in mapping objectClass and attributeType creation/modify/deletion
+CREATE OR REPLACE PROCEDURE create_person(keyval OUT NUMBER) AS
+BEGIN
+INSERT INTO persons (id,name) VALUES (person_ids.nextval,' ');
+SELECT person_ids.currval INTO keyval FROM DUAL;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE delete_person(keyval IN NUMBER) AS
+BEGIN
+DELETE FROM phones WHERE pers_id=keyval;
+DELETE FROM authors_docs WHERE pers_id=keyval;
+DELETE FROM persons WHERE id=keyval;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE create_org(keyval OUT NUMBER) AS
+BEGIN
+INSERT INTO institutes (id,name) VALUES (institute_ids.nextval,' ');
+SELECT institute_ids.currval INTO keyval FROM DUAL;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE delete_org(keyval IN NUMBER) AS
+BEGIN
+DELETE FROM institutes WHERE id=keyval;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE create_document(keyval OUT NUMBER) AS
+BEGIN
+INSERT INTO documents (id,title) VALUES (document_ids.nextval,' ');
+SELECT document_ids.currval INTO keyval FROM DUAL;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE delete_document (keyval IN NUMBER) AS
+BEGIN
+DELETE FROM authors_docs WHERE doc_id=keyval;
+DELETE FROM documents WHERE id=keyval;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE add_phone(pers_id IN NUMBER, phone IN varchar2) AS
+BEGIN
+INSERT INTO phones (id,pers_id,phone) VALUES (phone_ids.nextval,pers_id,phone);
+END;
+/
+
+CREATE OR REPLACE PROCEDURE delete_phone(keyval IN NUMBER, phone IN varchar2) AS
+BEGIN
+DELETE FROM phones WHERE pers_id=keyval AND phone=phone;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE set_person_name(keyval IN NUMBER, new_name IN varchar2) AS
+BEGIN
+UPDATE persons SET name=new_name WHERE id=keyval;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE set_org_name(keyval IN NUMBER, new_name IN varchar2) AS
+BEGIN
+UPDATE institutes SET name=new_name WHERE id=keyval;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE set_doc_title (keyval IN NUMBER, new_title IN varchar2) AS
+BEGIN
+UPDATE documents SET title=new_title WHERE id=keyval;
+END;
+/
+
+CREATE OR REPLACE PROCEDURE set_doc_abstract (keyval IN NUMBER, new_abstract IN varchar2) AS
+BEGIN
+UPDATE documents SET abstract=new_abstract WHERE id=keyval;
+END;
+/
+
+CREATE OR REPLACE FUNCTION make_author_link (keyval IN NUMBER, author_dn IN varchar2) RETURN NUMBER AS
+per_id NUMBER;
+BEGIN
+SELECT keyval INTO per_id FROM ldap_entries
+ WHERE oc_map_id=1 AND dn=author_dn;
+IF NOT (per_id IS NULL) THEN
+ INSERT INTO authors_docs (doc_id,pers_id) VALUES (keyval,per_id);
+ RETURN 1;
+END IF;
+RETURN 0;
+END;
+/
+
+CREATE OR REPLACE FUNCTION make_doc_link (keyval IN NUMBER, doc_dn IN varchar2) RETURN NUMBER AS
+docid NUMBER;
+BEGIN
+SELECT keyval INTO docid FROM ldap_entries
+ WHERE oc_map_id=2 AND dn=doc_dn;
+IF NOT (docid IS NULL) THEN
+ INSERT INTO authors_docs (pers_id,doc_id) VALUES (keyval,docid);
+ RETURN 1;
+END IF;
+RETURN 0;
+END;
+/
+
+CREATE OR REPLACE FUNCTION del_doc_link (keyval IN NUMBER, doc_dn IN varchar2) RETURN NUMBER AS
+docid NUMBER;
+BEGIN
+SELECT keyval INTO docid FROM ldap_entries
+ WHERE oc_map_id=2 AND dn=doc_dn;
+IF NOT (docid IS NULL) THEN
+ DELETE FROM authors_docs WHERE pers_id=keyval AND doc_id=docid;
+ RETURN 1;
+END IF;
+RETURN 0;
+END;
+/
+
+CREATE OR REPLACE FUNCTION del_author_link (keyval IN NUMBER, author_dn IN varchar2) RETURN NUMBER AS
+per_id NUMBER;
+BEGIN
+SELECT keyval INTO per_id FROM ldap_entries
+ WHERE oc_map_id=1 AND dn=author_dn;
+
+IF NOT (per_id IS NULL) THEN
+ DELETE FROM authors_docs WHERE doc_id=keyval AND pers_id=per_id;
+ RETURN 1;
+END IF;
+ RETURN 0;
+END;
+/
diff --git a/servers/slapd/back-sql/rdbms_depend/pgsql/backsql_create.sql b/servers/slapd/back-sql/rdbms_depend/pgsql/backsql_create.sql
new file mode 100644
index 0000000..a4baa70
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/pgsql/backsql_create.sql
@@ -0,0 +1,50 @@
+drop table ldap_oc_mappings;
+drop sequence ldap_oc_mappings_id_seq;
+create table ldap_oc_mappings
+ (
+ id serial not null primary key,
+ name varchar(64) not null,
+ keytbl varchar(64) not null,
+ keycol varchar(64) not null,
+ create_proc varchar(255),
+ delete_proc varchar(255),
+ expect_return int not null
+);
+
+drop table ldap_attr_mappings;
+drop sequence ldap_attr_mappings_id_seq;
+create table ldap_attr_mappings
+ (
+ 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,
+ sel_expr_u varchar(255),
+ from_tbls varchar(255) not null,
+ join_where varchar(255),
+ add_proc varchar(255),
+ delete_proc varchar(255),
+ param_order int not null,
+ expect_return int not null
+);
+
+drop table ldap_entries;
+drop sequence ldap_entries_id_seq;
+create table ldap_entries
+ (
+ 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,
+ keyval int NOT NULL,
+ UNIQUE ( oc_map_id, keyval ),
+ UNIQUE ( dn )
+);
+
+drop table ldap_entry_objclasses;
+create table ldap_entry_objclasses
+ (
+ entry_id integer not null references ldap_entries(id),
+ oc_name varchar(64)
+ );
+
diff --git a/servers/slapd/back-sql/rdbms_depend/pgsql/backsql_drop.sql b/servers/slapd/back-sql/rdbms_depend/pgsql/backsql_drop.sql
new file mode 100644
index 0000000..eff0a9e
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/pgsql/backsql_drop.sql
@@ -0,0 +1,4 @@
+DROP TABLE ldap_entry_objclasses;
+DROP TABLE ldap_attr_mappings;
+DROP TABLE ldap_entries;
+DROP TABLE ldap_oc_mappings;
diff --git a/servers/slapd/back-sql/rdbms_depend/pgsql/slapd.conf b/servers/slapd/back-sql/rdbms_depend/pgsql/slapd.conf
new file mode 100644
index 0000000..70a8dee
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/pgsql/slapd.conf
@@ -0,0 +1,35 @@
+# $OpenLDAP$
+#
+# See slapd.conf(5) for details on configuration options.
+# This file should NOT be world readable.
+#
+include /usr/local/etc/openldap/schema/core.schema
+include /usr/local/etc/openldap/schema/cosine.schema
+include /usr/local/etc/openldap/schema/inetorgperson.schema
+
+# Define global ACLs to disable default read access.
+
+# Do not enable referrals until AFTER you have a working directory
+# service AND an understanding of referrals.
+#referral ldap://root.openldap.org
+
+pidfile /usr/local/var/slapd.pid
+argsfile /usr/local/var/slapd.args
+
+#######################################################################
+# sql database definitions
+#######################################################################
+
+database sql
+suffix "o=sql,c=RU"
+rootdn "cn=root,o=sql,c=RU"
+rootpw secret
+dbname PostgreSQL
+dbuser postgres
+dbpasswd postgres
+insentry_stmt "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
+
diff --git a/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_create.sql b/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_create.sql
new file mode 100644
index 0000000..e1c57e7
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_create.sql
@@ -0,0 +1,55 @@
+drop table persons;
+drop sequence persons_id_seq;
+create table persons (
+ id serial not null primary key,
+ name varchar(255) not null,
+ surname varchar(255) not null,
+ password varchar(64)
+);
+
+drop table institutes;
+drop sequence institutes_id_seq;
+create table institutes (
+ id serial not null primary key,
+ name varchar(255)
+);
+
+drop table documents;
+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 )
+);
+
+drop table phones;
+drop sequence phones_id_seq;
+create table phones (
+ id serial not null primary key,
+ phone varchar(255) not null ,
+ pers_id int not null
+);
+
+drop table certs;
+drop sequence certs_id_seq;
+CREATE TABLE certs (
+ id int not null primary key,
+ cert bytea not null,
+ pers_id int not null
+);
+
+drop table referrals;
+drop sequence referrals_id_seq;
+create table referrals (
+ id serial not null primary key,
+ name varchar(255) not null,
+ url varchar(255) not null
+);
+
diff --git a/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_data.sql b/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_data.sql
new file mode 100644
index 0000000..0e661d4
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_data.sql
@@ -0,0 +1,21 @@
+insert into institutes (id,name) values (1,'Example');
+
+insert into persons (id,name,surname,password) values (1,'Mitya','Kovalev','mit');
+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);
+insert into phones (id,phone,pers_id) values (3,'545-4563',2);
+
+insert into documents (id,abstract,title) values (1,'abstract1','book1');
+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);
+
+insert into referrals (id,name,url) values (1,'Referral','ldap://localhost:9012/');
+
+insert into certs (id,cert,pers_id) values (1,decode('MIIDazCCAtSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjETMBEGA1UEAxMKRXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wHhcNMDMxMDE3MTYzMzE5WhcNMDQxMDE2MTYzMzE5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEfMB0GA1UEChMWT3BlbkxEQVAgRXhhbXBsZSwgTHRkLjEYMBYGA1UEAxMPVXJzdWxhIEhhbXBzdGVyMR8wHQYJKoZIhvcNAQkBFhB1aGFtQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDuxgp5ELV9LmhxWMpV7qc4028QQT3+zzFDXhruuXE7ji2n3S3ea8bOwDtJh+qnsDe561DhHHHlgIjMKCiDEizYMpxvJPYEXmvp0huRkMgpKZgmel95BSkt6TYmJ0erS3aoimOHLEFimmnTLolNRMiWqNBvqwobx940PGwUWEePKQIDAQABo4H/MIH8MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSjI94TbBmuDEeUUOiC37EK0Uf0XjCBoQYDVR0jBIGZMIGWgBRLbyEaNiTSkPlDsFNHLX3hwOaYI6F7pHkwdzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHzAdBgNVBAoTFk9wZW5MREFQIEV4YW1wbGUsIEx0ZC4xEzARBgNVBAMTCkV4YW1wbGUgQ0ExHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tggEAMA0GCSqGSIb3DQEBBAUAA4GBAIgUcARb3OlWYNbmr1nmqESuxLn16uqI1Ot6WkcICvpkdQ+Bo+R9AP05xpoXocZtKdNvBu3FNxB/jFkiOcLU2lX7Px1Ijnsjh60qVRy9HOsHCungIKlGcnXLKHmKu0y//5jds/HnaJsGcHI5JRG7CBJbW+wrwge3trJ1xHJI8prN','base64'),3);
+
diff --git a/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_drop.sql b/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_drop.sql
new file mode 100644
index 0000000..c061ff8
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_drop.sql
@@ -0,0 +1,13 @@
+DROP TABLE persons;
+DROP TABLE institutes;
+DROP TABLE documents;
+DROP TABLE authors_docs;
+DROP TABLE phones;
+DROP TABLE referrals;
+DROP FUNCTION create_person ();
+DROP FUNCTION update_person_cn (varchar, int);
+DROP FUNCTION add_phone (varchar, int);
+DROP FUNCTION create_doc ();
+DROP FUNCTION create_o ();
+DROP FUNCTION create_referral ();
+
diff --git a/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_metadata.sql b/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_metadata.sql
new file mode 100644
index 0000000..d645cf2
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/pgsql/testdb_metadata.sql
@@ -0,0 +1,146 @@
+-- mappings
+
+-- objectClass mappings: these may be viewed as structuralObjectClass, the ones that are used to decide how to build an entry
+-- id a unique number identifying the objectClass
+-- name the name of the objectClass; it MUST match the name of an objectClass that is loaded in slapd's schema
+-- keytbl the name of the table that is referenced for the primary key of an entry
+-- keycol the name of the column in "keytbl" that contains the primary key of an entry; the pair "keytbl.keycol" uniquely identifies an entry of objectClass "id"
+-- create_proc a procedure to create the entry
+-- delete_proc a procedure to delete the entry; it takes "keytbl.keycol" of the row to be deleted
+-- expect_return a bitmap that marks whether create_proc (1) and delete_proc (2) return a value or not
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return) values (1,'inetOrgPerson','persons','id','SELECT create_person()','DELETE FROM persons WHERE id=?',0);
+
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return) values (2,'document','documents','id','SELECT create_doc()','DELETE FROM documents WHERE id=?',0);
+
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return) values (3,'organization','institutes','id','SELECT create_o()','DELETE FROM institutes WHERE id=?',0);
+
+insert into ldap_oc_mappings (id,name,keytbl,keycol,create_proc,delete_proc,expect_return) values (4,'referral','referrals','id','SELECT create_referral()','DELETE FROM referrals WHERE id=?',0);
+
+-- attributeType mappings: describe how an attributeType for a certain objectClass maps to the SQL data.
+-- id a unique number identifying the attribute
+-- oc_map_id the value of "ldap_oc_mappings.id" that identifies the objectClass this attributeType is defined for
+-- name the name of the attributeType; it MUST match the name of an attributeType that is loaded in slapd's schema
+-- sel_expr the expression that is used to select this attribute (the "select <sel_expr> from ..." portion)
+-- from_tbls the expression that defines the table(s) this attribute is taken from (the "select ... from <from_tbls> where ..." portion)
+-- join_where the expression that defines the condition to select this attribute (the "select ... where <join_where> ..." portion)
+-- add_proc a procedure to insert the attribute; it takes the value of the attribute that is added, and the "keytbl.keycol" of the entry it is associated to
+-- delete_proc a procedure to delete the attribute; it takes the value of the attribute that is added, and the "keytbl.keycol" of the entry it is associated to
+-- param_order a mask that marks if the "keytbl.keycol" value comes before or after the value in add_proc (1) and delete_proc (2)
+-- expect_return a mask that marks whether add_proc (1) and delete_proc(2) are expected to return a value or not
+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(?,?)','SELECT 1 FROM persons WHERE persons.name=? AND persons.id=? AND 1=0',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(?,?)','DELETE FROM phones WHERE phone=? AND pers_id=?',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=?','UPDATE persons SET name='''' WHERE (name=? OR name='''') AND id=?',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,1,'sn','persons.surname','persons',NULL,'UPDATE persons SET surname=? WHERE id=?','UPDATE persons SET surname='''' WHERE (surname=? OR surname='''') AND id=?',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 (5,1,'userPassword','persons.password','persons','persons.password IS NOT NULL','UPDATE persons SET password=? WHERE id=?','UPDATE persons SET password=NULL WHERE password=? AND id=?',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,'seeAlso','seeAlso.dn','ldap_entries AS seeAlso,documents,authors_docs,persons','seeAlso.keyval=documents.id AND seeAlso.oc_map_id=2 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id',NULL,'DELETE from authors_docs WHERE authors_docs.doc_id=(SELECT documents.id FROM documents,ldap_entries AS seeAlso WHERE seeAlso.keyval=documents.id AND seeAlso.oc_map_id=2 AND seeAlso.dn=?) AND authors_docs.pers_id=?',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 (7,2,'description','documents.abstract','documents',NULL,'UPDATE documents SET abstract=? WHERE id=?','UPDATE documents SET abstract='''' WHERE abstract=? AND id=?',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,2,'documentTitle','documents.title','documents',NULL,'UPDATE documents SET title=? WHERE id=?','UPDATE documents SET title='''' WHERE title=? AND id=?',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','documentAuthor.dn','ldap_entries AS documentAuthor,documents,authors_docs,persons','documentAuthor.keyval=persons.id AND documentAuthor.oc_map_id=1 AND authors_docs.doc_id=documents.id AND authors_docs.pers_id=persons.id','INSERT INTO authors_docs (pers_id,doc_id) VALUES ((SELECT ldap_entries.keyval FROM ldap_entries WHERE upper(?)=upper(ldap_entries.dn)),?)','DELETE FROM authors_docs WHERE authors_docs.pers_id=(SELECT ldap_entries.keyval FROM ldap_entries WHERE upper(?)=upper(ldap_entries.dn)) AND authors_docs.doc_id=?',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 (10,2,'documentIdentifier','''document ''||text(documents.id)','documents',NULL,NULL,'SELECT 1 FROM documents WHERE title=? AND id=? AND 1=0',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 (11,3,'o','institutes.name','institutes',NULL,'UPDATE institutes SET name=? WHERE id=?','UPDATE institutes SET name='''' WHERE name=? AND id=?',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 (12,3,'dc','lower(institutes.name)','institutes,ldap_entries AS dcObject,ldap_entry_objclasses AS auxObjectClass','institutes.id=dcObject.keyval AND dcObject.oc_map_id=3 AND dcObject.id=auxObjectClass.entry_id AND auxObjectClass.oc_name=''dcObject''',NULL,'SELECT 1 FROM institutes WHERE lower(name)=? AND id=? and 1=0',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 (13,4,'ou','referrals.name','referrals',NULL,'UPDATE referrals SET name=? WHERE id=?','SELECT 1 FROM referrals WHERE name=? AND id=? and 1=0',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 (14,4,'ref','referrals.url','referrals',NULL,'UPDATE referrals SET url=? WHERE id=?','SELECT 1 FROM referrals WHERE url=? and id=? and 1=0',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 (15,1,'userCertificate','certs.cert','persons,certs','certs.pers_id=persons.id',NULL,NULL,3,0);
+
+-- entries mapping: each entry must appear in this table, with a unique DN rooted at the database naming context
+-- id a unique number > 0 identifying the entry
+-- dn the DN of the entry, in "pretty" form
+-- oc_map_id the "ldap_oc_mappings.id" of the main objectClass of this entry (view it as the structuralObjectClass)
+-- parent the "ldap_entries.id" of the parent of this objectClass; 0 if it is the "suffix" of the database
+-- keyval the value of the "keytbl.keycol" defined for this objectClass
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values (1,'dc=example,dc=com',3,0,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values (2,'cn=Mitya Kovalev,dc=example,dc=com',1,1,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values (3,'cn=Torvlobnor Puzdoy,dc=example,dc=com',1,1,2);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values (4,'cn=Akakiy Zinberstein,dc=example,dc=com',1,1,3);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values (5,'documentTitle=book1,dc=example,dc=com',2,1,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values (6,'documentTitle=book2,dc=example,dc=com',2,1,2);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values (7,'ou=Referral,dc=example,dc=com',4,1,1);
+
+-- objectClass mapping: entries that have multiple objectClass instances are listed here with the objectClass name (view them as auxiliary objectClass)
+-- entry_id the "ldap_entries.id" of the entry this objectClass value must be added
+-- oc_name the name of the objectClass; it MUST match the name of an objectClass that is loaded in slapd's schema
+insert into ldap_entry_objclasses (entry_id,oc_name) values (1,'dcObject');
+
+insert into ldap_entry_objclasses (entry_id,oc_name) values (4,'pkiUser');
+
+insert into ldap_entry_objclasses (entry_id,oc_name) values (7,'extensibleObject');
+
+-- procedures
+-- these procedures are specific for this RDBMS and are used in mapping objectClass and attributeType creation/modify/deletion
+create function create_person () returns int
+as '
+ select setval (''persons_id_seq'', (select case when max(id) is null then 1 else max(id) end from persons));
+ insert into persons (id,name,surname)
+ values ((select case when max(id) is null then 1 else nextval(''persons_id_seq'') end from persons),'''','''');
+ 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 add_phone (varchar, int) returns int
+as '
+ select setval (''phones_id_seq'', (select case when max(id) is null then 1 else max(id) end 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 create_doc () returns int
+as '
+ select setval (''documents_id_seq'', (select case when max(id) is null then 1 else max(id) end from documents));
+ insert into documents (id,title,abstract)
+ values ((select case when max(id) is null then 1 else nextval(''documents_id_seq'') end from documents),'''','''');
+ select max(id) from documents
+' language 'sql';
+
+create function create_o () returns int
+as '
+ select setval (''institutes_id_seq'', (select case when max(id) is null then 1 else max(id) end from institutes));
+ insert into institutes (id,name)
+ values ((select case when max(id) is null then 1 else nextval(''institutes_id_seq'') end from institutes),'''');
+ select max(id) from institutes
+' language 'sql';
+
+create function create_referral () returns int
+as '
+ select setval (''referrals_id_seq'', (select case when max(id) is null then 1 else max(id) end from referrals));
+ insert into referrals (id,name,url)
+ values ((select case when max(id) is null then 1 else nextval(''referrals_id_seq'') end from referrals),'''','''');
+ select max(id) from referrals
+' language 'sql';
+
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/backsql_create.sql b/servers/slapd/back-sql/rdbms_depend/timesten/backsql_create.sql
new file mode 100644
index 0000000..055e9df
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/backsql_create.sql
@@ -0,0 +1,66 @@
+
+create table ldap_oc_mappings
+ (
+ id integer not null primary key,
+ name varchar(64) not null,
+ keytbl varchar(64) not null,
+ keycol varchar(64) not null,
+ create_proc varchar(255),
+ delete_proc varchar(255),
+ expect_return tinyint not null
+);
+
+create table ldap_attr_mappings
+ (
+ id integer not null primary key,
+ oc_map_id integer not null,
+ name varchar(255) not null,
+ sel_expr varchar(255) not null,
+ sel_expr_u varchar(255),
+ from_tbls varchar(255) not null,
+ join_where varchar(255),
+ add_proc varchar(255),
+ delete_proc varchar(255),
+ param_order tinyint not null,
+ expect_return tinyint not null,
+ foreign key (oc_map_id) references ldap_oc_mappings(id)
+);
+
+create table ldap_entries
+ (
+ id integer not null primary key,
+ dn varchar(255) not null,
+ dn_ru varchar(255),
+ oc_map_id integer not null,
+ parent int NOT NULL ,
+ keyval int NOT NULL,
+ foreign key (oc_map_id) references ldap_oc_mappings(id)
+);
+
+create index ldap_entriesx1 on ldap_entries(dn_ru);
+
+create unique index unq1_ldap_entries on ldap_entries
+ (
+ oc_map_id,
+ keyval
+ );
+
+create unique index unq2_ldap_entries on ldap_entries
+ (
+ dn
+ );
+
+create table ldap_referrals
+ (
+ entry_id integer not null,
+ url varchar(4096) not null,
+ foreign key (entry_id) references ldap_entries(id)
+);
+
+create table ldap_entry_objclasses
+ (
+ entry_id integer not null,
+ oc_name varchar(64),
+ foreign key (entry_id) references ldap_entries(id)
+ );
+
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/backsql_drop.sql b/servers/slapd/back-sql/rdbms_depend/timesten/backsql_drop.sql
new file mode 100644
index 0000000..7aa0b83
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/backsql_drop.sql
@@ -0,0 +1,9 @@
+DROP TABLE ldap_referrals;
+
+DROP TABLE ldap_entry_objclasses;
+
+DROP TABLE ldap_attr_mappings;
+
+DROP TABLE ldap_entries;
+
+DROP TABLE ldap_oc_mappings;
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/create_schema.sh b/servers/slapd/back-sql/rdbms_depend/timesten/create_schema.sh
new file mode 100755
index 0000000..947db21
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/create_schema.sh
@@ -0,0 +1,4 @@
+ttIsql -connStr "DSN=ldap_tt;Overwrite=1" -f backsql_create.sql
+ttIsql -connStr "DSN=ldap_tt" -f testdb_create.sql
+ttIsql -connStr "DSN=ldap_tt" -f testdb_data.sql
+ttIsql -connStr "DSN=ldap_tt" -f testdb_metadata.sql
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/Makefile b/servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/Makefile
new file mode 100644
index 0000000..1b0b1ee
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/Makefile
@@ -0,0 +1,48 @@
+## Copyright 1997-2022 The OpenLDAP Foundation, All Rights Reserved.
+## COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+
+#
+# Build TimesTen ODBC Sample Programs for Solaris 2.5.1.
+# (c) Copyright 1996-1998, TimesTen Performance Software.
+# All rights reserved.
+## Note: This file was contributed by Sam Drake of TimesTen Performance
+## Software for use and redistribution as an integral part of
+## OpenLDAP Software. -Kdz
+
+CPLUSPLUS = CC
+TTCLASSES = ../../../../../../../../../cs/classes
+ODBC = /opt/TimesTen4.1/32
+CFLAGS = -g -I$(ODBC)/include -I. -I$(TTCLASSES) -DUNIX
+LDFLAGS = -g
+DIRLIBS = $(TTCLASSES)/ttclasses.a -L $(ODBC)/lib -R $(ODBC)/lib -ltten -lpthread -lm -lrt
+XLALIB = -L $(ODBC)/lib -lxla
+
+DIRPROGS= dnreverse
+
+DNREVERSE= dnreverse.o
+
+#
+# Top-level targets
+#
+
+all: $(DIRPROGS)
+
+direct: $(DIRPROGS)
+
+clean:
+ rm -rf $(DIRPROGS) *.o
+
+
+#
+# Direct-linked programs
+#
+
+dnreverse: $(DNREVERSE)
+ $(CPLUSPLUS) -o dnreverse $(LDFLAGS) $(DNREVERSE) $(DIRLIBS) $(XLALIB)
+
+#
+# .o files
+#
+
+dnreverse.o: dnreverse.cpp
+ $(CPLUSPLUS) $(CFLAGS) -c dnreverse.cpp
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp b/servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp
new file mode 100644
index 0000000..7407b4e
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/dnreverse/dnreverse.cpp
@@ -0,0 +1,387 @@
+// Copyright 1997-2022 The OpenLDAP Foundation, All Rights Reserved.
+// COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+
+// (c) Copyright 1999-2001 TimesTen Performance Software. All rights reserved.
+
+//// Note: This file was contributed by Sam Drake of TimesTen Performance
+//// Software for use and redistribution as an integral part of
+//// OpenLDAP Software. -Kdz
+
+#include <stdlib.h>
+
+#include <TTConnectionPool.h>
+#include <TTConnection.h>
+#include <TTCmd.h>
+#include <TTXla.h>
+
+#include <signal.h>
+
+TTConnectionPool pool;
+TTXlaConnection conn;
+TTConnection conn2;
+TTCmd assignDn_ru;
+TTCmd getNullDNs;
+
+//----------------------------------------------------------------------
+// This class contains all the logic to be implemented whenever
+// the SCOTT.MYDATA table is changed. This is the table that is
+// created by "sample.cpp", one of the other TTClasses demos.
+// That application should be executed before this one in order to
+// create and populate the table.
+//----------------------------------------------------------------------
+
+class LDAPEntriesHandler: public TTXlaTableHandler {
+private:
+ // Definition of the columns in the table
+ int Id;
+ int Dn;
+ int Oc_map_id;
+ int Parent;
+ int Keyval;
+ int Dn_ru;
+
+protected:
+
+public:
+ LDAPEntriesHandler(TTXlaConnection& conn, const char* ownerP, const char* nameP);
+ ~LDAPEntriesHandler();
+
+ virtual void HandleDelete(ttXlaUpdateDesc_t*);
+ virtual void HandleInsert(ttXlaUpdateDesc_t*);
+ virtual void HandleUpdate(ttXlaUpdateDesc_t*);
+
+ static void ReverseAndUpper(char* dnP, int id, bool commit=true);
+
+};
+
+LDAPEntriesHandler::LDAPEntriesHandler(TTXlaConnection& conn,
+ const char* ownerP, const char* nameP) :
+ TTXlaTableHandler(conn, ownerP, nameP)
+{
+ Id = Dn = Oc_map_id = Parent = Keyval = Dn_ru = -1;
+
+ // We are looking for several particular named columns. We need to get
+ // the ordinal position of the columns by name for later use.
+
+ Id = tbl.getColNumber("ID");
+ if (Id < 0) {
+ cerr << "target table has no 'ID' column" << endl;
+ exit(1);
+ }
+ Dn = tbl.getColNumber("DN");
+ if (Dn < 0) {
+ cerr << "target table has no 'DN' column" << endl;
+ exit(1);
+ }
+ Oc_map_id = tbl.getColNumber("OC_MAP_ID");
+ if (Oc_map_id < 0) {
+ cerr << "target table has no 'OC_MAP_ID' column" << endl;
+ exit(1);
+ }
+ Parent = tbl.getColNumber("PARENT");
+ if (Parent < 0) {
+ cerr << "target table has no 'PARENT' column" << endl;
+ exit(1);
+ }
+ Keyval = tbl.getColNumber("KEYVAL");
+ if (Keyval < 0) {
+ cerr << "target table has no 'KEYVAL' column" << endl;
+ exit(1);
+ }
+ Dn_ru = tbl.getColNumber("DN_RU");
+ if (Dn_ru < 0) {
+ cerr << "target table has no 'DN_RU' column" << endl;
+ exit(1);
+ }
+
+}
+
+LDAPEntriesHandler::~LDAPEntriesHandler()
+{
+
+}
+
+void LDAPEntriesHandler::ReverseAndUpper(char* dnP, int id, bool commit)
+{
+ TTStatus stat;
+ char dn_rn[512];
+ int i;
+ int j;
+
+ // Reverse and upper case the given DN
+
+ for ((j=0, i = strlen(dnP)-1); i > -1; (j++, i--)) {
+ dn_rn[j] = toupper(*(dnP+i));
+ }
+ dn_rn[j] = '\0';
+
+
+ // Update the database
+
+ try {
+ assignDn_ru.setParam(1, (char*) &dn_rn[0]);
+ assignDn_ru.setParam(2, id);
+ assignDn_ru.Execute(stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error updating id " << id << " ('" << dnP << "' to '"
+ << dn_rn << "'): " << stat;
+ exit(1);
+ }
+
+ // Commit the transaction
+
+ if (commit) {
+ try {
+ conn2.Commit(stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error committing update: " << stat;
+ exit(1);
+ }
+ }
+
+}
+
+
+
+void LDAPEntriesHandler::HandleInsert(ttXlaUpdateDesc_t* p)
+{
+ char* dnP;
+ int id;
+
+ row.Get(Dn, &dnP);
+ cerr << "DN '" << dnP << "': Inserted ";
+ row.Get(Id, &id);
+
+ ReverseAndUpper(dnP, id);
+
+}
+
+void LDAPEntriesHandler::HandleUpdate(ttXlaUpdateDesc_t* p)
+{
+ char* newDnP;
+ char* oldDnP;
+ char oDn[512];
+ int id;
+
+ // row is 'old'; row2 is 'new'
+ row.Get(Dn, &oldDnP);
+ strcpy(oDn, oldDnP);
+ row.Get(Id, &id);
+ row2.Get(Dn, &newDnP);
+
+ cerr << "old DN '" << oDn << "' / new DN '" << newDnP << "' : Updated ";
+
+ if (strcmp(oDn, newDnP) != 0) {
+ // The DN field changed, update it
+ cerr << "(new DN: '" << newDnP << "')";
+ ReverseAndUpper(newDnP, id);
+ }
+ else {
+ // The DN field did NOT change, leave it alone
+ }
+
+ cerr << endl;
+
+}
+
+void LDAPEntriesHandler::HandleDelete(ttXlaUpdateDesc_t* p)
+{
+ char* dnP;
+
+ row.Get(Dn, &dnP);
+ cerr << "DN '" << dnP << "': Deleted ";
+}
+
+
+
+
+//----------------------------------------------------------------------
+
+int pleaseStop = 0;
+
+extern "C" {
+ void
+ onintr(int sig)
+ {
+ pleaseStop = 1;
+ cerr << "Stopping...\n";
+ }
+};
+
+//----------------------------------------------------------------------
+
+int
+main(int argc, char* argv[])
+{
+
+ char* ownerP;
+
+ TTXlaTableList list(&conn); // List of tables to monitor
+
+ // Handlers, one for each table we want to monitor
+
+ LDAPEntriesHandler* sampP = NULL;
+
+ // Misc stuff
+
+ TTStatus stat;
+
+ ttXlaUpdateDesc_t ** arry;
+
+ int records;
+
+ SQLUBIGINT oldsize;
+ int j;
+
+ if (argc < 2) {
+ cerr << "syntax: " << argv[0] << " <username>" << endl;
+ exit(3);
+ }
+
+ ownerP = argv[1];
+
+ signal(SIGINT, onintr); /* signal for CTRL-C */
+#ifdef _WIN32
+ signal(SIGBREAK, onintr); /* signal for CTRL-BREAK */
+#endif
+
+ // Before we do anything related to XLA, first we connect
+ // to the database. This is the connection we will use
+ // to perform non-XLA operations on the tables.
+
+ try {
+ cerr << "Connecting..." << endl;
+
+ conn2.Connect("DSN=ldap_tt", stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error connecting to TimesTen: " << stat;
+ exit(1);
+ }
+
+ try {
+ assignDn_ru.Prepare(&conn2,
+ "update ldap_entries set dn_ru=? where id=?",
+ "", stat);
+ getNullDNs.Prepare(&conn2,
+ "select dn, id from ldap_entries "
+ "where dn_ru is null "
+ "for update",
+ "", stat);
+ conn2.Commit(stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error preparing update: " << stat;
+ exit(1);
+ }
+
+ // If there are any entries with a NULL reversed/upper cased DN,
+ // fix them now.
+
+ try {
+ cerr << "Fixing NULL reversed DNs" << endl;
+ getNullDNs.Execute(stat);
+ for (int k = 0;; k++) {
+ getNullDNs.FetchNext(stat);
+ if (stat.rc == SQL_NO_DATA_FOUND) break;
+ char* dnP;
+ int id;
+ getNullDNs.getColumn(1, &dnP);
+ getNullDNs.getColumn(2, &id);
+ // cerr << "Id " << id << ", Dn '" << dnP << "'" << endl;
+ LDAPEntriesHandler::ReverseAndUpper(dnP, id, false);
+ if (k % 1000 == 0)
+ cerr << ".";
+ }
+ getNullDNs.Close(stat);
+ conn2.Commit(stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error updating NULL rows: " << stat;
+ exit(1);
+ }
+
+
+ // Go ahead and start up the change monitoring application
+
+ cerr << "Starting change monitoring..." << endl;
+ try {
+ conn.Connect("DSN=ldap_tt", stat);
+ }
+ catch (TTStatus stat) {
+ cerr << "Error connecting to TimesTen: " << stat;
+ exit(1);
+ }
+
+ /* set and configure size of buffer */
+ conn.setXlaBufferSize((SQLUBIGINT) 1000000, &oldsize, stat);
+ if (stat.rc) {
+ cerr << "Error setting buffer size " << stat << endl;
+ exit(1);
+ }
+
+ // Make a handler to process changes to the MYDATA table and
+ // add the handler to the list of all handlers
+
+ sampP = new LDAPEntriesHandler(conn, ownerP, "ldap_entries");
+ if (!sampP) {
+ cerr << "Could not create LDAPEntriesHandler" << endl;
+ exit(3);
+ }
+ list.add(sampP);
+
+ // Enable transaction logging for the table we're interested in
+
+ sampP->EnableTracking(stat);
+
+ // Get updates. Dispatch them to the appropriate handler.
+ // This loop will handle updates to all the tables.
+
+ while (pleaseStop == 0) {
+ conn.fetchUpdates(&arry, 1000, &records, stat);
+ if (stat.rc) {
+ cerr << "Error fetching updates" << stat << endl;
+ exit(1);
+ }
+
+ // Interpret the updates
+
+ for(j=0;j < records;j++){
+ ttXlaUpdateDesc_t *p;
+
+ p = arry[j];
+
+ list.HandleChange(p, stat);
+
+ } // end for each record fetched
+
+ if (records) {
+ cerr << "Processed " << records << " records\n";
+ }
+
+ if (records == 0) {
+#ifdef _WIN32
+ Sleep(250);
+#else
+ struct timeval t;
+ t.tv_sec = 0;
+ t.tv_usec = 250000; // .25 seconds
+ select(0, NULL, NULL, NULL, &t);
+#endif
+ }
+ } // end while pleasestop == 0
+
+
+ // When we get to here, the program is exiting.
+
+ list.del(sampP); // Take the table out of the list
+ delete sampP;
+
+ conn.setXlaBufferSize(oldsize, NULL, stat);
+
+ return 0;
+
+}
+
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/slapd.conf b/servers/slapd/back-sql/rdbms_depend/timesten/slapd.conf
new file mode 100644
index 0000000..f93de8b
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/slapd.conf
@@ -0,0 +1,31 @@
+# $OpenLDAP$
+#
+# See slapd.conf(5) for details on configuration options.
+# This file should NOT be world readable.
+#
+include /usr/local/etc/openldap/schema/core.schema
+include /usr/local/etc/openldap/schema/cosine.schema
+include /usr/local/etc/openldap/schema/inetorgperson.schema
+
+# Define global ACLs to disable default read access.
+
+# Do not enable referrals until AFTER you have a working directory
+# service AND an understanding of referrals.
+#referral ldap://root.openldap.org
+
+pidfile /usr/local/var/slapd.pid
+argsfile /usr/local/var/slapd.args
+
+#######################################################################
+# sql database definitions
+#######################################################################
+
+database sql
+suffix "o=sql,c=RU"
+rootdn "cn=root,o=sql,c=RU"
+rootpw secret
+dbname ldap_tt
+dbuser root
+dbpasswd
+subtree_cond "ldap_entries.dn LIKE ?"
+insentry_stmt "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) VALUES (?,?,?,?)"
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/testdb_create.sql b/servers/slapd/back-sql/rdbms_depend/timesten/testdb_create.sql
new file mode 100644
index 0000000..768aec8
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/testdb_create.sql
@@ -0,0 +1,36 @@
+CREATE TABLE persons (
+ id int NOT NULL primary key,
+ name varchar(255) NOT NULL
+)
+unique hash on (id) pages=100;
+
+CREATE TABLE institutes (
+ id int NOT NULL primary key,
+ name varchar(255)
+)
+unique hash on (id) pages=100;
+
+CREATE TABLE documents (
+ id int NOT NULL primary key,
+ title varchar(255) NOT NULL,
+ abstract varchar(255)
+)
+unique hash on (id) pages=100;
+
+CREATE TABLE authors_docs (
+ pers_id int NOT NULL,
+ doc_id int NOT NULL,
+ PRIMARY KEY
+ (
+ pers_id,
+ doc_id
+ )
+) unique hash on (pers_id, doc_id) pages=100;
+
+CREATE TABLE phones (
+ id int NOT NULL primary key,
+ phone varchar(255) NOT NULL ,
+ pers_id int NOT NULL
+)
+unique hash on (id) pages=100;
+
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/testdb_data.sql b/servers/slapd/back-sql/rdbms_depend/timesten/testdb_data.sql
new file mode 100644
index 0000000..f141f41
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/testdb_data.sql
@@ -0,0 +1,16 @@
+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 phones (id,phone,pers_id) values (1,'332-2334',1);
+insert into phones (id,phone,pers_id) values (2,'222-3234',1);
+insert into phones (id,phone,pers_id) values (3,'545-4563',2);
+
+insert into documents (id,abstract,title) values (1,'abstract1','book1');
+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);
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/testdb_drop.sql b/servers/slapd/back-sql/rdbms_depend/timesten/testdb_drop.sql
new file mode 100644
index 0000000..17b12af
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/testdb_drop.sql
@@ -0,0 +1,5 @@
+DROP TABLE persons;
+DROP TABLE institutes;
+DROP TABLE documents;
+DROP TABLE authors_docs;
+DROP TABLE phones;
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/testdb_metadata.sql b/servers/slapd/back-sql/rdbms_depend/timesten/testdb_metadata.sql
new file mode 100644
index 0000000..f9e3419
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/testdb_metadata.sql
@@ -0,0 +1,108 @@
+
+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,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, 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);
+
+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);
+
+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
+(5, 2, 'documentTitle','documents.title','documents',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 (6,2,'documentAuthor','persons.name','persons,documents,authors_docs',
+-- 'persons.id=authors_docs.pers_id AND documents.id=authors_docs.doc_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
+(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 (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);
+
+-- entries
+
+insert into ldap_entries
+(id, dn, oc_map_id, parent, keyval)
+values
+(1, 'o=sql,c=RU', 3, 0, 1);
+
+insert into ldap_entries
+(id, dn, oc_map_id, parent, keyval)
+values
+(2, 'cn=Mitya Kovalev,o=sql,c=RU', 1, 1, 1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (3,'cn=Torvlobnor Puzdoy,o=sql,c=RU',1,1,2);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (4,'cn=Akakiy Zinberstein,o=sql,c=RU',1,1,3);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (5,'documentTitle=book1,o=sql,c=RU',2,1,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (6,'documentTitle=book2,o=sql,c=RU',2,1,2);
+
+
+-- referrals
+
+insert into ldap_entry_objclasses (entry_id,oc_name)
+values (4,'referral');
+
+insert into ldap_referrals (entry_id,url)
+values (4,'ldap://localhost:9012');
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/ttcreate_schema.sh b/servers/slapd/back-sql/rdbms_depend/timesten/ttcreate_schema.sh
new file mode 100755
index 0000000..c4c5df2
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/ttcreate_schema.sh
@@ -0,0 +1,4 @@
+ttIsql -connStr "DSN=ldap_tt;Overwrite=1" -f backsql_create.sql
+ttIsql -connStr "DSN=ldap_tt" -f tttestdb_create.sql
+ttIsql -connStr "DSN=ldap_tt" -f tttestdb_data.sql
+ttIsql -connStr "DSN=ldap_tt" -f tttestdb_metadata.sql
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_create.sql b/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_create.sql
new file mode 100644
index 0000000..f5955d2
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_create.sql
@@ -0,0 +1,42 @@
+CREATE TABLE persons (
+ id int NOT NULL primary key,
+ name varchar(255) NOT NULL,
+ name_u varchar(255),
+ title varchar(255),
+ title_U varchar(255),
+ organization varchar(255)
+)
+unique hash on (id) pages=100;
+create index personsx1 on persons(title_U);
+create index personsx2 on persons(name_u);
+
+CREATE TABLE institutes (
+ id int NOT NULL primary key,
+ name varchar(255)
+)
+unique hash on (id) pages=100;
+
+CREATE TABLE documents (
+ id int NOT NULL primary key,
+ title varchar(255) NOT NULL,
+ abstract varchar(255)
+)
+unique hash on (id) pages=100;
+
+CREATE TABLE authors_docs (
+ pers_id int NOT NULL,
+ doc_id int NOT NULL,
+ PRIMARY KEY
+ (
+ pers_id,
+ doc_id
+ )
+) unique hash on (pers_id, doc_id) pages=100;
+
+CREATE TABLE phones (
+ id int NOT NULL primary key,
+ phone varchar(255) NOT NULL ,
+ pers_id int NOT NULL
+)
+unique hash on (id) pages=100;
+
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_data.sql b/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_data.sql
new file mode 100644
index 0000000..ca75339
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_data.sql
@@ -0,0 +1,20 @@
+insert into institutes (id,name) values (1,'sql');
+
+insert into persons (id,name, title, title_U, organization) values
+(1,'Mitya Kovalev', 'Engineer', 'ENGINEER', 'Development');
+insert into persons (id,name, title, title_U, organization) values
+(2,'Torvlobnor Puzdoy', 'Engineer', 'ENGINEER', 'Sales');
+insert into persons (id,name, title, title_U, organization) values
+(3,'Akakiy Zinberstein', 'Engineer', 'ENGINEER', 'Marketing');
+update persons set name_u = upper(name);
+
+insert into phones (id,phone,pers_id) values (1,'332-2334',1);
+insert into phones (id,phone,pers_id) values (2,'222-3234',1);
+insert into phones (id,phone,pers_id) values (3,'545-4563',2);
+
+insert into documents (id,abstract,title) values (1,'abstract1','book1');
+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);
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_drop.sql b/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_drop.sql
new file mode 100644
index 0000000..17b12af
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_drop.sql
@@ -0,0 +1,5 @@
+DROP TABLE persons;
+DROP TABLE institutes;
+DROP TABLE documents;
+DROP TABLE authors_docs;
+DROP TABLE phones;
diff --git a/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_metadata.sql b/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_metadata.sql
new file mode 100644
index 0000000..69bda8a
--- /dev/null
+++ b/servers/slapd/back-sql/rdbms_depend/timesten/tttestdb_metadata.sql
@@ -0,0 +1,122 @@
+
+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,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, sel_expr_u, from_tbls,
+join_where,add_proc, delete_proc,param_order,expect_return)
+values
+(1, 1, 'cn', 'persons.name', 'persons.name_u','persons',
+NULL, NULL, NULL, 3, 0);
+
+insert into ldap_attr_mappings
+(id, oc_map_id, name, sel_expr, sel_expr_u, from_tbls,join_where,
+add_proc, delete_proc,param_order,expect_return)
+values
+(10, 1, 'title', 'persons.title', 'persons.title_u', '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);
+
+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
+(30, 1, 'ou', 'persons.organization','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
+(4, 2, 'description', 'documents.abstract','documents', 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
+(5, 2, 'documentTitle','documents.title','documents',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 (6,2,'documentAuthor','persons.name','persons,documents,authors_docs',
+-- 'persons.id=authors_docs.pers_id AND documents.id=authors_docs.doc_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
+(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 (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);
+
+-- entries
+
+insert into ldap_entries
+(id, dn, oc_map_id, parent, keyval)
+values
+(1, 'o=sql,c=RU', 3, 0, 1);
+
+insert into ldap_entries
+(id, dn, oc_map_id, parent, keyval)
+values
+(2, 'cn=Mitya Kovalev,o=sql,c=RU', 1, 1, 1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (3,'cn=Torvlobnor Puzdoy,o=sql,c=RU',1,1,2);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (4,'cn=Akakiy Zinberstein,o=sql,c=RU',1,1,3);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (5,'documentTitle=book1,o=sql,c=RU',2,1,1);
+
+insert into ldap_entries (id,dn,oc_map_id,parent,keyval)
+values (6,'documentTitle=book2,o=sql,c=RU',2,1,2);
+
+
+-- referrals
+
+insert into ldap_entry_objclasses (entry_id,oc_name)
+values (4,'referral');
+
+insert into ldap_referrals (entry_id,url)
+values (4,'http://localhost');