Merge branch 'its10506' into 'OPENLDAP_REL_ENG_2_7'

ITS#10506 - Remove back-sql

See merge request openldap/openldap!880
This commit is contained in:
Quanah Gibson-Mount 2026-05-19 19:51:56 +00:00
commit 38d68e0785
111 changed files with 7 additions and 19786 deletions

View file

@ -202,11 +202,7 @@ MODULES_LDFLAGS = @SLAPD_MODULES_LDFLAGS@
MODULES_LIBS = @MODULES_LIBS@
SLAPD_PERL_LDFLAGS = @SLAPD_PERL_LDFLAGS@
SLAPD_SQL_LDFLAGS = @SLAPD_SQL_LDFLAGS@
SLAPD_SQL_INCLUDES = @SLAPD_SQL_INCLUDES@
SLAPD_SQL_LIBS = @SLAPD_SQL_LIBS@
SLAPD_LIBS = @SLAPD_LIBS@ @SLAPD_PERL_LDFLAGS@ @SLAPD_SQL_LDFLAGS@ @SLAPD_SQL_LIBS@ @SLAPD_SLP_LIBS@ @SLAPD_GMP_LIBS@
SLAPD_LIBS = @SLAPD_LIBS@ @SLAPD_PERL_LDFLAGS@ @SLAPD_SLP_LIBS@ @SLAPD_GMP_LIBS@
LLOADD_LIBS = @BALANCER_LIBS@ $(LEVENT_LIBS)
# Our Defaults

View file

@ -322,8 +322,6 @@ OL_ARG_ENABLE_BK(relay, [relay backend],
yes, [no yes mod], ol_enable_backends)dnl
OL_ARG_ENABLE_BK(sock, [sock backend],
no, [no yes mod], ol_enable_backends)dnl
OL_ARG_ENABLE_BK(sql, [sql backend],
no, [no yes mod], ol_enable_backends)dnl
OL_ARG_ENABLE_BK(wt, [WiredTiger backend],
no, [no yes mod], ol_enable_backends)dnl
@ -565,10 +563,6 @@ SLAPD_PERL_LDFLAGS=
MOD_PERL_LDFLAGS=
PERL_CPPFLAGS=
SLAPD_SQL_LDFLAGS=
SLAPD_SQL_LIBS=
SLAPD_SQL_INCLUDES=
SASL_LIBS=
TLS_LIBS=
WITH_TLS_TYPE=no
@ -1914,77 +1908,6 @@ if test $ol_enable_syslog != no ; then
ol_enable_syslog=$ac_cv_func_openlog
fi
dnl ----------------------------------------------------------------
dnl SQL
ol_link_sql=no
if test $ol_enable_sql != no ; then
AC_CHECK_HEADERS(sql.h sqlext.h,[],[
AC_MSG_ERROR([could not locate SQL headers])
])
sql_LIBS="$LIBS"
LIBS="$LTHREAD_LIBS $LIBS"
if test $ol_with_odbc = auto ; then
ol_with_odbc="iodbc unixodbc odbc32"
fi
for odbc in $ol_with_odbc ; do
if test $ol_link_sql = no ; then
case $odbc in
iodbc)
AC_CHECK_LIB(iodbc, SQLDriverConnect, [have_iodbc=yes], [have_iodbc=no])
if test $have_iodbc = yes ; then
ol_link_sql="-liodbc"
fi
;;
unixodbc)
AC_CHECK_LIB(odbc, SQLDriverConnect, [have_odbc=yes], [have_odbc=no])
if test $have_odbc = yes ; then
ol_link_sql="-lodbc"
fi
;;
odbc32)
AC_CHECK_LIB(odbc32, SQLDriverConnect, [have_odbc32=yes], [have_odbc32=no])
dnl The windows API uses __stdcall which cannot be detected by AC_CHECK_LIB
if test $have_odbc32 = no ; then
AC_MSG_CHECKING([for SQLDriverConnect in -lodbc32 with windows.h])
save_LIBS="$LIBS"
LIBS="$LIBS -lodbc32"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <windows.h>
#include <sqlext.h>
]], [[
SQLDriverConnect(NULL,NULL,NULL,0,NULL,0,NULL,0);
]])],[have_odbc32=yes], [have_odbc32=no])
LIBS="$save_LIBS"
AC_MSG_RESULT($have_odbc32)
fi
if test $have_odbc32 = yes ; then
ol_link_sql="-lodbc32"
fi
;;
*)
AC_MSG_ERROR([unknown ODBC library])
;;
esac
fi
done
LIBS="$sql_LIBS"
if test $ol_link_sql != no ; then
SLAPD_SQL_LIBS="$ol_link_sql"
elif test $ol_enable_sql != auto ; then
AC_MSG_ERROR([could not locate suitable ODBC library])
fi
fi
dnl ----------------------------------------------------------------
dnl WiredTiger
ol_link_wt=no
@ -2561,9 +2484,6 @@ fi
if test "$ol_link_perl" = no ; then
ol_enable_perl=no
fi
if test "$ol_link_sql" = no ; then
ol_enable_sql=no
fi
if test "$ol_link_wt" = no ; then
ol_enable_wt=no
fi
@ -2830,10 +2750,6 @@ AC_SUBST(ARGON2_LIBS)
AC_SUBST(SLAPD_SLP_LIBS)
AC_SUBST(SLAPD_GMP_LIBS)
AC_SUBST(SLAPD_SQL_LDFLAGS)
AC_SUBST(SLAPD_SQL_LIBS)
AC_SUBST(SLAPD_SQL_INCLUDES)
AC_SUBST(WT_CFLAGS)
AC_SUBST(WT_LIBS)
@ -2878,7 +2794,6 @@ AC_CONFIG_FILES([Makefile:build/top.mk:Makefile.in:build/dir.mk]
[servers/slapd/back-perl/Makefile:build/top.mk:servers/slapd/modules.mk:servers/slapd/back-perl/Makefile.in:build/mod.mk]
[servers/slapd/back-relay/Makefile:build/top.mk:servers/slapd/modules.mk:servers/slapd/back-relay/Makefile.in:build/mod.mk]
[servers/slapd/back-sock/Makefile:build/top.mk:servers/slapd/modules.mk:servers/slapd/back-sock/Makefile.in:build/mod.mk]
[servers/slapd/back-sql/Makefile:build/top.mk:servers/slapd/modules.mk:servers/slapd/back-sql/Makefile.in:build/mod.mk]
[servers/slapd/back-wt/Makefile:build/top.mk:servers/slapd/modules.mk:servers/slapd/back-wt/Makefile.in:build/mod.mk]
[servers/slapd/slapi/Makefile:build/top.mk:servers/slapd/slapi/Makefile.in:build/lib.mk:build/lib-shared.mk]
[servers/slapd/overlays/Makefile:build/top.mk:servers/slapd/overlays/Makefile.in:build/lib.mk]

View file

@ -168,7 +168,6 @@ reqAttr
dynlist
args
hardcoded
pgsql
argv
kdz
notAllowedOnRDN
@ -361,7 +360,6 @@ matchedDN
ufn
allusersgroup
FIXME
sql
uid
crit
objectClassViolation
@ -757,7 +755,6 @@ schemas
pwdPolicySubentry
pwdPolicySubEntry
reqId
backsql
scanf
olcBackend
TLSCACertificatePath
@ -992,7 +989,6 @@ searchFilter
wholeSubtree
SASLprep
nisMailAlias
libodbcpsqlS
OxObjects
attributeDescription
groupnummer
@ -1459,7 +1455,6 @@ LDAPSync
bitstring
objclass
oplist
libodbcpsql
LDAPObjectClass
sockurl
somevalue

View file

@ -440,117 +440,3 @@ LATER
H3: Further Information
{{slapd-relay}}(5)
H2: SQL
H3: Overview
The primary purpose of this {{slapd}}(8) backend is to PRESENT information
stored in some RDBMS as an LDAP subtree without any programming (some SQL and
maybe stored procedures can't be considered programming, anyway ;).
That is, for example, when you (some ISP) have account information you use in
an RDBMS, and want to use modern solutions that expect such information in LDAP
(to authenticate users, make email lookups etc.). Or you want to synchronize or
distribute information between different sites/applications that use RDBMSes
and/or LDAP. Or whatever else...
It is {{B:NOT}} designed as a general-purpose backend that uses RDBMS instead of
LMDB (as the standard back-mdb backend does), though it can be used as such with
several limitations. Please see {{SECT: LDAP vs RDBMS}} for discussion.
The idea is to use some meta-information to translate LDAP queries to SQL queries,
leaving relational schema untouched, so that old applications can continue using
it without any modifications. This allows SQL and LDAP applications to interoperate
without replication, and exchange data as needed.
The SQL backend is designed to be tunable to virtually any relational schema without
having to change source (through that meta-information mentioned). Also, it uses
ODBC to connect to RDBMSes, and is highly configurable for SQL dialects RDBMSes
may use, so it may be used for integration and distribution of data on different
RDBMSes, OSes, hosts etc., in other words, in highly heterogeneous environments.
This backend is experimental and deprecated.
H3: back-sql Configuration
This backend has to be one of the most abused and complex backends there is.
Therefore, we will go through a simple, small example that comes with the
OpenLDAP source and can be found in {{F: servers/slapd/back-sql/rdbms_depend/README}}
For this example we will be using PostgreSQL.
First, we add to {{F: /etc/odbc.ini}} 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 =
The relevant information for our test setup is highlighted with '<===' on the
right above.
Next, we add to {{F: /etc/odbcinst.ini}} a block of the form:
> [PostgreSQL]
> Description = ODBC for PostgreSQL
> Driver = /usr/lib/libodbcpsql.so
> Setup = /usr/lib/libodbcpsqlS.so
> FileUsage = 1
We will presume you know how to create a database and user in PostgreSQL and
how to set a password. Also, we'll presume you can populate the 'example'
database you've just created with the following files, as found in {{F: servers/slapd/back-sql/rdbms_depend/pgsql }}
> backsql_create.sql, testdb_create.sql, testdb_data.sql, testdb_metadata.sql
Lastly, run the test:
> [root@localhost]# cd $SOURCES/tests
> [root@localhost]# SLAPD_USE_SQL=pgsql ./run sql-test000
Briefly, you should see something like (cut short for space):
> Cleaning up test run directory leftover from previous run.
> Running ./scripts/sql-test000-read...
> running defines.sh
> Starting slapd on TCP/IP port 9011...
> Testing SQL backend read operations...
> Waiting 5 seconds for slapd to start...
> Testing correct bind... dn:cn=Mitya Kovalev,dc=example,dc=com
> Testing incorrect bind (should fail)... ldap_bind: Invalid credentials (49)
>
> ......
>
> Filtering original ldif...
> Comparing filter output...
> >>>>> Test succeeded
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.
Using {{F: sql-test000}}, files in {{F: servers/slapd/back-sql/rdbms_depend/pgsql/}}
and the man page, you should be set.
Note: This backend is experimental and deprecated.
H3: Further Information
{{slapd-sql}}(5) and {{F: servers/slapd/back-sql/rdbms_depend/README}}

View file

@ -347,19 +347,6 @@ really have a "directory".
Existing commercial LDAP server implementations that use a relational database
are either from the first kind or the third. I don't know of any implementation
that uses a relational database to do inefficiently what LMDB does efficiently.
For those who are interested in "third way" (exposing EXISTING data from RDBMS
as LDAP tree, having some limitations compared to classic LDAP model, but making
it possible to interoperate between LDAP and SQL applications):
OpenLDAP includes back-sql - the backend that makes it possible. It uses ODBC +
additional metainformation about translating LDAP queries to SQL queries in your
RDBMS schema, providing different levels of access - from read-only to full
access depending on RDBMS you use, and your schema.
For more information on concept and limitations, see {{slapd-sql}}(5) man page,
or the {{SECT: Backends}} section. There are also several examples for several
RDBMSes in {{F:back-sql/rdbms_depend/*}} subdirectories.
H2: What is slapd and what can it do?
@ -420,8 +407,7 @@ database operations. Because these two pieces communicate via a
well-defined {{TERM:C}} {{TERM:API}}, you can write your own
customized modules which extend {{slapd}} in numerous ways. Also,
a number of {{programmable database}} modules are provided. These
allow you to expose external data sources to {{slapd}} using popular
programming languages ({{PRD:Perl}}, and {{TERM:SQL}}).
allow you to expose external data sources to {{slapd}}.
{{B:Threads}}: {{slapd}} is threaded for high performance. A single
multi-threaded {{slapd}} process handles all incoming requests using

View file

@ -374,7 +374,6 @@ passwd Provides read-only access to {{passwd}}(5)
perl Perl Programmable backend
relay Relay backend
sock Socket backend
sql SQL Programmable backend
wt WiredTiger backend
!endblock

View file

@ -274,7 +274,6 @@ passwd Provides read-only access to {{passwd}}(5)
perl Perl Programmable backend
relay Relay backend
sock Socket backend
sql SQL Programmable backend
wt WiredTiger backend
!endblock

View file

@ -1246,7 +1246,6 @@ should be one of
.BR perl ,
.BR relay ,
.BR sock ,
.BR sql ,
or
.BR wt .
At present, only back-mdb implements any options of this type, so this

View file

@ -1,699 +0,0 @@
.TH SLAPD-SQL 5 "RELEASEDATE" "OpenLDAP LDVERSION"
.\" $OpenLDAP$
.SH NAME
slapd\-sql \- SQL backend to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
The primary purpose of this
.BR slapd (8)
backend is to PRESENT information stored in some RDBMS as an LDAP subtree
without any programming (some SQL and maybe stored procedures can't be
considered programming, anyway ;).
.LP
That is, for example, when you (some ISP) have account information you
use in an RDBMS, and want to use modern solutions that expect such
information in LDAP (to authenticate users, make email lookups etc.).
Or you want to synchronize or distribute information between different
sites/applications that use RDBMSes and/or LDAP.
Or whatever else...
.LP
It is NOT designed as a general-purpose backend that uses RDBMS instead
of LMDB (as the standard MDB backend does), though it can be
used as such with several limitations.
You can take a look at
.B http://www.openldap.org/faq/index.cgi?file=378
(OpenLDAP FAQ\-O\-Matic/General LDAP FAQ/Directories vs. conventional
databases) to find out more on this point.
.LP
The idea (detailed below) is to use some meta-information to translate
LDAP queries to SQL queries, leaving relational schema untouched, so
that old applications can continue using it without any
modifications.
This allows SQL and LDAP applications to inter-operate without
replication, and exchange data as needed.
.LP
The SQL backend is designed to be tunable to virtually any relational
schema without having to change source (through that meta-information
mentioned).
Also, it uses ODBC to connect to RDBMSes, and is highly configurable
for SQL dialects RDBMSes may use, so it may be used for integration
and distribution of data on different RDBMSes, OSes, hosts etc., in
other words, in highly heterogeneous environment.
.LP
This backend is \fIexperimental\fP.
.SH CONFIGURATION
These
.B slapd.conf
options apply to the SQL backend database, which means that
they must follow a "database sql" line and come before any
subsequent "backend" or "database" lines.
Other database options not specific to this backend are described
in the
.BR slapd.conf (5)
manual page.
.SH DATA SOURCE CONFIGURATION
.TP
.B dbname <datasource name>
The name of the ODBC datasource to use.
.LP
.B dbhost <hostname>
.br
.B dbpasswd <password>
.br
.B dbuser <username>
.RS
The three above options are generally unneeded, because this information
is taken from the datasource specified by the
.B dbname
directive.
They allow to override datasource settings.
Also, several RDBMS' drivers tend to require explicit passing of user/password,
even if those are given in datasource (Note:
.B dbhost
is currently ignored).
.RE
.SH SCOPING CONFIGURATION
These options specify SQL query templates for scoping searches.
.TP
.B subtree_cond <SQL expression>
Specifies a where-clause template used to form a subtree search condition
(dn="(.+,)?<dn>$").
It may differ from one SQL dialect to another (see samples).
By default, it is constructed based on the knowledge about
how to normalize DN values (e.g.
\fB"<upper_func>(ldap_entries.dn) LIKE CONCAT('%',?)"\fP);
see \fBupper_func\fP, \fBupper_needs_cast\fP, \fBconcat_pattern\fP
and \fBstrcast_func\fP in "HELPER CONFIGURATION" for details.
.TP
.B children_cond <SQL expression>
Specifies a where-clause template used to form a children search condition
(dn=".+,<dn>$").
It may differ from one SQL dialect to another (see samples).
By default, it is constructed based on the knowledge about
how to normalize DN values (e.g.
\fB"<upper_func>(ldap_entries.dn) LIKE CONCAT('%,',?)"\fP);
see \fBupper_func\fP, \fBupper_needs_cast\fP, \fBconcat_pattern\fP
and \fBstrcast_func\fP in "HELPER CONFIGURATION" for details.
.TP
.B use_subtree_shortcut { YES | no }
Do not use the subtree condition when the searchBase is the database
suffix, and the scope is subtree; rather collect all entries.
.RE
.SH STATEMENT CONFIGURATION
These options specify SQL query templates for loading schema mapping
meta-information, adding and deleting entries to ldap_entries, etc.
All these and subtree_cond should have the given default values.
For the current value it is recommended to look at the sources,
or in the log output when slapd starts with "\-d 5" or greater.
Note that the parameter number and order must not be changed.
.TP
.B oc_query <SQL expression>
The query that is used to collect the objectClass mapping data
from table \fIldap_oc_mappings\fP; see "METAINFORMATION USED" for details.
The default is
\fB"SELECT id, name, keytbl, keycol, create_proc, delete_proc, expect_return
FROM ldap_oc_mappings"\fP.
.TP
.B at_query <SQL expression>
The query that is used to collect the attributeType mapping data
from table \fIldap_attr_mappings\fP; see "METAINFORMATION USED" for details.
The default is
\fB"SELECT name, sel_expr, from_tbls, join_where, add_proc, delete_proc,
param_order, expect_return FROM ldap_attr_mappings WHERE oc_map_id=?"\fP.
.TP
.B id_query <SQL expression>
The query that is used to map a DN to an entry
in table \fIldap_entries\fP; see "METAINFORMATION USED" for details.
The default is
\fB"SELECT id,keyval,oc_map_id,dn FROM ldap_entries WHERE <DN match expr>"\fP,
where \fB<DN match expr>\fP is constructed based on the knowledge about
how to normalize DN values (e.g. \fB"dn=?"\fP if no means to uppercase
strings are available; typically, \fB"<upper_func>(dn)=?"\fP is used);
see \fBupper_func\fP, \fBupper_needs_cast\fP, \fBconcat_pattern\fP
and \fBstrcast_func\fP in "HELPER CONFIGURATION" for details.
.TP
.B insentry_stmt <SQL expression>
The statement that is used to insert a new entry
in table \fIldap_entries\fP; see "METAINFORMATION USED" for details.
The default is
\fB"INSERT INTO ldap_entries (dn, oc_map_id, parent, keyval) VALUES
(?, ?, ?, ?)"\fP.
.TP
.B delentry_stmt <SQL expression>
The statement that is used to delete an existing entry
from table \fIldap_entries\fP; see "METAINFORMATION USED" for details.
The default is
\fB"DELETE FROM ldap_entries WHERE id=?"\fP.
.TP
.B delobjclasses_stmt <SQL expression>
The statement that is used to delete an existing entry's ID
from table \fIldap_objclasses\fP; see "METAINFORMATION USED" for details.
The default is
\fB"DELETE FROM ldap_entry_objclasses WHERE entry_id=?"\fP.
.RE
.SH HELPER CONFIGURATION
These statements are used to modify the default behavior of the backend
according to issues of the dialect of the RDBMS.
The first options essentially refer to string and DN normalization
when building filters.
LDAP normalization is more than upper- (or lower-)casing everything;
however, as a reasonable trade-off, for case-sensitive RDBMSes the backend
can be instructed to uppercase strings and DNs by providing
the \fBupper_func\fP directive.
Some RDBMSes, to use functions on arbitrary data types, e.g. string
constants, requires a cast, which is triggered
by the \fBupper_needs_cast\fP directive.
If required, a string cast function can be provided as well,
by using the \fBstrcast_func\fP directive.
Finally, a custom string concatenation pattern may be required;
it is provided by the \fBconcat_pattern\fP directive.
.TP
.B upper_func <SQL function name>
Specifies the name of a function that converts a given value to uppercase.
This is used for case insensitive matching when the RDBMS is case sensitive.
It may differ from one SQL dialect to another (e.g. \fBUCASE\fP, \fBUPPER\fP
or whatever; see samples). By default, none is used, i.e. strings are not
uppercased, so matches may be case sensitive.
.TP
.B upper_needs_cast { NO | yes }
Set this directive to
.B yes
if
.B upper_func
needs an explicit cast when applied to literal strings.
A cast in the form
.B CAST (<arg> AS VARCHAR(<max DN length>))
is used, where
.B <max DN length>
is builtin in back-sql; see macro
.B BACKSQL_MAX_DN_LEN
(currently 255; note that slapd's builtin limit, in macro
.BR SLAP_LDAPDN_MAXLEN ,
is set to 8192).
This is \fIexperimental\fP and may change in future releases.
.TP
.B strcast_func <SQL function name>
Specifies the name of a function that converts a given value to a string
for appropriate ordering. This is used in "SELECT DISTINCT" statements
for strongly typed RDBMSes with little implicit casting (like PostgreSQL),
when a literal string is specified.
This is \fIexperimental\fP and may change in future releases.
.TP
.B concat_pattern <pattern>
This statement defines the
.B pattern
that is used to concatenate strings. The
.B pattern
MUST contain two question marks, '?', that will be replaced
by the two strings that must be concatenated. The default value is
.BR "CONCAT(?,?)";
a form that is known to be highly portable (IBM db2, PostgreSQL) is
.BR "?||?",
but an explicit cast may be required when operating on literal strings:
.BR "CAST(?||? AS VARCHAR(<length>))".
On some RDBMSes (IBM db2, MSSQL) the form
.B "?+?"
is known to work as well.
Carefully check the documentation of your RDBMS or stay with the examples
for supported ones.
This is \fIexperimental\fP and may change in future releases.
.TP
.B aliasing_keyword <string>
Define the aliasing keyword. Some RDBMSes use the word "\fIAS\fP"
(the default), others don't use any.
.TP
.B aliasing_quote <string>
Define the quoting char of the aliasing keyword. Some RDBMSes
don't require any (the default), others may require single
or double quotes.
.TP
.B has_ldapinfo_dn_ru { NO | yes }
Explicitly inform the backend whether the dn_ru column
(DN in reverse uppercased form) is present in table \fIldap_entries\fP.
Overrides automatic check (this is required, for instance,
by PostgreSQL/unixODBC).
This is \fIexperimental\fP and may change in future releases.
.TP
.B fail_if_no_mapping { NO | yes }
When set to
.B yes
it forces \fIattribute\fP write operations to fail if no appropriate
mapping between LDAP attributes and SQL data is available.
The default behavior is to ignore those changes that cannot be mapped.
It has no impact on objectClass mapping, i.e. if the
.I structuralObjectClass
of an entry cannot be mapped to SQL by looking up its name
in ldap_oc_mappings, an
.I add
operation will fail regardless of the
.B fail_if_no_mapping
switch; see section "METAINFORMATION USED" for details.
This is \fIexperimental\fP and may change in future releases.
.TP
.B allow_orphans { NO | yes }
When set to
.B yes
orphaned entries (i.e. without the parent entry in the database)
can be added. This option should be used with care, possibly
in conjunction with some special rule on the RDBMS side that
dynamically creates the missing parent.
.TP
.B baseObject [ <filename> ]
Instructs the database to create and manage an in-memory baseObject
entry instead of looking for one in the RDBMS.
If the (optional)
.B <filename>
argument is given, the entry is read from that file in
.BR LDIF (5)
format; otherwise, an entry with objectClass \fBextensibleObject\fP
is created based on the contents of the RDN of the \fIbaseObject\fP.
This is particularly useful when \fIldap_entries\fP
information is stored in a view rather than in a table, and
.B union
is not supported for views, so that the view can only specify
one rule to compute the entry structure for one objectClass.
This topic is discussed further in section "METAINFORMATION USED".
This is \fIexperimental\fP and may change in future releases.
.TP
.B create_needs_select { NO | yes }
Instructs the database whether or not entry creation
in table \fIldap_entries\fP needs a subsequent select to collect
the automatically assigned ID, instead of being returned
by a stored procedure.
.LP
.B fetch_attrs <attrlist>
.br
.B fetch_all_attrs { NO | yes }
.RS
The first statement allows one to provide a list of attributes that
must always be fetched in addition to those requested by any specific
operation, because they are required for the proper usage of the
backend. For instance, all attributes used in ACLs should be listed
here. The second statement is a shortcut to require all attributes
to be always loaded. Note that the dynamically generated attributes,
e.g. \fIhasSubordinates\fP, \fIentryDN\fP and other implementation
dependent attributes are \fBNOT\fP generated at this point, for
consistency with the rest of slapd. This may change in the future.
.RE
.TP
.B check_schema { YES | no }
Instructs the database to check schema adherence of entries after
modifications, and structural objectClass chain when entries are built.
By default it is set to
.BR yes .
.TP
.B sqllayer <name> [...]
Loads the layer \fB<name>\fP onto a stack of helpers that are used
to map DNs from LDAP to SQL representation and vice-versa.
Subsequent args are passed to the layer configuration routine.
This is \fIhighly experimental\fP and should be used with extreme care.
The API of the layers is not frozen yet, so it is unpublished.
.TP
.B autocommit { NO | yes }
Activates autocommit; by default, it is off.
.SH METAINFORMATION USED
.LP
Almost everything mentioned later is illustrated in examples located
in the
.B servers/slapd/back\-sql/rdbms_depend/
directory in the OpenLDAP source tree, and contains scripts for
generating sample database for Oracle, MS SQL Server, mySQL and more
(including PostgreSQL and IBM db2).
.LP
The first thing that one must arrange is what set of LDAP
object classes can present your RDBMS information.
.LP
The easiest way is to create an objectClass for each entity you had in
ER-diagram when designing your relational schema.
Any relational schema, no matter how normalized it is, was designed
after some model of your application's domain (for instance, accounts,
services etc. in ISP), and is used in terms of its entities, not just
tables of normalized schema.
It means that for every attribute of every such instance there is an
effective SQL query that loads its values.
.LP
Also you might want your object classes to conform to some of the standard
schemas like inetOrgPerson etc.
.LP
Nevertheless, when you think it out, we must define a way to translate
LDAP operation requests to (a series of) SQL queries.
Let us deal with the SEARCH operation.
.LP
Example:
Let's suppose that we store information about persons working in our
organization in two tables:
.LP
.nf
PERSONS PHONES
---------- -------------
id integer id integer
first_name varchar pers_id integer references persons(id)
last_name varchar phone
middle_name varchar
...
.fi
.LP
(PHONES contains telephone numbers associated with persons).
A person can have several numbers, then PHONES contains several
records with corresponding pers_id, or no numbers (and no records in
PHONES with such pers_id).
An LDAP objectclass to present such information could look like this:
.LP
.nf
person
-------
MUST cn
MAY telephoneNumber $ firstName $ lastName
...
.fi
.LP
To fetch all values for cn attribute given person ID, we construct the
query:
.LP
.nf
SELECT CONCAT(persons.first_name,' ',persons.last_name)
AS cn FROM persons WHERE persons.id=?
.fi
.LP
for telephoneNumber we can use:
.LP
.nf
SELECT phones.phone AS telephoneNumber FROM persons,phones
WHERE persons.id=phones.pers_id AND persons.id=?
.fi
.LP
If we wanted to service LDAP requests with filters like
(telephoneNumber=123*), we would construct something like:
.LP
.nf
SELECT ... FROM persons,phones
WHERE persons.id=phones.pers_id
AND persons.id=?
AND phones.phone like '%1%2%3%'
.fi
.LP
(note how the telephoneNumber match is expanded in multiple wildcards
to account for interspersed ininfluential chars like spaces, dashes
and so; this occurs by design because telephoneNumber is defined after
a specially recognized syntax).
So, if we had information about what tables contain values for each
attribute, how to join these tables and arrange these values, we could
try to automatically generate such statements, and translate search
filters to SQL WHERE clauses.
.LP
To store such information, we add three more tables to our schema
and fill it with data (see samples):
.LP
.nf
ldap_oc_mappings (some columns are not listed for clarity)
---------------
id=1
name="person"
keytbl="persons"
keycol="id"
.fi
.LP
This table defines a mapping between objectclass (its name held in the
"name" column), and a table that holds the primary key for corresponding
entities.
For instance, in our example, the person entity, which we are trying
to present as "person" objectclass, resides in two tables (persons and
phones), and is identified by the persons.id column (that we will call
the primary key for this entity).
Keytbl and keycol thus contain "persons" (name of the table), and "id"
(name of the column).
.LP
.nf
ldap_attr_mappings (some columns are not listed for clarity)
-----------
id=1
oc_map_id=1
name="cn"
sel_expr="CONCAT(persons.first_name,' ',persons.last_name)"
from_tbls="persons"
join_where=NULL
************
id=<n>
oc_map_id=1
name="telephoneNumber"
sel_expr="phones.phone"
from_tbls="persons,phones"
join_where="phones.pers_id=persons.id"
.fi
.LP
This table defines mappings between LDAP attributes and SQL queries
that load their values.
Note that, unlike LDAP schema, these are not
.B attribute types
- the attribute "cn" for "person" objectclass can
have its values in different tables than "cn" for some other objectclass,
so attribute mappings depend on objectclass mappings (unlike attribute
types in LDAP schema, which are indifferent to objectclasses).
Thus, we have oc_map_id column with link to oc_mappings table.
.LP
Now we cut the SQL query that loads values for a given attribute into 3 parts.
First goes into sel_expr column - this is the expression we had
between SELECT and FROM keywords, which defines WHAT to load.
Next is table list - text between FROM and WHERE keywords.
It may contain aliases for convenience (see examples).
The last is part of the where clause, which (if it exists at all) expresses the
condition for joining the table containing values with the table
containing the primary key (foreign key equality and such).
If values are in the same table as the primary key, then this column is
left NULL (as for cn attribute above).
.LP
Having this information in parts, we are able to not only construct
queries that load attribute values by id of entry (for this we could
store SQL query as a whole), but to construct queries that load id's
of objects that correspond to a given search filter (or at least part of
it).
See below for examples.
.LP
.nf
ldap_entries
------------
id=1
dn=<dn you choose>
oc_map_id=...
parent=<parent record id>
keyval=<value of primary key>
.fi
.LP
This table defines mappings between DNs of entries in your LDAP tree,
and values of primary keys for corresponding relational data.
It has recursive structure (parent column references id column of the
same table), which allows you to add any tree structure(s) to your
flat relational data.
Having id of objectclass mapping, we can determine table and column
for primary key, and keyval stores value of it, thus defining the exact
tuple corresponding to the LDAP entry with this DN.
.LP
Note that such design (see exact SQL table creation query) implies one
important constraint - the key must be an integer.
But all that I know about well-designed schemas makes me think that it's
not very narrow ;) If anyone needs support for different types for
keys - he may want to write a patch, and submit it to OpenLDAP ITS,
then I'll include it.
.LP
Also, several users complained that they don't really need very
structured trees, and they don't want to update one more table every
time they add or delete an instance in the relational schema.
Those people can use a view instead of a real table for ldap_entries, something
like this (by Robin Elfrink):
.LP
.nf
CREATE VIEW ldap_entries (id, dn, oc_map_id, parent, keyval)
AS
SELECT 0, UPPER('o=MyCompany,c=NL'),
3, 0, 'baseObject' FROM unixusers WHERE userid='root'
UNION
SELECT (1000000000+userid),
UPPER(CONCAT(CONCAT('cn=',gecos),',o=MyCompany,c=NL')),
1, 0, userid FROM unixusers
UNION
SELECT (2000000000+groupnummer),
UPPER(CONCAT(CONCAT('cn=',groupname),',o=MyCompany,c=NL')),
2, 0, groupnummer FROM groups;
.fi
.LP
If your RDBMS does not support
.B unions
in views, only one objectClass can be mapped in
.BR ldap_entries ,
and the baseObject cannot be created; in this case, see the
.B baseObject
directive for a possible workaround.
.LP
.SH TYPICAL SQL BACKEND OPERATION
Having meta-information loaded, the SQL backend uses these tables to
determine a set of primary keys of candidates (depending on search
scope and filter).
It tries to do it for each objectclass registered in ldap_objclasses.
.LP
Example:
for our query with filter (telephoneNumber=123*) we would get the following
query generated (which loads candidate IDs)
.LP
.nf
SELECT ldap_entries.id,persons.id, 'person' AS objectClass,
ldap_entries.dn AS dn
FROM ldap_entries,persons,phones
WHERE persons.id=ldap_entries.keyval
AND ldap_entries.objclass=?
AND ldap_entries.parent=?
AND phones.pers_id=persons.id
AND (phones.phone LIKE '%1%2%3%')
.fi
.LP
(for ONELEVEL search)
or "... AND dn=?" (for BASE search)
or "... AND dn LIKE '%?'" (for SUBTREE)
.LP
Then, for each candidate, we load the requested attributes using
per-attribute queries like
.LP
.nf
SELECT phones.phone AS telephoneNumber
FROM persons,phones
WHERE persons.id=? AND phones.pers_id=persons.id
.fi
.LP
Then, we use test_filter() from the frontend API to test the entry for a full
LDAP search filter match (since we cannot effectively make sense of
SYNTAX of corresponding LDAP schema attribute, we translate the filter
into the most relaxed SQL condition to filter candidates), and send it to
the user.
.LP
ADD, DELETE, MODIFY and MODRDN operations are also performed on per-attribute
meta-information (add_proc etc.).
In those fields one can specify an SQL statement or stored procedure
call which can add, or delete given values of a given attribute, using
the given entry keyval (see examples -- mostly PostgreSQL, ORACLE and MSSQL
- since as of this writing there are no stored procs in MySQL).
.LP
We just add more columns to ldap_oc_mappings and ldap_attr_mappings, holding
statements to execute (like create_proc, add_proc, del_proc etc.), and
flags governing the order of parameters passed to those statements.
Please see samples to find out what are the parameters passed, and other
information on this matter - they are self-explanatory for those familiar
with the concepts expressed above.
.LP
.SH COMMON TECHNIQUES
First of all, let's recall that among other major differences to the
complete LDAP data model, the above illustrated concept does not directly
support such features as multiple objectclasses per entry, and referrals.
Fortunately, they are easy to adopt in this scheme.
The SQL backend requires that one more table is added to the schema:
ldap_entry_objectclasses(entry_id,oc_name).
.LP
That table contains any number of objectclass names that corresponding
entries will possess, in addition to that mentioned in mapping.
The SQL backend automatically adds attribute mapping for the "objectclass"
attribute to each objectclass mapping that loads values from this table.
So, you may, for instance, have a mapping for inetOrgPerson, and use it
for queries for "person" objectclass...
.LP
Referrals used to be implemented in a loose manner by adding an extra
table that allowed any entry to host a "ref" attribute, along with
a "referral" extra objectClass in table ldap_entry_objclasses.
In the current implementation, referrals are treated like any other
user-defined schema, since "referral" is a structural objectclass.
The suggested practice is to define a "referral" entry in ldap_oc_mappings,
holding a naming attribute, e.g. "ou" or "cn", a "ref" attribute,
containing the url; in case multiple referrals per entry are needed,
a separate table for urls can be created, where urls are mapped
to the respective entries.
The use of the naming attribute usually requires to add
an "extensibleObject" value to ldap_entry_objclasses.
.LP
.SH CAVEATS
As previously stated, this backend should not be considered
a replacement of other data storage backends, but rather a gateway
to existing RDBMS storages that need to be published in LDAP form.
.LP
The \fBhasSubordinates\fP operational attribute is honored by back-sql
in search results and in compare operations; it is partially honored
also in filtering. Owing to design limitations, a (brain-dead?) filter
of the form
\fB(!(hasSubordinates=TRUE))\fP
will give no results instead of returning all the leaf entries, because
it actually expands into \fB... AND NOT (1=1)\fP.
If you need to find all the leaf entries, please use
\fB(hasSubordinates=FALSE)\fP
instead.
.LP
A directoryString value of the form "__First___Last_"
(where underscores mean spaces, ASCII 0x20 char) corresponds
to its prettified counterpart "First_Last"; this is not currently
honored by back-sql if non-prettified data is written via RDBMS;
when non-prettified data is written through back-sql, the prettified
values are actually used instead.
.LP
.SH BUGS
When the
.B ldap_entry_objclasses
table is empty, filters on the
.B objectClass
attribute erroneously result in no candidates.
A workaround consists in adding at least one row to that table,
no matter if valid or not.
.LP
.SH PROXY CACHE OVERLAY
The proxy cache overlay
allows caching of LDAP search requests (queries) in a local database.
See
.BR slapo\-pcache (5)
for details.
.SH EXAMPLES
There are example SQL modules in the slapd/back\-sql/rdbms_depend/
directory in the OpenLDAP source tree.
.SH ACCESS CONTROL
The
.B sql
backend honors access control semantics as indicated in
.BR slapd.access (5)
(including the
.B disclose
access privilege when enabled at compile time).
.SH FILES
.TP
ETCDIR/slapd.conf
default slapd configuration file
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd (8).

View file

@ -1141,10 +1141,8 @@ and for the discovery phase of the search operation,
full ACL semantics is only supported by the primary backends, i.e.
.BR slapd\-mdb (5).
Some other backend, like
.BR slapd\-sql (5),
may fully support them; others may only support a portion of the
described semantics, or even differ in some aspects.
Some other backends may fully support them; others may only support a
portion of the described semantics, or even differ in some aspects.
The relevant details are described in the backend-specific man pages.
.SH CAVEATS

View file

@ -95,10 +95,6 @@ for details) to rewrite the naming context of the request.
It is primarily intended to implement virtual views on databases
that actually store data.
.TP
.B sql
This backend is experimental and deprecated.
It services LDAP requests from an SQL database.
.TP
.B wiredtiger
This backend is experimental.
It services LDAP requests from a wiredtiger database.
@ -123,7 +119,6 @@ default slapd configuration directory
.BR slapd\-passwd (5),
.BR slapd\-perl (5),
.BR slapd\-relay (5),
.BR slapd\-sql (5),
.BR slapd\-wt (5),
.BR slapd.conf (5),
.BR slapd.overlays (5),

View file

@ -1323,7 +1323,6 @@ should be one of
.BR perl ,
.BR relay ,
.BR sock ,
.BR sql ,
or
.BR wt .
At present, only back-mdb implements any options of this type, so this
@ -1354,7 +1353,6 @@ should be one of
.BR perl ,
.BR relay ,
.BR sock ,
.BR sql ,
or
.BR wt ,
depending on which backend will serve the database.

View file

@ -45,10 +45,9 @@ cache:
This directive adds the proxy cache overlay to the current backend. The
proxy cache overlay may be used with any backend but is intended for use
with the
.BR ldap ,
.BR meta ,
.BR ldap
and
.BR sql
.BR meta
backends. Please note that the underlying backend must have a configured
.BR rootdn.
.TP
@ -323,7 +322,6 @@ default slapd configuration file
.BR slapd\-config (5),
.BR slapd\-ldap (5),
.BR slapd\-meta (5),
.BR slapd\-sql (5),
.BR slapd (8).
.SH AUTHOR
Originally implemented by Apurva Kumar as an extension to back-meta;

View file

@ -538,12 +538,6 @@
/* if you have spawnlp() */
#undef HAVE_SPAWNLP
/* Define to 1 if you have the <sqlext.h> header file. */
#undef HAVE_SQLEXT_H
/* Define to 1 if you have the <sql.h> header file. */
#undef HAVE_SQL_H
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H

View file

@ -1,45 +0,0 @@
# Makefile.in for back-sql
# $OpenLDAP$
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
##
## Copyright 1998-2026 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted only as authorized by the OpenLDAP
## Public License.
##
## A copy of this license is available in the file LICENSE in the
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
SRCS = init.c config.c search.c bind.c compare.c operational.c \
entry-id.c schema-map.c sql-wrap.c modify.c util.c \
add.c delete.c modrdn.c api.c
OBJS = init.lo config.lo search.lo bind.lo compare.lo operational.lo \
entry-id.lo schema-map.lo sql-wrap.lo modify.lo util.lo \
add.lo delete.lo modrdn.lo api.lo
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries
BUILD_OPT = "--enable-sql"
BUILD_MOD = $(BUILD_SQL)
mod_DEFS = -DSLAPD_IMPORT
MOD_DEFS = $($(BUILD_MOD)_DEFS)
shared_LDAP_LIBS = $(LDAP_LIBLDAP_LA) $(LDAP_LIBLBER_LA)
NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS) $(SLAPD_SQL_LIBS)
LIBBASE = back_sql
XINCPATH = -I.. -I$(srcdir)/.. $(SLAPD_SQL_INCLUDES)
XDEFS = $(MODULES_CPPFLAGS)
all-local-lib: ../.backend
../.backend: lib$(LIBBASE).a
@touch $@

File diff suppressed because it is too large Load diff

View file

@ -1,211 +0,0 @@
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2004 Pierangelo Masarati.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati.
*/
#include "portable.h"
#include <stdio.h>
#include <sys/types.h>
#include "ac/string.h"
#include "slap.h"
#include "proto-sql.h"
static backsql_api *backsqlapi;
int
backsql_api_config( backsql_info *bi, const char *name, int argc, char *argv[] )
{
backsql_api *ba;
assert( bi != NULL );
assert( name != NULL );
for ( ba = backsqlapi; ba; ba = ba->ba_next ) {
if ( strcasecmp( name, ba->ba_name ) == 0 ) {
backsql_api *ba2;
ba2 = ch_malloc( sizeof( backsql_api ) );
*ba2 = *ba;
if ( ba2->ba_config ) {
if ( ( *ba2->ba_config )( ba2, argc, argv ) ) {
ch_free( ba2 );
return 1;
}
ba2->ba_argc = argc;
if ( argc ) {
int i;
ba2->ba_argv = ch_malloc( argc * sizeof(char *));
for ( i=0; i<argc; i++ )
ba2->ba_argv[i] = ch_strdup( argv[i] );
}
}
ba2->ba_next = bi->sql_api;
bi->sql_api = ba2;
return 0;
}
}
return 1;
}
int
backsql_api_destroy( backsql_info *bi )
{
backsql_api *ba;
assert( bi != NULL );
ba = bi->sql_api;
if ( ba == NULL ) {
return 0;
}
for ( ; ba; ba = ba->ba_next ) {
if ( ba->ba_destroy ) {
(void)( *ba->ba_destroy )( ba );
}
}
return 0;
}
int
backsql_api_register( backsql_api *ba )
{
backsql_api *ba2;
assert( ba != NULL );
assert( ba->ba_private == NULL );
if ( ba->ba_name == NULL ) {
fprintf( stderr, "API module has no name\n" );
exit(EXIT_FAILURE);
}
for ( ba2 = backsqlapi; ba2; ba2 = ba2->ba_next ) {
if ( strcasecmp( ba->ba_name, ba2->ba_name ) == 0 ) {
fprintf( stderr, "API module \"%s\" already defined\n", ba->ba_name );
exit( EXIT_FAILURE );
}
}
ba->ba_next = backsqlapi;
backsqlapi = ba;
return 0;
}
int
backsql_api_dn2odbc( Operation *op, SlapReply *rs, struct berval *dn )
{
backsql_info *bi = (backsql_info *)op->o_bd->be_private;
backsql_api *ba;
int rc;
struct berval bv;
ba = bi->sql_api;
if ( ba == NULL ) {
return 0;
}
ber_dupbv( &bv, dn );
for ( ; ba; ba = ba->ba_next ) {
if ( ba->ba_dn2odbc ) {
/*
* The dn2odbc() helper is supposed to rewrite
* the contents of bv, freeing the original value
* with ch_free() if required and replacing it
* with a newly allocated one using ch_malloc()
* or companion functions.
*
* NOTE: it is supposed to __always__ free
* the value of bv in case of error, and reset
* it with BER_BVZERO() .
*/
rc = ( *ba->ba_dn2odbc )( op, rs, &bv );
if ( rc ) {
/* in case of error, dn2odbc() must cleanup */
assert( BER_BVISNULL( &bv ) );
return rc;
}
}
}
assert( !BER_BVISNULL( &bv ) );
*dn = bv;
return 0;
}
int
backsql_api_odbc2dn( Operation *op, SlapReply *rs, struct berval *dn )
{
backsql_info *bi = (backsql_info *)op->o_bd->be_private;
backsql_api *ba;
int rc;
struct berval bv;
ba = bi->sql_api;
if ( ba == NULL ) {
return 0;
}
ber_dupbv( &bv, dn );
for ( ; ba; ba = ba->ba_next ) {
if ( ba->ba_dn2odbc ) {
rc = ( *ba->ba_odbc2dn )( op, rs, &bv );
/*
* The odbc2dn() helper is supposed to rewrite
* the contents of bv, freeing the original value
* with ch_free() if required and replacing it
* with a newly allocated one using ch_malloc()
* or companion functions.
*
* NOTE: it is supposed to __always__ free
* the value of bv in case of error, and reset
* it with BER_BVZERO() .
*/
if ( rc ) {
/* in case of error, odbc2dn() must cleanup */
assert( BER_BVISNULL( &bv ) );
return rc;
}
}
}
assert( !BER_BVISNULL( &bv ) );
*dn = bv;
return 0;
}

View file

@ -1,631 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Mararati.
* Portions Copyright 2004 Mark Adamson.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati and Mark Adamson.
*/
/*
* The following changes have been addressed:
*
* Enhancements:
* - re-styled code for better readability
* - upgraded backend API to reflect recent changes
* - LDAP schema is checked when loading SQL/LDAP mapping
* - AttributeDescription/ObjectClass pointers used for more efficient
* mapping lookup
* - bervals used where string length is required often
* - atomized write operations by committing at the end of each operation
* and defaulting connection closure to rollback
* - added LDAP access control to write operations
* - fully implemented modrdn (with rdn attrs change, deleteoldrdn,
* access check, parent/children check and more)
* - added parent access control, children control to delete operation
* - added structuralObjectClass operational attribute check and
* value return on search
* - added hasSubordinate operational attribute on demand
* - search limits are appropriately enforced
* - function backsql_strcat() has been made more efficient
* - concat function has been made configurable by means of a pattern
* - added config switches:
* - fail_if_no_mapping write operations fail if there is no mapping
* - has_ldapinfo_dn_ru overrides autodetect
* - concat_pattern a string containing two '?' is used
* (note that "?||?" should be more portable
* than builtin function "CONCAT(?,?)")
* - strcast_func cast of string constants in "SELECT DISTINCT
* statements (needed by PostgreSQL)
* - upper_needs_cast cast the argument of upper when required
* (basically when building dn substring queries)
* - added noop control
* - added values return filter control
* - hasSubordinate can be used in search filters (with limitations)
* - eliminated oc->name; use oc->oc->soc_cname instead
*
* Todo:
* - add security checks for SQL statements that can be injected (?)
* - re-test with previously supported RDBMs
* - replace dn_ru and so with normalized dn (no need for upper() and so
* in dn match)
* - implement a backsql_normalize() function to replace the upper()
* conversion routines
* - note that subtree deletion, subtree renaming and so could be easily
* implemented (rollback and consistency checks are available :)
* - implement "lastmod" and other operational stuff (ldap_entries table ?)
* - check how to allow multiple operations with one statement, to remove
* BACKSQL_REALLOC_STMT from modify.c (a more recent unixODBC lib?)
*/
/*
* Improvements submitted by (ITS#3432)
*
* 1. id_query.patch applied (with changes)
* 2. shortcut.patch applied (reworked)
* 3. create_hint.patch applied
* 4. count_query.patch applied (reworked)
* 5. returncodes.patch applied (with sanity checks)
* 6. connpool.patch under evaluation
* 7. modoc.patch under evaluation (requires
* manageDSAit and "manage"
* access privileges)
* 8. miscfixes.patch applied (reworked; other
* operations need to load the
* entire entry for ACL purposes;
* see ITS#3480, now fixed)
*
* original description:
Changes that were made to the SQL backend.
The patches were made against 2.2.18 and can be applied individually,
but would best be applied in the numerical order of the file names.
A synopsis of each patch is given here:
1. Added an option to set SQL query for the "id_query" operation.
2. Added an option to the SQL backend called "use_subtree_shortcut".
When a search is performed, the SQL query includes a WHERE clause
which says the DN must be "LIKE %<searchbase>". The LIKE operation
can be slow in an RDBM. This shortcut option says that if the
searchbase of the LDAP search is the root DN of the SQL backend,
and thus all objects will match the LIKE operator, do not include
the "LIKE %<searchbase>" clause in the SQL query (it is replaced
instead by the always true "1=1" clause to keep the "AND"'s
working correctly). This option is off by default, and should be
turned on only if all objects to be found in the RDBM are under the
same root DN. Multiple backends working within the same RDBM table
space would encounter problems. LDAP searches whose searchbase are
not at the root DN will bypass this shortcut and employ the LIKE
clause.
3. Added a "create_hint" column to ldap_oc_mappings table. Allows
taking the value of an attr named in "create_hint" and passing it to
the create_proc procedure. This is necessary for when an objectClass's
table is partition indexed by some indexing column and thus the value
in that indexing column cannot change after the row is created. The
value for the indexed column is passed into the create_proc, which
uses it to fill in the indexed column as the new row is created.
4. When loading the values of an attribute, the count(*) of the number
of values is fetched first and memory is allocated for the array of
values and normalized values. The old system of loading the values one
by one and running realloc() on the array of values and normalized
values each time was badly fragmenting memory. The array of values and
normalized values would be side by side in memory, and realloc()'ing
them over and over would force them to leapfrog each other through all
of available memory. Attrs with a large number of values could not be
loaded without crashing the slapd daemon.
5. Added code to interpret the value returned by stored procedures
which have expect_return set. Returned value is interpreted as an LDAP
return code. This allows the distinction between the SQL failing to
execute and the SQL running to completion and returning an error code
which can indicate a policy violation.
6. Added RDBM connection pooling. Once an operation is finished the
connection to the RDBM is returned to a pool rather than closing.
Allows the next operation to skip the initialization and authentication
phases of contacting the RDBM. Also, if licensing with ODBC places
a limit on the number of connections, an LDAP thread can block waiting
for another thread to finish, so that no LDAP errors are returned
for having more LDAP connections than allowed RDBM connections. An
RDBM connection which receives an SQL error is marked as "tainted"
so that it will be closed rather than returned to the pool.
Also, RDBM connections must be bound to a given LDAP connection AND
operation number, and NOT just the connection number. Asynchronous
LDAP clients can have multiple simultaneous LDAP operations which
should not share the same RDBM connection. A given LDAP operation can
even make multiple SQL operations (e.g. a BIND operation which
requires SASL to perform an LDAP search to convert the SASL ID to an
LDAP DN), so each RDBM connection now has a refcount that must reach
zero before the connection is returned to the free pool.
7. Added ability to change the objectClass of an object. Required
considerable work to copy all attributes out of old object and into
new object. Does a schema check before proceeding. Creates a new
object, fills it in, deletes the old object, then changes the
oc_map_id and keyval of the entry in the "ldap_entries" table.
8. Generic fixes. Includes initializing pointers before they
get used in error branch cases, pointer checks before dereferencing,
resetting a return code to success after a COMPARE op, sealing
memory leaks, and in search.c, changing some of the "1=1" tests to
"2=2", "3=3", etc so that when reading slapd trace output, the
location in the source code where the x=x test was added to the SQL
can be easily distinguished.
*/
#ifndef __BACKSQL_H__
#define __BACKSQL_H__
/* former sql-types.h */
#include <sql.h>
#include <sqlext.h>
typedef struct {
SWORD ncols;
BerVarray col_names;
UDWORD *col_prec;
SQLSMALLINT *col_type;
char **cols;
SQLLEN *value_len;
} BACKSQL_ROW_NTS;
/*
* Better use the standard length of 8192 (as of slap.h)?
*
* NOTE: must be consistent with definition in ldap_entries table
*/
/* #define BACKSQL_MAX_DN_LEN SLAP_LDAPDN_MAXLEN */
#define BACKSQL_MAX_DN_LEN 255
/*
* define to enable very extensive trace logging (debug only)
*/
#undef BACKSQL_TRACE
/*
* define if using MS SQL and workaround needed (see sql-wrap.c)
*/
#undef BACKSQL_MSSQL_WORKAROUND
/*
* define to enable values counting for attributes
*/
#define BACKSQL_COUNTQUERY
/*
* define to enable prettification/validation of values
*/
#define BACKSQL_PRETTY_VALIDATE
/*
* define to enable varchars as unique keys in user tables
*
* by default integers are used (and recommended)
* for performances. Integers are used anyway in back-sql
* related tables.
*/
#undef BACKSQL_ARBITRARY_KEY
/*
* type used for keys
*/
#if defined(HAVE_LONG_LONG) && defined(SQL_C_UBIGINT) && \
( defined(HAVE_STRTOULL) || defined(HAVE_STRTOUQ) )
typedef unsigned long long backsql_key_t;
#define BACKSQL_C_NUMID SQL_C_UBIGINT
#define BACKSQL_IDNUMFMT "%llu"
#define BACKSQL_STR2ID lutil_atoullx
#else /* ! HAVE_LONG_LONG || ! SQL_C_UBIGINT */
typedef unsigned long backsql_key_t;
#define BACKSQL_C_NUMID SQL_C_ULONG
#define BACKSQL_IDNUMFMT "%lu"
#define BACKSQL_STR2ID lutil_atoulx
#endif /* ! HAVE_LONG_LONG */
/*
* define to enable support for syncprov overlay
*/
#define BACKSQL_SYNCPROV
/*
* define to the appropriate aliasing string
*
* some RDBMSes tolerate (or require) that " AS " is not used
* when aliasing tables/columns
*/
#define BACKSQL_ALIASING "AS "
/* #define BACKSQL_ALIASING "" */
/*
* define to the appropriate quoting char
*
* some RDBMSes tolerate/require that the aliases be enclosed
* in quotes. This is especially true for those that do not
* allow keywords used as aliases.
*/
#define BACKSQL_ALIASING_QUOTE ""
/* #define BACKSQL_ALIASING_QUOTE "\"" */
/* #define BACKSQL_ALIASING_QUOTE "'" */
/*
* API
*
* a simple mechanism to allow DN mucking between the LDAP
* and the stored string representation.
*/
typedef struct backsql_api {
char *ba_name;
int (*ba_config)( struct backsql_api *self, int argc, char *argv[] );
int (*ba_destroy)( struct backsql_api *self );
int (*ba_dn2odbc)( Operation *op, SlapReply *rs, struct berval *dn );
int (*ba_odbc2dn)( Operation *op, SlapReply *rs, struct berval *dn );
void *ba_private;
struct backsql_api *ba_next;
char **ba_argv;
int ba_argc;
} backsql_api;
/*
* "structural" objectClass mapping structure
*/
typedef struct backsql_oc_map_rec {
/*
* Structure of corresponding LDAP objectClass definition
*/
ObjectClass *bom_oc;
#define BACKSQL_OC_NAME(ocmap) ((ocmap)->bom_oc->soc_cname.bv_val)
struct berval bom_keytbl;
struct berval bom_keycol;
/* expected to return keyval of newly created entry */
char *bom_create_proc;
/* in case create_proc does not return the keyval of the newly
* created row */
char *bom_create_keyval;
/* supposed to expect keyval as parameter and delete
* all the attributes as well */
char *bom_delete_proc;
/* flags whether delete_proc is a function (whether back-sql
* should bind first parameter as output for return code) */
int bom_expect_return;
backsql_key_t bom_id;
Avlnode *bom_attrs;
AttributeDescription *bom_create_hint;
} backsql_oc_map_rec;
/*
* attributeType mapping structure
*/
typedef struct backsql_at_map_rec {
/* Description of corresponding LDAP attribute type */
AttributeDescription *bam_ad;
AttributeDescription *bam_true_ad;
/* ObjectClass if bam_ad is objectClass */
ObjectClass *bam_oc;
struct berval bam_from_tbls;
struct berval bam_join_where;
struct berval bam_sel_expr;
/* TimesTen, or, if a uppercase function is defined,
* an uppercased version of bam_sel_expr */
struct berval bam_sel_expr_u;
/* supposed to expect 2 binded values: entry keyval
* and attr. value to add, like "add_name(?,?,?)" */
char *bam_add_proc;
/* supposed to expect 2 binded values: entry keyval
* and attr. value to delete */
char *bam_delete_proc;
/* for optimization purposes attribute load query
* is preconstructed from parts on schemamap load time */
char *bam_query;
#ifdef BACKSQL_COUNTQUERY
char *bam_countquery;
#endif /* BACKSQL_COUNTQUERY */
/* following flags are bitmasks (first bit used for add_proc,
* second - for delete_proc) */
/* order of parameters for procedures above;
* 1 means "data then keyval", 0 means "keyval then data" */
int bam_param_order;
/* flags whether one or more of procedures is a function
* (whether back-sql should bind first parameter as output
* for return code) */
int bam_expect_return;
/* next mapping for attribute */
struct backsql_at_map_rec *bam_next;
} backsql_at_map_rec;
#define BACKSQL_AT_MAP_REC_INIT { NULL, NULL, BER_BVC(""), BER_BVC(""), BER_BVNULL, BER_BVNULL, NULL, NULL, NULL, 0, 0, NULL }
/* define to uppercase filters only if the matching rule requires it
* (currently broken) */
/* #define BACKSQL_UPPERCASE_FILTER */
#define BACKSQL_AT_CANUPPERCASE(at) ( !BER_BVISNULL( &(at)->bam_sel_expr_u ) )
/* defines to support bitmasks above */
#define BACKSQL_ADD 0x1
#define BACKSQL_DEL 0x2
#define BACKSQL_IS_ADD(x) ( ( BACKSQL_ADD & (x) ) == BACKSQL_ADD )
#define BACKSQL_IS_DEL(x) ( ( BACKSQL_DEL & (x) ) == BACKSQL_DEL )
#define BACKSQL_NCMP(v1,v2) ber_bvcmp((v1),(v2))
#define BACKSQL_CONCAT
/*
* berbuf structure: a berval with a buffer size associated
*/
typedef struct berbuf {
struct berval bb_val;
ber_len_t bb_len;
} BerBuffer;
#define BB_NULL { BER_BVNULL, 0 }
/*
* Entry ID structure
*/
typedef struct backsql_entryID {
/* #define BACKSQL_ARBITRARY_KEY to allow a non-numeric key.
* It is required by some special applications that use
* strings as keys for the main table.
* In this case, #define BACKSQL_MAX_KEY_LEN consistently
* with the key size definition */
#ifdef BACKSQL_ARBITRARY_KEY
struct berval eid_id;
struct berval eid_keyval;
#define BACKSQL_MAX_KEY_LEN 64
#else /* ! BACKSQL_ARBITRARY_KEY */
/* The original numeric key is maintained as default. */
backsql_key_t eid_id;
backsql_key_t eid_keyval;
#endif /* ! BACKSQL_ARBITRARY_KEY */
backsql_key_t eid_oc_id;
backsql_oc_map_rec *eid_oc;
struct berval eid_dn;
struct berval eid_ndn;
struct backsql_entryID *eid_next;
} backsql_entryID;
#ifdef BACKSQL_ARBITRARY_KEY
#define BACKSQL_ENTRYID_INIT { BER_BVNULL, BER_BVNULL, 0, NULL, BER_BVNULL, BER_BVNULL, NULL }
#else /* ! BACKSQL_ARBITRARY_KEY */
#define BACKSQL_ENTRYID_INIT { 0, 0, 0, NULL, BER_BVNULL, BER_BVNULL, NULL }
#endif /* BACKSQL_ARBITRARY_KEY */
/* the function must collect the entry associated to nbase */
#define BACKSQL_ISF_GET_ID 0x1U
#define BACKSQL_ISF_GET_ENTRY ( 0x2U | BACKSQL_ISF_GET_ID )
#define BACKSQL_ISF_GET_OC ( 0x4U | BACKSQL_ISF_GET_ID )
#define BACKSQL_ISF_MATCHED 0x8U
#define BACKSQL_IS_GET_ID(f) \
( ( (f) & BACKSQL_ISF_GET_ID ) == BACKSQL_ISF_GET_ID )
#define BACKSQL_IS_GET_ENTRY(f) \
( ( (f) & BACKSQL_ISF_GET_ENTRY ) == BACKSQL_ISF_GET_ENTRY )
#define BACKSQL_IS_GET_OC(f) \
( ( (f) & BACKSQL_ISF_GET_OC ) == BACKSQL_ISF_GET_OC )
#define BACKSQL_IS_MATCHED(f) \
( ( (f) & BACKSQL_ISF_MATCHED ) == BACKSQL_ISF_MATCHED )
typedef struct backsql_srch_info {
Operation *bsi_op;
SlapReply *bsi_rs;
unsigned bsi_flags;
#define BSQL_SF_NONE 0x0000U
#define BSQL_SF_ALL_USER 0x0001U
#define BSQL_SF_ALL_OPER 0x0002U
#define BSQL_SF_ALL_ATTRS (BSQL_SF_ALL_USER|BSQL_SF_ALL_OPER)
#define BSQL_SF_FILTER_HASSUBORDINATE 0x0010U
#define BSQL_SF_FILTER_ENTRYUUID 0x0020U
#define BSQL_SF_FILTER_ENTRYCSN 0x0040U
#define BSQL_SF_RETURN_ENTRYUUID (BSQL_SF_FILTER_ENTRYUUID << 8)
#define BSQL_ISF(bsi, f) ( ( (bsi)->bsi_flags & f ) == f )
#define BSQL_ISF_ALL_USER(bsi) BSQL_ISF(bsi, BSQL_SF_ALL_USER)
#define BSQL_ISF_ALL_OPER(bsi) BSQL_ISF(bsi, BSQL_SF_ALL_OPER)
#define BSQL_ISF_ALL_ATTRS(bsi) BSQL_ISF(bsi, BSQL_SF_ALL_ATTRS)
struct berval *bsi_base_ndn;
int bsi_use_subtree_shortcut;
backsql_entryID bsi_base_id;
int bsi_scope;
/* BACKSQL_SCOPE_BASE_LIKE can be set by API in ors_scope
* whenever the search base DN contains chars that cannot
* be mapped into the charset used in the RDBMS; so they're
* turned into '%' and an approximate ('LIKE') condition
* is used */
#define BACKSQL_SCOPE_BASE_LIKE ( LDAP_SCOPE_BASE | 0x1000 )
Filter *bsi_filter;
time_t bsi_stoptime;
backsql_entryID *bsi_id_list,
**bsi_id_listtail,
*bsi_c_eid;
int bsi_n_candidates;
int bsi_status;
backsql_oc_map_rec *bsi_oc;
struct berbuf bsi_sel,
bsi_from,
bsi_join_where,
bsi_flt_where;
ObjectClass *bsi_filter_oc;
SQLHDBC bsi_dbh;
AttributeName *bsi_attrs;
Entry *bsi_e;
} backsql_srch_info;
/*
* Backend private data structure
*/
typedef struct backsql_info {
char *sql_dbhost;
int sql_dbport;
char *sql_dbuser;
char *sql_dbpasswd;
char *sql_dbname;
/*
* SQL condition for subtree searches differs in syntax:
* "LIKE CONCAT('%',?)" or "LIKE '%'+?" or "LIKE '%'||?"
* or smtg else
*/
struct berval sql_subtree_cond;
struct berval sql_children_cond;
struct berval sql_dn_match_cond;
char *sql_oc_query;
char *sql_at_query;
char *sql_insentry_stmt;
char *sql_delentry_stmt;
char *sql_renentry_stmt;
char *sql_delobjclasses_stmt;
char *sql_id_query;
char *sql_has_children_query;
char *sql_list_children_query;
MatchingRule *sql_caseIgnoreMatch;
MatchingRule *sql_telephoneNumberMatch;
struct berval sql_upper_func;
struct berval sql_upper_func_open;
struct berval sql_upper_func_close;
struct berval sql_strcast_func;
BerVarray sql_concat_func;
char *sql_concat_patt;
struct berval sql_aliasing;
struct berval sql_aliasing_quote;
struct berval sql_dn_oc_aliasing;
AttributeName *sql_anlist;
unsigned int sql_flags;
#define BSQLF_SCHEMA_LOADED 0x0001
#define BSQLF_UPPER_NEEDS_CAST 0x0002
#define BSQLF_CREATE_NEEDS_SELECT 0x0004
#define BSQLF_FAIL_IF_NO_MAPPING 0x0008
#define BSQLF_HAS_LDAPINFO_DN_RU 0x0010
#define BSQLF_DONTCHECK_LDAPINFO_DN_RU 0x0020
#define BSQLF_USE_REVERSE_DN 0x0040
#define BSQLF_ALLOW_ORPHANS 0x0080
#define BSQLF_USE_SUBTREE_SHORTCUT 0x0100
#define BSQLF_FETCH_ALL_USERATTRS 0x0200
#define BSQLF_FETCH_ALL_OPATTRS 0x0400
#define BSQLF_FETCH_ALL_ATTRS (BSQLF_FETCH_ALL_USERATTRS|BSQLF_FETCH_ALL_OPATTRS)
#define BSQLF_CHECK_SCHEMA 0x0800
#define BSQLF_AUTOCOMMIT_ON 0x1000
#define BACKSQL_ISF(si, f) \
(((si)->sql_flags & f) == f)
#define BACKSQL_SCHEMA_LOADED(si) \
BACKSQL_ISF(si, BSQLF_SCHEMA_LOADED)
#define BACKSQL_UPPER_NEEDS_CAST(si) \
BACKSQL_ISF(si, BSQLF_UPPER_NEEDS_CAST)
#define BACKSQL_CREATE_NEEDS_SELECT(si) \
BACKSQL_ISF(si, BSQLF_CREATE_NEEDS_SELECT)
#define BACKSQL_FAIL_IF_NO_MAPPING(si) \
BACKSQL_ISF(si, BSQLF_FAIL_IF_NO_MAPPING)
#define BACKSQL_HAS_LDAPINFO_DN_RU(si) \
BACKSQL_ISF(si, BSQLF_HAS_LDAPINFO_DN_RU)
#define BACKSQL_DONTCHECK_LDAPINFO_DN_RU(si) \
BACKSQL_ISF(si, BSQLF_DONTCHECK_LDAPINFO_DN_RU)
#define BACKSQL_USE_REVERSE_DN(si) \
BACKSQL_ISF(si, BSQLF_USE_REVERSE_DN)
#define BACKSQL_CANUPPERCASE(si) \
(!BER_BVISNULL( &(si)->sql_upper_func ))
#define BACKSQL_ALLOW_ORPHANS(si) \
BACKSQL_ISF(si, BSQLF_ALLOW_ORPHANS)
#define BACKSQL_USE_SUBTREE_SHORTCUT(si) \
BACKSQL_ISF(si, BSQLF_USE_SUBTREE_SHORTCUT)
#define BACKSQL_FETCH_ALL_USERATTRS(si) \
BACKSQL_ISF(si, BSQLF_FETCH_ALL_USERATTRS)
#define BACKSQL_FETCH_ALL_OPATTRS(si) \
BACKSQL_ISF(si, BSQLF_FETCH_ALL_OPATTRS)
#define BACKSQL_FETCH_ALL_ATTRS(si) \
BACKSQL_ISF(si, BSQLF_FETCH_ALL_ATTRS)
#define BACKSQL_CHECK_SCHEMA(si) \
BACKSQL_ISF(si, BSQLF_CHECK_SCHEMA)
#define BACKSQL_AUTOCOMMIT_ON(si) \
BACKSQL_ISF(si, BSQLF_AUTOCOMMIT_ON)
Entry *sql_baseObject;
char *sql_base_ob_file;
#ifdef BACKSQL_ARBITRARY_KEY
#define BACKSQL_BASEOBJECT_IDSTR "baseObject"
#define BACKSQL_BASEOBJECT_KEYVAL BACKSQL_BASEOBJECT_IDSTR
#define BACKSQL_IS_BASEOBJECT_ID(id) (bvmatch((id), &backsql_baseObject_bv))
#else /* ! BACKSQL_ARBITRARY_KEY */
#define BACKSQL_BASEOBJECT_ID 0
#define BACKSQL_BASEOBJECT_IDSTR LDAP_XSTRING(BACKSQL_BASEOBJECT_ID)
#define BACKSQL_BASEOBJECT_KEYVAL 0
#define BACKSQL_IS_BASEOBJECT_ID(id) (*(id) == BACKSQL_BASEOBJECT_ID)
#endif /* ! BACKSQL_ARBITRARY_KEY */
#define BACKSQL_BASEOBJECT_OC 0
Avlnode *sql_db_conns;
SQLHDBC sql_dbh;
ldap_pvt_thread_mutex_t sql_dbconn_mutex;
Avlnode *sql_oc_by_oc;
Avlnode *sql_oc_by_id;
ldap_pvt_thread_mutex_t sql_schema_mutex;
SQLHENV sql_db_env;
backsql_api *sql_api;
} backsql_info;
#define BACKSQL_SUCCESS( rc ) \
( (rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO )
#define BACKSQL_AVL_STOP 0
#define BACKSQL_AVL_CONTINUE 1
/* see ldap.h for the meaning of the macros and of the values */
#define BACKSQL_LEGAL_ERROR( rc ) \
( LDAP_RANGE( (rc), 0x00, 0x0e ) \
|| LDAP_ATTR_ERROR( (rc) ) \
|| LDAP_NAME_ERROR( (rc) ) \
|| LDAP_SECURITY_ERROR( (rc) ) \
|| LDAP_SERVICE_ERROR( (rc) ) \
|| LDAP_UPDATE_ERROR( (rc) ) )
#define BACKSQL_SANITIZE_ERROR( rc ) \
( BACKSQL_LEGAL_ERROR( (rc) ) ? (rc) : LDAP_OTHER )
#define BACKSQL_IS_BINARY(ct) \
( (ct) == SQL_BINARY \
|| (ct) == SQL_VARBINARY \
|| (ct) == SQL_LONGVARBINARY)
#ifdef BACKSQL_ARBITRARY_KEY
#define BACKSQL_IDFMT "%s"
#define BACKSQL_IDARG(arg) ((arg).bv_val)
#else /* ! BACKSQL_ARBITRARY_KEY */
#define BACKSQL_IDFMT BACKSQL_IDNUMFMT
#define BACKSQL_IDARG(arg) (arg)
#endif /* ! BACKSQL_ARBITRARY_KEY */
#endif /* __BACKSQL_H__ */

View file

@ -1,115 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Masarati.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati.
*/
#include "portable.h"
#include <stdio.h>
#include <sys/types.h>
#include "slap.h"
#include "proto-sql.h"
int
backsql_bind( Operation *op, SlapReply *rs )
{
SQLHDBC dbh = SQL_NULL_HDBC;
Entry e = { 0 };
Attribute *a;
backsql_srch_info bsi = { 0 };
AttributeName anlist[2];
int rc;
Debug( LDAP_DEBUG_TRACE, "==>backsql_bind()\n" );
switch ( be_rootdn_bind( op, rs ) ) {
case SLAP_CB_CONTINUE:
break;
default:
/* in case of success, front end will send result;
* otherwise, be_rootdn_bind() did */
Debug( LDAP_DEBUG_TRACE, "<==backsql_bind(%d)\n",
rs->sr_err );
return rs->sr_err;
}
rs->sr_err = backsql_get_db_conn( op, &dbh );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_bind(): "
"could not get connection handle - exiting\n" );
rs->sr_text = ( rs->sr_err == LDAP_OTHER )
? "SQL-backend error" : NULL;
goto error_return;
}
anlist[0].an_name = slap_schema.si_ad_userPassword->ad_cname;
anlist[0].an_desc = slap_schema.si_ad_userPassword;
anlist[1].an_name.bv_val = NULL;
bsi.bsi_e = &e;
rc = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs, anlist,
BACKSQL_ISF_GET_ENTRY );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_bind(): "
"could not retrieve bindDN ID - no such entry\n" );
rs->sr_err = LDAP_INVALID_CREDENTIALS;
goto error_return;
}
a = attr_find( e.e_attrs, slap_schema.si_ad_userPassword );
if ( a == NULL ) {
rs->sr_err = LDAP_INVALID_CREDENTIALS;
goto error_return;
}
if ( slap_passwd_check( op, &e, a, &op->oq_bind.rb_cred,
&rs->sr_text ) != 0 )
{
rs->sr_err = LDAP_INVALID_CREDENTIALS;
goto error_return;
}
error_return:;
if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
(void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &e.e_nname ) ) {
backsql_entry_clean( op, &e );
}
if ( bsi.bsi_attrs != NULL ) {
op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx );
}
if ( rs->sr_err != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
}
SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
Debug( LDAP_DEBUG_TRACE,"<==backsql_bind()\n" );
return rs->sr_err;
}

View file

@ -1,194 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Masarati.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati.
*/
#include "portable.h"
#include <stdio.h>
#include <sys/types.h>
#include "slap.h"
#include "proto-sql.h"
int
backsql_compare( Operation *op, SlapReply *rs )
{
SQLHDBC dbh = SQL_NULL_HDBC;
Entry e = { 0 };
Attribute *a = NULL;
backsql_srch_info bsi = { 0 };
int rc;
int manageDSAit = wants_manageDSAit( op );
AttributeName anlist[2];
Debug( LDAP_DEBUG_TRACE, "==>backsql_compare()\n" );
rs->sr_err = backsql_get_db_conn( op, &dbh );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_compare(): "
"could not get connection handle - exiting\n" );
rs->sr_text = ( rs->sr_err == LDAP_OTHER )
? "SQL-backend error" : NULL;
goto return_results;
}
anlist[ 0 ].an_name = op->oq_compare.rs_ava->aa_desc->ad_cname;
anlist[ 0 ].an_desc = op->oq_compare.rs_ava->aa_desc;
BER_BVZERO( &anlist[ 1 ].an_name );
/*
* Get the entry
*/
bsi.bsi_e = &e;
rc = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs, anlist,
( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
switch ( rc ) {
case LDAP_SUCCESS:
break;
case LDAP_REFERRAL:
if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
{
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
rs->sr_matched = NULL;
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
break;
}
/* fallthru */
default:
Debug( LDAP_DEBUG_TRACE, "backsql_compare(): "
"could not retrieve compareDN ID - no such entry\n" );
goto return_results;
}
if ( wants_assert( op ) &&
( test_filter( op, &e, get_assertion( op ) )
!= LDAP_COMPARE_TRUE ) )
{
rs->sr_err = LDAP_ASSERTION_FAILED;
goto return_results;
}
if ( is_at_operational( op->oq_compare.rs_ava->aa_desc->ad_type ) ) {
SlapReply nrs = { REP_SEARCH };
Attribute **ap;
for ( ap = &e.e_attrs; *ap; ap = &(*ap)->a_next )
;
nrs.sr_attrs = anlist;
nrs.sr_entry = &e;
nrs.sr_attr_flags = SLAP_OPATTRS_NO;
nrs.sr_operational_attrs = NULL;
rs->sr_err = backsql_operational( op, &nrs );
if ( rs->sr_err != LDAP_SUCCESS ) {
goto return_results;
}
*ap = nrs.sr_operational_attrs;
}
if ( ! access_allowed( op, &e, op->oq_compare.rs_ava->aa_desc,
&op->oq_compare.rs_ava->aa_value,
ACL_COMPARE, NULL ) )
{
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
}
rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE;
for ( a = attrs_find( e.e_attrs, op->oq_compare.rs_ava->aa_desc );
a != NULL;
a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc ) )
{
rs->sr_err = LDAP_COMPARE_FALSE;
if ( attr_valfind( a,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
&op->oq_compare.rs_ava->aa_value, NULL,
op->o_tmpmemctx ) == 0 )
{
rs->sr_err = LDAP_COMPARE_TRUE;
break;
}
}
return_results:;
switch ( rs->sr_err ) {
case LDAP_COMPARE_TRUE:
case LDAP_COMPARE_FALSE:
break;
default:
if ( !BER_BVISNULL( &e.e_nname ) &&
! access_allowed( op, &e,
slap_schema.si_ad_entry, NULL,
ACL_DISCLOSE, NULL ) )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
rs->sr_text = NULL;
}
break;
}
send_ldap_result( op, rs );
if ( rs->sr_matched ) {
rs->sr_matched = NULL;
}
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
(void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &e.e_nname ) ) {
backsql_entry_clean( op, &e );
}
if ( bsi.bsi_attrs != NULL ) {
op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx );
}
Debug(LDAP_DEBUG_TRACE,"<==backsql_compare()\n" );
switch ( rs->sr_err ) {
case LDAP_COMPARE_TRUE:
case LDAP_COMPARE_FALSE:
return LDAP_SUCCESS;
default:
return rs->sr_err;
}
}

View file

@ -1,778 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Masarati.
* Portions Copyright 2004 Mark Adamson.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati.
*/
#include "portable.h"
#include <stdio.h>
#include "ac/string.h"
#include <sys/types.h>
#include "slap.h"
#include "slap-config.h"
#include "ldif.h"
#include "lutil.h"
#include "proto-sql.h"
static int
create_baseObject(
BackendDB *be,
const char *fname,
int lineno );
static int
read_baseObject(
BackendDB *be,
const char *fname );
static ConfigDriver sql_cf_gen;
enum {
BSQL_CONCAT_PATT = 1,
BSQL_CREATE_NEEDS_SEL,
BSQL_UPPER_NEEDS_CAST,
BSQL_HAS_LDAPINFO_DN_RU,
BSQL_FAIL_IF_NO_MAPPING,
BSQL_ALLOW_ORPHANS,
BSQL_BASE_OBJECT,
BSQL_LAYER,
BSQL_SUBTREE_SHORTCUT,
BSQL_FETCH_ALL_ATTRS,
BSQL_FETCH_ATTRS,
BSQL_CHECK_SCHEMA,
BSQL_ALIASING_KEYWORD,
BSQL_AUTOCOMMIT
};
static ConfigTable sqlcfg[] = {
{ "dbhost", "hostname", 2, 2, 0, ARG_STRING|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_dbhost),
"( OLcfgDbAt:6.1 NAME 'olcDbHost' "
"DESC 'Hostname of SQL server' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "dbname", "name", 2, 2, 0, ARG_STRING|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_dbname),
"( OLcfgDbAt:6.2 NAME 'olcDbName' "
"DESC 'Name of SQL database' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "dbuser", "username", 2, 2, 0, ARG_STRING|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_dbuser),
"( OLcfgDbAt:6.3 NAME 'olcDbUser' "
"DESC 'Username for SQL session' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "dbpasswd", "password", 2, 2, 0, ARG_STRING|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_dbpasswd),
"( OLcfgDbAt:6.4 NAME 'olcDbPass' "
"DESC 'Password for SQL session' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "concat_pattern", "pattern", 2, 2, 0,
ARG_STRING|ARG_MAGIC|BSQL_CONCAT_PATT, (void *)sql_cf_gen,
"( OLcfgDbAt:6.20 NAME 'olcSqlConcatPattern' "
"DESC 'Pattern used to concatenate strings' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "subtree_cond", "SQL expression", 2, 0, 0, ARG_BERVAL|ARG_QUOTE|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_subtree_cond),
"( OLcfgDbAt:6.21 NAME 'olcSqlSubtreeCond' "
"DESC 'Where-clause template for a subtree search condition' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "children_cond", "SQL expression", 2, 0, 0, ARG_BERVAL|ARG_QUOTE|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_children_cond),
"( OLcfgDbAt:6.22 NAME 'olcSqlChildrenCond' "
"DESC 'Where-clause template for a children search condition' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "dn_match_cond", "SQL expression", 2, 0, 0, ARG_BERVAL|ARG_QUOTE|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_dn_match_cond),
"( OLcfgDbAt:6.23 NAME 'olcSqlDnMatchCond' "
"DESC 'Where-clause template for a DN match search condition' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "oc_query", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_oc_query),
"( OLcfgDbAt:6.24 NAME 'olcSqlOcQuery' "
"DESC 'Query used to collect objectClass mapping data' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "at_query", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_at_query),
"( OLcfgDbAt:6.25 NAME 'olcSqlAtQuery' "
"DESC 'Query used to collect attributeType mapping data' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "insentry_stmt", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_insentry_stmt),
"( OLcfgDbAt:6.26 NAME 'olcSqlInsEntryStmt' "
"DESC 'Statement used to insert a new entry' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "create_needs_select", "yes|no", 2, 2, 0,
ARG_ON_OFF|ARG_MAGIC|BSQL_CREATE_NEEDS_SEL, (void *)sql_cf_gen,
"( OLcfgDbAt:6.27 NAME 'olcSqlCreateNeedsSelect' "
"DESC 'Whether entry creation needs a subsequent select' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "upper_func", "SQL function name", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_upper_func),
"( OLcfgDbAt:6.28 NAME 'olcSqlUpperFunc' "
"DESC 'Function that converts a value to uppercase' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "upper_needs_cast", "yes|no", 2, 2, 0,
ARG_ON_OFF|ARG_MAGIC|BSQL_UPPER_NEEDS_CAST, (void *)sql_cf_gen,
"( OLcfgDbAt:6.29 NAME 'olcSqlUpperNeedsCast' "
"DESC 'Whether olcSqlUpperFunc needs an explicit cast' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "strcast_func", "SQL function name", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_strcast_func),
"( OLcfgDbAt:6.30 NAME 'olcSqlStrcastFunc' "
"DESC 'Function that converts a value to a string' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "delentry_stmt", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_delentry_stmt),
"( OLcfgDbAt:6.31 NAME 'olcSqlDelEntryStmt' "
"DESC 'Statement used to delete an existing entry' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "renentry_stmt", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_renentry_stmt),
"( OLcfgDbAt:6.32 NAME 'olcSqlRenEntryStmt' "
"DESC 'Statement used to rename an entry' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "delobjclasses_stmt", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_delobjclasses_stmt),
"( OLcfgDbAt:6.33 NAME 'olcSqlDelObjclassesStmt' "
"DESC 'Statement used to delete the ID of an entry' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "has_ldapinfo_dn_ru", "yes|no", 2, 2, 0,
ARG_ON_OFF|ARG_MAGIC|BSQL_HAS_LDAPINFO_DN_RU, (void *)sql_cf_gen,
"( OLcfgDbAt:6.34 NAME 'olcSqlHasLDAPinfoDnRu' "
"DESC 'Whether the dn_ru column is present' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "fail_if_no_mapping", "yes|no", 2, 2, 0,
ARG_ON_OFF|ARG_MAGIC|BSQL_FAIL_IF_NO_MAPPING, (void *)sql_cf_gen,
"( OLcfgDbAt:6.35 NAME 'olcSqlFailIfNoMapping' "
"DESC 'Whether to fail on unknown attribute mappings' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "allow_orphans", "yes|no", 2, 2, 0,
ARG_ON_OFF|ARG_MAGIC|BSQL_ALLOW_ORPHANS, (void *)sql_cf_gen,
"( OLcfgDbAt:6.36 NAME 'olcSqlAllowOrphans' "
"DESC 'Whether to allow adding entries with no parent' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "baseobject", "[file]", 1, 2, 0,
ARG_STRING|ARG_MAGIC|BSQL_BASE_OBJECT, (void *)sql_cf_gen,
"( OLcfgDbAt:6.37 NAME 'olcSqlBaseObject' "
"DESC 'Manage an in-memory baseObject entry' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "sqllayer", "name", 2, 0, 0,
ARG_MAGIC|BSQL_LAYER, (void *)sql_cf_gen,
"( OLcfgDbAt:6.38 NAME 'olcSqlLayer' "
"DESC 'Helper used to map DNs between LDAP and SQL' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "use_subtree_shortcut", "yes|no", 2, 2, 0,
ARG_ON_OFF|ARG_MAGIC|BSQL_SUBTREE_SHORTCUT, (void *)sql_cf_gen,
"( OLcfgDbAt:6.39 NAME 'olcSqlUseSubtreeShortcut' "
"DESC 'Collect all entries when searchBase is DB suffix' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "fetch_all_attrs", "yes|no", 2, 2, 0,
ARG_ON_OFF|ARG_MAGIC|BSQL_FETCH_ALL_ATTRS, (void *)sql_cf_gen,
"( OLcfgDbAt:6.40 NAME 'olcSqlFetchAllAttrs' "
"DESC 'Require all attributes to always be loaded' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "fetch_attrs", "attrlist", 2, 0, 0,
ARG_MAGIC|BSQL_FETCH_ATTRS, (void *)sql_cf_gen,
"( OLcfgDbAt:6.41 NAME 'olcSqlFetchAttrs' "
"DESC 'Set of attributes to always fetch' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "check_schema", "yes|no", 2, 2, 0,
ARG_ON_OFF|ARG_MAGIC|BSQL_CHECK_SCHEMA, (void *)sql_cf_gen,
"( OLcfgDbAt:6.42 NAME 'olcSqlCheckSchema' "
"DESC 'Check schema after modifications' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "aliasing_keyword", "string", 2, 2, 0,
ARG_STRING|ARG_MAGIC|BSQL_ALIASING_KEYWORD, (void *)sql_cf_gen,
"( OLcfgDbAt:6.43 NAME 'olcSqlAliasingKeyword' "
"DESC 'The aliasing keyword' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "aliasing_quote", "string", 2, 2, 0, ARG_BERVAL|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_aliasing_quote),
"( OLcfgDbAt:6.44 NAME 'olcSqlAliasingQuote' "
"DESC 'Quoting char of the aliasing keyword' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "autocommit", "yes|no", 2, 2, 0,
ARG_ON_OFF|ARG_MAGIC|BSQL_AUTOCOMMIT, (void *)sql_cf_gen,
"( OLcfgDbAt:6.45 NAME 'olcSqlAutocommit' "
"EQUALITY booleanMatch "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ "id_query", "SQL expression", 2, 0, 0, ARG_STRING|ARG_QUOTE|ARG_OFFSET,
(void *)offsetof(struct backsql_info, sql_id_query),
"( OLcfgDbAt:6.46 NAME 'olcSqlIdQuery' "
"DESC 'Query used to collect entryID mapping data' "
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
NULL, NULL, NULL, NULL }
};
static ConfigOCs sqlocs[] = {
{
"( OLcfgDbOc:6.1 "
"NAME 'olcSqlConfig' "
"DESC 'SQL backend configuration' "
"SUP olcDatabaseConfig "
"MUST olcDbName "
"MAY ( olcDbHost $ olcDbUser $ olcDbPass $ olcSqlConcatPattern $ "
"olcSqlSubtreeCond $ olcsqlChildrenCond $ olcSqlDnMatchCond $ "
"olcSqlOcQuery $ olcSqlAtQuery $ olcSqlInsEntryStmt $ "
"olcSqlCreateNeedsSelect $ olcSqlUpperFunc $ olcSqlUpperNeedsCast $ "
"olcSqlStrCastFunc $ olcSqlDelEntryStmt $ olcSqlRenEntryStmt $ "
"olcSqlDelObjClassesStmt $ olcSqlHasLDAPInfoDnRu $ "
"olcSqlFailIfNoMapping $ olcSqlAllowOrphans $ olcSqlBaseObject $ "
"olcSqlLayer $ olcSqlUseSubtreeShortcut $ olcSqlFetchAllAttrs $ "
"olcSqlFetchAttrs $ olcSqlCheckSchema $ olcSqlAliasingKeyword $ "
"olcSqlAliasingQuote $ olcSqlAutocommit $ olcSqlIdQuery ) )",
Cft_Database, sqlcfg },
{ NULL, Cft_Abstract, NULL }
};
static int
sql_cf_gen( ConfigArgs *c )
{
backsql_info *bi = (backsql_info *)c->be->be_private;
int rc = 0;
if ( c->op == SLAP_CONFIG_EMIT ) {
switch( c->type ) {
case BSQL_CONCAT_PATT:
if ( bi->sql_concat_patt ) {
c->value_string = ch_strdup( bi->sql_concat_patt );
} else {
rc = 1;
}
break;
case BSQL_CREATE_NEEDS_SEL:
if ( bi->sql_flags & BSQLF_CREATE_NEEDS_SELECT )
c->value_int = 1;
break;
case BSQL_UPPER_NEEDS_CAST:
if ( bi->sql_flags & BSQLF_UPPER_NEEDS_CAST )
c->value_int = 1;
break;
case BSQL_HAS_LDAPINFO_DN_RU:
if ( !(bi->sql_flags & BSQLF_DONTCHECK_LDAPINFO_DN_RU) )
return 1;
if ( bi->sql_flags & BSQLF_HAS_LDAPINFO_DN_RU )
c->value_int = 1;
break;
case BSQL_FAIL_IF_NO_MAPPING:
if ( bi->sql_flags & BSQLF_FAIL_IF_NO_MAPPING )
c->value_int = 1;
break;
case BSQL_ALLOW_ORPHANS:
if ( bi->sql_flags & BSQLF_ALLOW_ORPHANS )
c->value_int = 1;
break;
case BSQL_SUBTREE_SHORTCUT:
if ( bi->sql_flags & BSQLF_USE_SUBTREE_SHORTCUT )
c->value_int = 1;
break;
case BSQL_FETCH_ALL_ATTRS:
if ( bi->sql_flags & BSQLF_FETCH_ALL_ATTRS )
c->value_int = 1;
break;
case BSQL_CHECK_SCHEMA:
if ( bi->sql_flags & BSQLF_CHECK_SCHEMA )
c->value_int = 1;
break;
case BSQL_AUTOCOMMIT:
if ( bi->sql_flags & BSQLF_AUTOCOMMIT_ON )
c->value_int = 1;
break;
case BSQL_BASE_OBJECT:
if ( bi->sql_base_ob_file ) {
c->value_string = ch_strdup( bi->sql_base_ob_file );
} else if ( bi->sql_baseObject ) {
c->value_string = ch_strdup( "TRUE" );
} else {
rc = 1;
}
break;
case BSQL_LAYER:
if ( bi->sql_api ) {
backsql_api *ba;
struct berval bv;
char *ptr;
int i;
for ( ba = bi->sql_api; ba; ba = ba->ba_next ) {
bv.bv_len = strlen( ba->ba_name );
if ( ba->ba_argc ) {
for ( i = 0; i<ba->ba_argc; i++ )
bv.bv_len += strlen( ba->ba_argv[i] ) + 3;
}
bv.bv_val = ch_malloc( bv.bv_len + 1 );
ptr = lutil_strcopy( bv.bv_val, ba->ba_name );
if ( ba->ba_argc ) {
for ( i = 0; i<ba->ba_argc; i++ ) {
*ptr++ = ' ';
*ptr++ = '"';
ptr = lutil_strcopy( ptr, ba->ba_argv[i] );
*ptr++ = '"';
}
}
ber_bvarray_add( &c->rvalue_vals, &bv );
}
} else {
rc = 1;
}
break;
case BSQL_ALIASING_KEYWORD:
if ( !BER_BVISNULL( &bi->sql_aliasing )) {
struct berval bv;
bv = bi->sql_aliasing;
bv.bv_len--;
value_add_one( &c->rvalue_vals, &bv );
} else {
rc = 1;
}
break;
case BSQL_FETCH_ATTRS:
if ( bi->sql_anlist ||
( bi->sql_flags & (BSQLF_FETCH_ALL_USERATTRS|
BSQLF_FETCH_ALL_OPATTRS)))
{
char buf[BUFSIZ*2], *ptr;
struct berval bv;
# define WHATSLEFT ((ber_len_t) (&buf[sizeof( buf )] - ptr))
ptr = buf;
if ( bi->sql_anlist ) {
ptr = anlist_unparse( bi->sql_anlist, ptr, WHATSLEFT );
if ( ptr == NULL )
return 1;
}
if ( bi->sql_flags & BSQLF_FETCH_ALL_USERATTRS ) {
if ( WHATSLEFT <= STRLENOF( ",*" )) return 1;
if ( ptr != buf ) *ptr++ = ',';
*ptr++ = '*';
}
if ( bi->sql_flags & BSQLF_FETCH_ALL_OPATTRS ) {
if ( WHATSLEFT <= STRLENOF( ",+" )) return 1;
if ( ptr != buf ) *ptr++ = ',';
*ptr++ = '+';
}
bv.bv_val = buf;
bv.bv_len = ptr - buf;
value_add_one( &c->rvalue_vals, &bv );
}
break;
}
return rc;
} else if ( c->op == LDAP_MOD_DELETE ) { /* FIXME */
return -1;
}
switch( c->type ) {
case BSQL_CONCAT_PATT:
if ( backsql_split_pattern( c->argv[ 1 ], &bi->sql_concat_func, 2 ) ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s: unable to parse pattern \"%s\"",
c->log, c->argv[ 1 ] );
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg );
return -1;
}
bi->sql_concat_patt = c->value_string;
break;
case BSQL_CREATE_NEEDS_SEL:
if ( c->value_int )
bi->sql_flags |= BSQLF_CREATE_NEEDS_SELECT;
else
bi->sql_flags &= ~BSQLF_CREATE_NEEDS_SELECT;
break;
case BSQL_UPPER_NEEDS_CAST:
if ( c->value_int )
bi->sql_flags |= BSQLF_UPPER_NEEDS_CAST;
else
bi->sql_flags &= ~BSQLF_UPPER_NEEDS_CAST;
break;
case BSQL_HAS_LDAPINFO_DN_RU:
bi->sql_flags |= BSQLF_DONTCHECK_LDAPINFO_DN_RU;
if ( c->value_int )
bi->sql_flags |= BSQLF_HAS_LDAPINFO_DN_RU;
else
bi->sql_flags &= ~BSQLF_HAS_LDAPINFO_DN_RU;
break;
case BSQL_FAIL_IF_NO_MAPPING:
if ( c->value_int )
bi->sql_flags |= BSQLF_FAIL_IF_NO_MAPPING;
else
bi->sql_flags &= ~BSQLF_FAIL_IF_NO_MAPPING;
break;
case BSQL_ALLOW_ORPHANS:
if ( c->value_int )
bi->sql_flags |= BSQLF_ALLOW_ORPHANS;
else
bi->sql_flags &= ~BSQLF_ALLOW_ORPHANS;
break;
case BSQL_SUBTREE_SHORTCUT:
if ( c->value_int )
bi->sql_flags |= BSQLF_USE_SUBTREE_SHORTCUT;
else
bi->sql_flags &= ~BSQLF_USE_SUBTREE_SHORTCUT;
break;
case BSQL_FETCH_ALL_ATTRS:
if ( c->value_int )
bi->sql_flags |= BSQLF_FETCH_ALL_ATTRS;
else
bi->sql_flags &= ~BSQLF_FETCH_ALL_ATTRS;
break;
case BSQL_CHECK_SCHEMA:
if ( c->value_int )
bi->sql_flags |= BSQLF_CHECK_SCHEMA;
else
bi->sql_flags &= ~BSQLF_CHECK_SCHEMA;
break;
case BSQL_AUTOCOMMIT:
if ( c->value_int )
bi->sql_flags |= BSQLF_AUTOCOMMIT_ON;
else
bi->sql_flags &= ~BSQLF_AUTOCOMMIT_ON;
break;
case BSQL_BASE_OBJECT:
if ( c->be->be_nsuffix == NULL ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s: suffix must be set", c->log );
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg );
rc = ARG_BAD_CONF;
break;
}
if ( bi->sql_baseObject ) {
Debug( LDAP_DEBUG_CONFIG,
"%s: "
"\"baseObject\" already provided (will be overwritten)\n",
c->log );
entry_free( bi->sql_baseObject );
}
if ( c->argc == 2 && !strcmp( c->argv[1], "TRUE" ))
c->argc = 1;
switch( c->argc ) {
case 1:
return create_baseObject( c->be, c->fname, c->lineno );
case 2:
rc = read_baseObject( c->be, c->argv[ 1 ] );
if ( rc == 0 ) {
ch_free( bi->sql_base_ob_file );
bi->sql_base_ob_file = c->value_string;
}
return rc;
default:
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s: trailing values in directive", c->log );
Debug( LDAP_DEBUG_ANY, "%s\n", c->cr_msg );
return 1;
}
break;
case BSQL_LAYER:
if ( backsql_api_config( bi, c->argv[ 1 ], c->argc - 2, &c->argv[ 2 ] ) )
{
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"%s: unable to load sql layer", c->log );
Debug( LDAP_DEBUG_ANY, "%s \"%s\"\n",
c->cr_msg, c->argv[1] );
return 1;
}
break;
case BSQL_ALIASING_KEYWORD:
if ( ! BER_BVISNULL( &bi->sql_aliasing ) ) {
ch_free( bi->sql_aliasing.bv_val );
}
ber_str2bv( c->argv[ 1 ], strlen( c->argv[ 1 ] ) + 1, 1,
&bi->sql_aliasing );
/* add a trailing space... */
bi->sql_aliasing.bv_val[ bi->sql_aliasing.bv_len - 1] = ' ';
break;
case BSQL_FETCH_ATTRS: {
char *str, *s, *next;
const char *delimstr = ",";
str = ch_strdup( c->argv[ 1 ] );
for ( s = ldap_pvt_strtok( str, delimstr, &next );
s != NULL;
s = ldap_pvt_strtok( NULL, delimstr, &next ) )
{
if ( strlen( s ) == 1 ) {
if ( *s == '*' ) {
bi->sql_flags |= BSQLF_FETCH_ALL_USERATTRS;
c->argv[ 1 ][ s - str ] = ',';
} else if ( *s == '+' ) {
bi->sql_flags |= BSQLF_FETCH_ALL_OPATTRS;
c->argv[ 1 ][ s - str ] = ',';
}
}
}
ch_free( str );
bi->sql_anlist = str2anlist( bi->sql_anlist, c->argv[ 1 ], delimstr );
if ( bi->sql_anlist == NULL ) {
return -1;
}
}
break;
}
return rc;
}
/*
* Read the entries specified in fname and merge the attributes
* to the user defined baseObject entry. Note that if we find any errors
* what so ever, we will discard the entire entries, print an
* error message and return.
*/
static int
read_baseObject(
BackendDB *be,
const char *fname )
{
backsql_info *bi = (backsql_info *)be->be_private;
LDIFFP *fp;
int rc = 0, lmax = 0, ldifrc;
unsigned long lineno = 0;
char *buf = NULL;
assert( fname != NULL );
fp = ldif_open( fname, "r" );
if ( fp == NULL ) {
Debug( LDAP_DEBUG_ANY,
"could not open back-sql baseObject "
"attr file \"%s\" - absolute path?\n",
fname );
perror( fname );
return LDAP_OTHER;
}
bi->sql_baseObject = entry_alloc();
if ( bi->sql_baseObject == NULL ) {
Debug( LDAP_DEBUG_ANY,
"read_baseObject_file: entry_alloc failed" );
ldif_close( fp );
return LDAP_NO_MEMORY;
}
bi->sql_baseObject->e_name = be->be_suffix[0];
bi->sql_baseObject->e_nname = be->be_nsuffix[0];
bi->sql_baseObject->e_attrs = NULL;
while (( ldifrc = ldif_read_record( fp, &lineno, &buf, &lmax )) > 0 ) {
Entry *e = str2entry( buf );
Attribute *a;
if( e == NULL ) {
fprintf( stderr, "back-sql baseObject: "
"could not parse entry (line=%lu)\n",
lineno );
rc = LDAP_OTHER;
break;
}
/* make sure the DN is the database's suffix */
if ( !be_issuffix( be, &e->e_nname ) ) {
fprintf( stderr,
"back-sql: invalid baseObject - "
"dn=\"%s\" (line=%lu)\n",
e->e_name.bv_val, lineno );
entry_free( e );
rc = LDAP_OTHER;
break;
}
/*
* we found a valid entry, so walk thru all the attributes in the
* entry, and add each attribute type and description to baseObject
*/
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
if ( attr_merge( bi->sql_baseObject, a->a_desc,
a->a_vals,
( a->a_nvals == a->a_vals ) ?
NULL : a->a_nvals ) )
{
rc = LDAP_OTHER;
break;
}
}
entry_free( e );
if ( rc ) {
break;
}
}
if ( ldifrc < 0 )
rc = LDAP_OTHER;
if ( rc ) {
entry_free( bi->sql_baseObject );
bi->sql_baseObject = NULL;
}
ch_free( buf );
ldif_close( fp );
Debug( LDAP_DEBUG_CONFIG, "back-sql baseObject file \"%s\" read.\n",
fname );
return rc;
}
static int
create_baseObject(
BackendDB *be,
const char *fname,
int lineno )
{
backsql_info *bi = (backsql_info *)be->be_private;
LDAPRDN rdn;
char *p;
int rc, iAVA;
char buf[1024];
snprintf( buf, sizeof(buf),
"dn: %s\n"
"objectClass: extensibleObject\n"
"description: builtin baseObject for back-sql\n"
"description: all entries mapped "
"in table \"ldap_entries\" "
"must have "
"\"" BACKSQL_BASEOBJECT_IDSTR "\" "
"in the \"parent\" column",
be->be_suffix[0].bv_val );
bi->sql_baseObject = str2entry( buf );
if ( bi->sql_baseObject == NULL ) {
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): "
"unable to parse baseObject entry\n",
fname, lineno );
return 1;
}
if ( BER_BVISEMPTY( &be->be_suffix[ 0 ] ) ) {
return 0;
}
rc = ldap_bv2rdn( &be->be_suffix[ 0 ], &rdn, (char **)&p,
LDAP_DN_FORMAT_LDAP );
if ( rc != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): unable to extract RDN " "from baseObject DN \"%s\" (%d: %s)\n",
fname, lineno, be->be_suffix[0].bv_val, rc,
ldap_err2string(rc) );
return 1;
}
for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
LDAPAVA *ava = rdn[ iAVA ];
AttributeDescription *ad = NULL;
slap_syntax_transform_func *transf = NULL;
struct berval bv = BER_BVNULL;
const char *text = NULL;
assert( ava != NULL );
rc = slap_bv2ad( &ava->la_attr, &ad, &text );
if ( rc != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): AttributeDescription of naming " "attribute #%d from baseObject " "DN \"%s\": %d: %s\n",
fname, lineno, iAVA, be->be_suffix[0].bv_val,
rc, ldap_err2string(rc) );
return 1;
}
transf = ad->ad_type->sat_syntax->ssyn_pretty;
if ( transf ) {
/*
* transform value by pretty function
* if value is empty, use empty_bv
*/
rc = ( *transf )( ad->ad_type->sat_syntax,
ava->la_value.bv_len
? &ava->la_value
: (struct berval *) &slap_empty_bv,
&bv, NULL );
if ( rc != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): " "prettying of attribute #%d " "from baseObject " "DN \"%s\" failed: %d: %s\n",
fname, lineno, iAVA,
be->be_suffix[0].bv_val, rc,
ldap_err2string(rc) );
return 1;
}
}
if ( !BER_BVISNULL( &bv ) ) {
if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) {
ber_memfree( ava->la_value.bv_val );
}
ava->la_value = bv;
ava->la_flags |= LDAP_AVA_FREE_VALUE;
}
attr_merge_normalize_one( bi->sql_baseObject,
ad, &ava->la_value, NULL );
}
ldap_rdnfree( rdn );
return 0;
}
int backsql_init_cf( BackendInfo *bi )
{
int rc;
bi->bi_cf_ocs = sqlocs;
rc = config_register_schema( sqlcfg, sqlocs );
if ( rc ) return rc;
return 0;
}

View file

@ -1,627 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Masarati.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati.
*/
#include "portable.h"
#include <stdio.h>
#include <sys/types.h>
#include "ac/string.h"
#include "slap.h"
#include "proto-sql.h"
typedef struct backsql_delete_attr_t {
Operation *op;
SlapReply *rs;
SQLHDBC dbh;
backsql_entryID *e_id;
} backsql_delete_attr_t;
static int
backsql_delete_attr_f( void *v_at, void *v_bda )
{
backsql_at_map_rec *at = (backsql_at_map_rec *)v_at;
backsql_delete_attr_t *bda = (backsql_delete_attr_t *)v_bda;
int rc;
rc = backsql_modify_delete_all_values( bda->op,
bda->rs, bda->dbh, bda->e_id, at );
if ( rc != LDAP_SUCCESS ) {
return BACKSQL_AVL_STOP;
}
return BACKSQL_AVL_CONTINUE;
}
static int
backsql_delete_all_attrs(
Operation *op,
SlapReply *rs,
SQLHDBC dbh,
backsql_entryID *eid )
{
backsql_delete_attr_t bda;
int rc;
bda.op = op;
bda.rs = rs;
bda.dbh = dbh;
bda.e_id = eid;
rc = ldap_avl_apply( eid->eid_oc->bom_attrs, backsql_delete_attr_f, &bda,
BACKSQL_AVL_STOP, AVL_INORDER );
if ( rc == BACKSQL_AVL_STOP ) {
return rs->sr_err;
}
return LDAP_SUCCESS;
}
static int
backsql_delete_int(
Operation *op,
SlapReply *rs,
SQLHDBC dbh,
SQLHSTMT *sthp,
backsql_entryID *eid,
Entry **ep )
{
backsql_info *bi = (backsql_info*)op->o_bd->be_private;
SQLHSTMT sth = SQL_NULL_HSTMT;
RETCODE rc;
int prc = LDAP_SUCCESS;
/* first parameter no */
SQLUSMALLINT pno = 0;
sth = *sthp;
/* ldap_avl_apply ... */
rs->sr_err = backsql_delete_all_attrs( op, rs, dbh, eid );
if ( rs->sr_err != LDAP_SUCCESS ) {
goto done;
}
rc = backsql_Prepare( dbh, &sth, eid->eid_oc->bom_delete_proc, 0 );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
"error preparing delete query\n" );
backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "SQL-backend error";
*ep = NULL;
goto done;
}
if ( BACKSQL_IS_DEL( eid->eid_oc->bom_expect_return ) ) {
pno = 1;
rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
"error binding output parameter for objectClass %s\n",
eid->eid_oc->bom_oc->soc_cname.bv_val );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
*ep = NULL;
goto done;
}
}
rc = backsql_BindParamID( sth, pno + 1, SQL_PARAM_INPUT, &eid->eid_keyval );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
"error binding keyval parameter for objectClass %s\n",
eid->eid_oc->bom_oc->soc_cname.bv_val );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
*ep = NULL;
goto done;
}
rc = SQLExecute( sth );
if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
rs->sr_err = LDAP_SUCCESS;
} else {
Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
"delete_proc execution failed (rc=%d, prc=%d)\n",
rc, prc );
if ( prc != LDAP_SUCCESS ) {
/* SQL procedure executed fine
* but returned an error */
rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
} else {
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
rs->sr_err = LDAP_OTHER;
}
SQLFreeStmt( sth, SQL_DROP );
goto done;
}
SQLFreeStmt( sth, SQL_DROP );
/* delete "auxiliary" objectClasses, if any... */
rc = backsql_Prepare( dbh, &sth, bi->sql_delobjclasses_stmt, 0 );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
"error preparing ldap_entry_objclasses delete query\n" );
backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "SQL-backend error";
*ep = NULL;
goto done;
}
rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &eid->eid_id );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
"error binding auxiliary objectClasses "
"entry ID parameter for objectClass %s\n",
eid->eid_oc->bom_oc->soc_cname.bv_val );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
*ep = NULL;
goto done;
}
rc = SQLExecute( sth );
switch ( rc ) {
case SQL_NO_DATA:
/* apparently there were no "auxiliary" objectClasses
* for this entry... */
case SQL_SUCCESS:
break;
default:
Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
"failed to delete record from ldap_entry_objclasses\n" );
backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "SQL-backend error";
*ep = NULL;
goto done;
}
SQLFreeStmt( sth, SQL_DROP );
/* delete entry... */
rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_stmt, 0 );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
"error preparing ldap_entries delete query\n" );
backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "SQL-backend error";
*ep = NULL;
goto done;
}
rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &eid->eid_id );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_delete(): "
"error binding entry ID parameter "
"for objectClass %s\n",
eid->eid_oc->bom_oc->soc_cname.bv_val );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
*ep = NULL;
goto done;
}
rc = SQLExecute( sth );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
"failed to delete record from ldap_entries\n" );
backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "SQL-backend error";
*ep = NULL;
goto done;
}
SQLFreeStmt( sth, SQL_DROP );
rs->sr_err = LDAP_SUCCESS;
*ep = NULL;
done:;
*sthp = sth;
return rs->sr_err;
}
typedef struct backsql_tree_delete_t {
Operation *btd_op;
int btd_rc;
backsql_entryID *btd_eid;
} backsql_tree_delete_t;
static int
backsql_tree_delete_search_cb( Operation *op, SlapReply *rs )
{
if ( rs->sr_type == REP_SEARCH ) {
backsql_tree_delete_t *btd;
backsql_entryID *eid;
btd = (backsql_tree_delete_t *)op->o_callback->sc_private;
if ( !access_allowed( btd->btd_op, rs->sr_entry,
slap_schema.si_ad_entry, NULL, ACL_WDEL, NULL )
|| !access_allowed( btd->btd_op, rs->sr_entry,
slap_schema.si_ad_children, NULL, ACL_WDEL, NULL ) )
{
btd->btd_rc = LDAP_INSUFFICIENT_ACCESS;
return rs->sr_err = LDAP_UNAVAILABLE;
}
assert( rs->sr_entry != NULL );
assert( rs->sr_entry->e_private != NULL );
eid = (backsql_entryID *)rs->sr_entry->e_private;
assert( eid->eid_oc != NULL );
if ( eid->eid_oc == NULL || eid->eid_oc->bom_delete_proc == NULL ) {
btd->btd_rc = LDAP_UNWILLING_TO_PERFORM;
return rs->sr_err = LDAP_UNAVAILABLE;
}
eid = backsql_entryID_dup( eid, op->o_tmpmemctx );
eid->eid_next = btd->btd_eid;
btd->btd_eid = eid;
}
return 0;
}
static int
backsql_tree_delete(
Operation *op,
SlapReply *rs,
SQLHDBC dbh,
SQLHSTMT *sthp )
{
Operation op2 = *op;
slap_callback sc = { 0 };
SlapReply rs2 = { REP_RESULT };
backsql_tree_delete_t btd = { 0 };
int rc;
/*
* - perform an internal subtree search as the rootdn
* - for each entry
* - check access
* - check objectClass and delete method(s)
* - for each entry
* - delete
* - if successful, commit
*/
op2.o_tag = LDAP_REQ_SEARCH;
op2.o_protocol = LDAP_VERSION3;
btd.btd_op = op;
sc.sc_private = &btd;
sc.sc_response = backsql_tree_delete_search_cb;
op2.o_callback = &sc;
op2.o_dn = op->o_bd->be_rootdn;
op2.o_ndn = op->o_bd->be_rootndn;
op2.o_managedsait = SLAP_CONTROL_CRITICAL;
op2.ors_scope = LDAP_SCOPE_SUBTREE;
op2.ors_deref = LDAP_DEREF_NEVER;
op2.ors_slimit = SLAP_NO_LIMIT;
op2.ors_tlimit = SLAP_NO_LIMIT;
op2.ors_filter = (Filter *)slap_filter_objectClass_pres;
op2.ors_filterstr = *slap_filterstr_objectClass_pres;
op2.ors_attrs = slap_anlist_all_attributes;
op2.ors_attrsonly = 0;
rc = op->o_bd->be_search( &op2, &rs2 );
if ( rc != LDAP_SUCCESS ) {
rc = rs->sr_err = btd.btd_rc;
rs->sr_text = "subtree delete not possible";
send_ldap_result( op, rs );
goto clean;
}
for ( ; btd.btd_eid != NULL;
btd.btd_eid = backsql_free_entryID( btd.btd_eid,
1, op->o_tmpmemctx ) )
{
Entry *e = (void *)0xbad;
rc = backsql_delete_int( op, rs, dbh, sthp, btd.btd_eid, &e );
if ( rc != LDAP_SUCCESS ) {
break;
}
}
clean:;
for ( ; btd.btd_eid != NULL;
btd.btd_eid = backsql_free_entryID( btd.btd_eid,
1, op->o_tmpmemctx ) )
;
return rc;
}
int
backsql_delete( Operation *op, SlapReply *rs )
{
SQLHDBC dbh = SQL_NULL_HDBC;
SQLHSTMT sth = SQL_NULL_HSTMT;
backsql_oc_map_rec *oc = NULL;
backsql_srch_info bsi = { 0 };
backsql_entryID e_id = { 0 };
Entry d = { 0 }, p = { 0 }, *e = NULL;
struct berval pdn = BER_BVNULL;
int manageDSAit = wants_manageDSAit( op );
Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry \"%s\"\n",
op->o_req_ndn.bv_val );
rs->sr_err = backsql_get_db_conn( op, &dbh );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
"could not get connection handle - exiting\n" );
rs->sr_text = ( rs->sr_err == LDAP_OTHER )
? "SQL-backend error" : NULL;
e = NULL;
goto done;
}
/*
* Get the entry
*/
bsi.bsi_e = &d;
rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
switch ( rs->sr_err ) {
case LDAP_SUCCESS:
break;
case LDAP_REFERRAL:
if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
{
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
rs->sr_matched = NULL;
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
break;
}
e = &d;
/* fallthru */
default:
Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
"could not retrieve deleteDN ID - no such entry\n" );
if ( !BER_BVISNULL( &d.e_nname ) ) {
/* FIXME: should always be true! */
e = &d;
} else {
e = NULL;
}
goto done;
}
if ( wants_assert( op ) &&
( test_filter( op, &d, get_assertion( op ) )
!= LDAP_COMPARE_TRUE ) )
{
rs->sr_err = LDAP_ASSERTION_FAILED;
e = &d;
goto done;
}
if ( !access_allowed( op, &d, slap_schema.si_ad_entry,
NULL, ACL_WDEL, NULL ) )
{
Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
"no write access to entry\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
e = &d;
goto done;
}
rs->sr_err = backsql_has_children( op, dbh, &op->o_req_ndn );
switch ( rs->sr_err ) {
case LDAP_COMPARE_FALSE:
rs->sr_err = LDAP_SUCCESS;
break;
case LDAP_COMPARE_TRUE:
#ifdef SLAP_CONTROL_X_TREE_DELETE
if ( wants_treeDelete( op ) ) {
rs->sr_err = LDAP_SUCCESS;
break;
}
#endif /* SLAP_CONTROL_X_TREE_DELETE */
Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
"entry \"%s\" has children\n",
op->o_req_dn.bv_val );
rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
rs->sr_text = "subordinate objects must be deleted first";
/* fallthru */
default:
e = &d;
goto done;
}
assert( bsi.bsi_base_id.eid_oc != NULL );
oc = bsi.bsi_base_id.eid_oc;
if ( oc->bom_delete_proc == NULL ) {
Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
"delete procedure is not defined "
"for this objectclass - aborting\n" );
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
rs->sr_text = "operation not permitted within namingContext";
e = NULL;
goto done;
}
/*
* Get the parent
*/
e_id = bsi.bsi_base_id;
memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
dnParent( &op->o_req_ndn, &pdn );
bsi.bsi_e = &p;
rs->sr_err = backsql_init_search( &bsi, &pdn,
LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs,
slap_anlist_no_attrs,
BACKSQL_ISF_GET_ENTRY );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
"could not retrieve deleteDN ID "
"- no such entry\n" );
e = &p;
goto done;
}
(void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
/* check parent for "children" acl */
if ( !access_allowed( op, &p, slap_schema.si_ad_children,
NULL, ACL_WDEL, NULL ) )
{
Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
"no write access to parent\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
e = &p;
goto done;
}
}
e = &d;
#ifdef SLAP_CONTROL_X_TREE_DELETE
if ( wants_treeDelete( op ) ) {
backsql_tree_delete( op, rs, dbh, &sth );
if ( rs->sr_err == LDAP_OTHER || rs->sr_err == LDAP_SUCCESS )
{
e = NULL;
}
} else
#endif /* SLAP_CONTROL_X_TREE_DELETE */
{
backsql_delete_int( op, rs, dbh, &sth, &e_id, &e );
}
/*
* Commit only if all operations succeed
*/
if ( sth != SQL_NULL_HSTMT ) {
SQLUSMALLINT CompletionType = SQL_ROLLBACK;
if ( rs->sr_err == LDAP_SUCCESS && !wants_noop( op ) ) {
assert( e == NULL );
CompletionType = SQL_COMMIT;
}
SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
}
done:;
if ( e != NULL ) {
if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL,
ACL_DISCLOSE, NULL ) )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
rs->sr_text = NULL;
rs->sr_matched = NULL;
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
}
}
if ( wants_noop( op ) && rs->sr_err == LDAP_SUCCESS ) {
rs->sr_err = LDAP_X_NO_OPERATION;
}
send_ldap_result( op, rs );
Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n" );
if ( !BER_BVISNULL( &e_id.eid_ndn ) ) {
(void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &d.e_nname ) ) {
backsql_entry_clean( op, &d );
}
if ( !BER_BVISNULL( &p.e_nname ) ) {
backsql_entry_clean( op, &p );
}
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
return rs->sr_err;
}

View file

@ -1,16 +0,0 @@
1) driver name comparison for MS SQL Server workaround is really kinda dirty
hack, but for now i don't know how to code it more carefully
2) another dirty hack: length of LONGVARCHAR and LONGVARBINARY fields is
currently set to MAX_ATTR_LEN. Maybe such fields must be handled with
SQLGetData() instead of SQLBindCol(), but it is said in documentation,
that it is guaranteed to work only when such column goes after last bound
column. Or should we get ALL columns with SQLGetData (then something like
_SQLFetchAsStrings() wrapper would do SQLGetData() for all columns)...
3) in some cases (particularly, when using OpenLink Generic ODBC driver with
MS SQL Server), it returns "Function sequence error" after all records are
fetched. I really don't know what it means, and after all
- it works with any other driver I tried
4) ldapsearch sometimes refuses to show some attributes ("NOT PRINTABLE" diags)
on Win32 (on linux everything's fine)
5) back-sql crashes on invalid filters (to be fixed ASAP)

View file

@ -1 +0,0 @@
The SQL backend is described in the slapd-sql(5) manual page.

View file

@ -1,86 +0,0 @@
PLEASE READ THIS WHOLE FILE AND CONCEPT, BECAUSE THEY COVER SEVERAL STICKY
ISSUES THAT YOU WILL PROBABLY STUMBLE ACROSS ANYWAY
1. Build
To build slapd with back-sql under Unix you need to build and install
iODBC 2.50.3 (later versions should probably work, but not earlier),
or unixODBC (you will have to change -liodbc to -lodbc then).
Then, at top of OpenLDAP source tree, run
"configure <other options you need> --enable-sql", then "make" -
this should build back-sql-enabled slapd, provided that you have iODBC/unixODBC
libraries and include files in include/library paths, "make install"...
In other words, follow installation procedure described in OpenLDAP
Administrators Guide, adding --enable-sql option to configure, and
having iODBC/unixODBC libraries installed an accessible by compiler.
Under Win32/MSVC++, I modified the workspace so that back-sql is built into
slapd automatically, since MS ODBC manager, odbc32.dll, is included in
standard library pack, and it does no bad even if you don't plan to use it.
I also could provide precompiled executables for those who don't have MSVC.
Note that Win32 port of OpenLDAP itself is experimental, and thus doesn't
provide very convenient build environment (yet).
2. Tune datasources and slapd.conf
Next, you need to define ODBC datasource with data you want to publish
with help of back-sql. Assuming that you have your data in some SQL-compliant
RDBMS, and have installed proper ODBC driver for this RDBMS, this is as simple
as adding a record into odbc.ini (for iODBC/unixODBC), or using ODBC wizard in
Control Panel (for odbc32).
Next, you need to add appropriate "database" record to your slapd.conf.
See samples provided in "back-sql/RDBMS_DEPENDENT/" subdirectory.
Several things worth noting about ODBC:
- "dbname" directive stands for ODBC datasource name (DSN),
not the name of your database in RDBMS context
- ODBC under Unix is not so common as under Windows, so you could have
problems with Unix drivers for your RDBMS. Visit http://www.openlinksw.com,
they provide a multitier solution which allows connecting to DBMSes on
different platforms, proxying and other connectivity and integration issues.
They also support iODBC, and have good free customer service through
newsserver (at news.openlinksw.com).
Also worth noting are: ODBC-ODBC bridge by EasySoft (which was claimed
by several people to be far more effective and stable than OpenLink),
OpenRDA package etc.
- be careful defining RDBMS connection parameters, you'll probably need only
"dbname" directive - all the rest can be defined in datasource. Every other
directive is used to override value stored in datasource definition.
Maybe you will want to use dbuser/dbpasswd to override credentials defined in datasource
- full list of configuration directives supported is available in file "guide",
you may also analyze output of 'slapd -d 5' to find out some useful
directives for redefining default queries
3. Creating and using back-sql metatables
Read the file "concept" to understand, what metainformation you need to add,
and what for... ;)
See SQL scripts and slapd.conf files in samples directory.
Find subdirectory in "rdbms_depend/" corresponding to your RDBMS (Oracle,
MS SQL Server and mySQL are listed there currently), or copy and edit
any of these to conform to SQL dialect of your RDBMS (please be sure to send
me scripts and notes for new RDBMSes ;).
Execute "backsql_create.sql" from that subdirectory (or edited one),
so that the tables it creates appear in the same
context with the data you want to export through LDAP (under same DB/user,
or whatever is needed in RDBMS you use). You can use something like
"mysql < xxx.sql" for mySQL, Query Analyzer+Open query file for MS SQL,
sqlplus and "@xxx.sql" for Oracle.
You may well want to try it with test data first, and see how metatables
are used. Create test data and metadata by running testdb_create.sql,
testdb_data.sql, and testdb_metadata.sql scripts (again, adopted for your
RDBMS, and in the same context as metatables you created before), and
tune slapd.conf to use your test DB.
4. Testing
To diagnose back-sql, run slapd with debug level TRACE ("slapd -d 5" will go).
Then, use some LDAP client to query corresponding subtree (for test database,
you could for instance search one level from "o=sql,c=RU"). I personally used
saucer, which is included in OpenLDAP package (it builds automatically under
Unix/GNU configure and for MSVC I added appropriate project to workspace).
And also Java LDAP browser-editor (see link somewhere on OpenLDAP site) to
test ADD/DELETE/MODIFY operations on Oracle and MS SQL.
See file "platforms" if you encounter connection problems - you may find
a hint for your RDBMS or OS there. If you are stuck - please contact me at
mit@openldap.org, or (better) post an issue through OpenLDAP's Issue Tracking
System (see http:/www.openldap.org/its).

View file

@ -1,8 +0,0 @@
Platforms and configurations it has been tested on:
General:
- ODBC managers: iODBC,unixODBC under unixes, odbc32.dll under Win32 family
- OSes: Linux/glibc, FreeBSD, OpenBSD, Solaris 2.6, Win98, WinNT, Win2000 server
- RDBMSes: Oracle 7/8/8i, MS SQL Server 6.5/7, mySQL
- access suites: OpenLink DAS, EasySoft OOB, various win32 drivers

View file

@ -1,12 +0,0 @@
1) must add alias handling
2) [sizelimit moved to frontend]
must set time limit when preparing all queries, and check size limit
3) there was expressed a need to have access to IP in while constructing
queries, to have response alter in accordance to client IP. Will add
preprocessor for values in metatables, which would substitute things
like "$IP$".
4) must handle NOT filters (see ITS#2652)
5) must map attribute types and syntaxes between LDAP and SQL types (e.g.
use BLOBs for octet streams)
6) must define another mech to add auxiliary objectClass to all entries
according to ldap_at_mappings (ldap_entry_objclasses has limitations)

File diff suppressed because it is too large Load diff

View file

@ -1,661 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Masarati.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati.
*/
#include "portable.h"
#include <stdio.h>
#include <sys/types.h>
#include "ac/string.h"
#include "slap.h"
#include "slap-config.h"
#include "proto-sql.h"
int
sql_back_initialize(
BackendInfo *bi )
{
static char *controls[] = {
LDAP_CONTROL_ASSERT,
LDAP_CONTROL_MANAGEDSAIT,
LDAP_CONTROL_NOOP,
#ifdef SLAP_CONTROL_X_TREE_DELETE
SLAP_CONTROL_X_TREE_DELETE,
#endif /* SLAP_CONTROL_X_TREE_DELETE */
#ifndef BACKSQL_ARBITRARY_KEY
LDAP_CONTROL_PAGEDRESULTS,
#endif /* ! BACKSQL_ARBITRARY_KEY */
NULL
};
int rc;
bi->bi_controls = controls;
bi->bi_flags |=
#if 0
SLAP_BFLAG_INCREMENT |
#endif
SLAP_BFLAG_REFERRALS;
Debug( LDAP_DEBUG_TRACE,"==>sql_back_initialize()\n" );
bi->bi_db_init = backsql_db_init;
bi->bi_db_config = config_generic_wrapper;
bi->bi_db_open = backsql_db_open;
bi->bi_db_close = backsql_db_close;
bi->bi_db_destroy = backsql_db_destroy;
bi->bi_op_abandon = 0;
bi->bi_op_compare = backsql_compare;
bi->bi_op_bind = backsql_bind;
bi->bi_op_unbind = 0;
bi->bi_op_search = backsql_search;
bi->bi_op_modify = backsql_modify;
bi->bi_op_modrdn = backsql_modrdn;
bi->bi_op_add = backsql_add;
bi->bi_op_delete = backsql_delete;
bi->bi_chk_referrals = 0;
bi->bi_operational = backsql_operational;
bi->bi_entry_get_rw = backsql_entry_get;
bi->bi_entry_release_rw = backsql_entry_release;
bi->bi_connection_init = 0;
rc = backsql_init_cf( bi );
Debug( LDAP_DEBUG_TRACE,"<==sql_back_initialize()\n" );
return rc;
}
int
backsql_destroy(
BackendInfo *bi )
{
Debug( LDAP_DEBUG_TRACE, "==>backsql_destroy()\n" );
Debug( LDAP_DEBUG_TRACE, "<==backsql_destroy()\n" );
return 0;
}
int
backsql_db_init(
BackendDB *bd,
ConfigReply *cr )
{
backsql_info *bi;
int rc = 0;
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_init()\n" );
bi = (backsql_info *)ch_calloc( 1, sizeof( backsql_info ) );
ldap_pvt_thread_mutex_init( &bi->sql_dbconn_mutex );
ldap_pvt_thread_mutex_init( &bi->sql_schema_mutex );
if ( backsql_init_db_env( bi ) != SQL_SUCCESS ) {
rc = -1;
}
bd->be_private = bi;
bd->be_cf_ocs = bd->bd_info->bi_cf_ocs;
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_init()\n" );
return rc;
}
int
backsql_db_destroy(
BackendDB *bd,
ConfigReply *cr )
{
backsql_info *bi = (backsql_info*)bd->be_private;
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_destroy()\n" );
backsql_free_db_env( bi );
ldap_pvt_thread_mutex_destroy( &bi->sql_dbconn_mutex );
backsql_destroy_schema_map( bi );
ldap_pvt_thread_mutex_destroy( &bi->sql_schema_mutex );
if ( bi->sql_dbname ) {
ch_free( bi->sql_dbname );
}
if ( bi->sql_dbuser ) {
ch_free( bi->sql_dbuser );
}
if ( bi->sql_dbpasswd ) {
ch_free( bi->sql_dbpasswd );
}
if ( bi->sql_dbhost ) {
ch_free( bi->sql_dbhost );
}
if ( bi->sql_upper_func.bv_val ) {
ch_free( bi->sql_upper_func.bv_val );
ch_free( bi->sql_upper_func_open.bv_val );
ch_free( bi->sql_upper_func_close.bv_val );
}
if ( bi->sql_concat_func ) {
ber_bvarray_free( bi->sql_concat_func );
}
if ( !BER_BVISNULL( &bi->sql_strcast_func ) ) {
ch_free( bi->sql_strcast_func.bv_val );
}
if ( !BER_BVISNULL( &bi->sql_children_cond ) ) {
ch_free( bi->sql_children_cond.bv_val );
}
if ( !BER_BVISNULL( &bi->sql_dn_match_cond ) ) {
ch_free( bi->sql_dn_match_cond.bv_val );
}
if ( !BER_BVISNULL( &bi->sql_subtree_cond ) ) {
ch_free( bi->sql_subtree_cond.bv_val );
}
if ( !BER_BVISNULL( &bi->sql_dn_oc_aliasing ) ) {
ch_free( bi->sql_dn_oc_aliasing.bv_val );
}
if ( bi->sql_oc_query ) {
ch_free( bi->sql_oc_query );
}
if ( bi->sql_at_query ) {
ch_free( bi->sql_at_query );
}
if ( bi->sql_id_query ) {
ch_free( bi->sql_id_query );
}
if ( bi->sql_has_children_query ) {
ch_free( bi->sql_has_children_query );
}
if ( bi->sql_insentry_stmt ) {
ch_free( bi->sql_insentry_stmt );
}
if ( bi->sql_delentry_stmt ) {
ch_free( bi->sql_delentry_stmt );
}
if ( bi->sql_renentry_stmt ) {
ch_free( bi->sql_renentry_stmt );
}
if ( bi->sql_delobjclasses_stmt ) {
ch_free( bi->sql_delobjclasses_stmt );
}
if ( !BER_BVISNULL( &bi->sql_aliasing ) ) {
ch_free( bi->sql_aliasing.bv_val );
}
if ( !BER_BVISNULL( &bi->sql_aliasing_quote ) ) {
ch_free( bi->sql_aliasing_quote.bv_val );
}
if ( bi->sql_anlist ) {
int i;
for ( i = 0; !BER_BVISNULL( &bi->sql_anlist[ i ].an_name ); i++ )
{
ch_free( bi->sql_anlist[ i ].an_name.bv_val );
}
ch_free( bi->sql_anlist );
}
if ( bi->sql_baseObject ) {
entry_free( bi->sql_baseObject );
}
ch_free( bi );
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_destroy()\n" );
return 0;
}
int
backsql_db_open(
BackendDB *bd,
ConfigReply *cr )
{
backsql_info *bi = (backsql_info*)bd->be_private;
struct berbuf bb = BB_NULL;
Connection conn = { 0 };
OperationBuffer opbuf;
Operation* op;
SQLHDBC dbh = SQL_NULL_HDBC;
void *thrctx = ldap_pvt_thread_pool_context();
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): "
"testing RDBMS connection\n" );
if ( bi->sql_dbname == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"datasource name not specified "
"(use \"dbname\" directive in slapd.conf)\n" );
return 1;
}
if ( bi->sql_concat_func == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"concat func not specified (use \"concat_pattern\" "
"directive in slapd.conf)\n" );
if ( backsql_split_pattern( backsql_def_concat_func,
&bi->sql_concat_func, 2 ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"unable to parse pattern \"%s\"",
backsql_def_concat_func );
return 1;
}
}
/*
* see back-sql.h for default values
*/
if ( BER_BVISNULL( &bi->sql_aliasing ) ) {
ber_str2bv( BACKSQL_ALIASING,
STRLENOF( BACKSQL_ALIASING ),
1, &bi->sql_aliasing );
}
if ( BER_BVISNULL( &bi->sql_aliasing_quote ) ) {
ber_str2bv( BACKSQL_ALIASING_QUOTE,
STRLENOF( BACKSQL_ALIASING_QUOTE ),
1, &bi->sql_aliasing_quote );
}
/*
* Prepare cast string as required
*/
if ( bi->sql_upper_func.bv_val ) {
char buf[1024];
if ( BACKSQL_UPPER_NEEDS_CAST( bi ) ) {
snprintf( buf, sizeof( buf ),
"%s(cast (" /* ? as varchar(%d))) */ ,
bi->sql_upper_func.bv_val );
ber_str2bv( buf, 0, 1, &bi->sql_upper_func_open );
snprintf( buf, sizeof( buf ),
/* (cast(? */ " as varchar(%d)))",
BACKSQL_MAX_DN_LEN );
ber_str2bv( buf, 0, 1, &bi->sql_upper_func_close );
} else {
snprintf( buf, sizeof( buf ), "%s(" /* ?) */ ,
bi->sql_upper_func.bv_val );
ber_str2bv( buf, 0, 1, &bi->sql_upper_func_open );
ber_str2bv( /* (? */ ")", 0, 1, &bi->sql_upper_func_close );
}
}
/* normalize filter values only if necessary */
bi->sql_caseIgnoreMatch = mr_find( "caseIgnoreMatch" );
assert( bi->sql_caseIgnoreMatch != NULL );
bi->sql_telephoneNumberMatch = mr_find( "telephoneNumberMatch" );
assert( bi->sql_telephoneNumberMatch != NULL );
if ( bi->sql_dbuser == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"user name not specified "
"(use \"dbuser\" directive in slapd.conf)\n" );
return 1;
}
if ( BER_BVISNULL( &bi->sql_subtree_cond ) ) {
/*
* Prepare concat function for subtree search condition
*/
struct berval concat;
struct berval values[] = {
BER_BVC( "'%'" ),
BER_BVC( "?" ),
BER_BVNULL
};
struct berbuf bb = BB_NULL;
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"subtree search SQL condition not specified "
"(use \"subtree_cond\" directive in slapd.conf); "
"preparing default\n" );
if ( backsql_prepare_pattern( bi->sql_concat_func, values,
&concat ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"unable to prepare CONCAT pattern for subtree search" );
return 1;
}
if ( bi->sql_upper_func.bv_val ) {
/*
* UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%',?))
*/
backsql_strfcat_x( &bb, NULL, "blbbb",
&bi->sql_upper_func,
(ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ),
"(ldap_entries.dn) LIKE ",
&bi->sql_upper_func_open,
&concat,
&bi->sql_upper_func_close );
} else {
/*
* ldap_entries.dn LIKE CONCAT('%',?)
*/
backsql_strfcat_x( &bb, NULL, "lb",
(ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ),
"ldap_entries.dn LIKE ",
&concat );
}
ch_free( concat.bv_val );
bi->sql_subtree_cond = bb.bb_val;
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting \"%s\" as default \"subtree_cond\"\n",
bi->sql_subtree_cond.bv_val );
}
if ( bi->sql_children_cond.bv_val == NULL ) {
/*
* Prepare concat function for children search condition
*/
struct berval concat;
struct berval values[] = {
BER_BVC( "'%,'" ),
BER_BVC( "?" ),
BER_BVNULL
};
struct berbuf bb = BB_NULL;
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"children search SQL condition not specified "
"(use \"children_cond\" directive in slapd.conf); "
"preparing default\n" );
if ( backsql_prepare_pattern( bi->sql_concat_func, values,
&concat ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"unable to prepare CONCAT pattern for children search" );
return 1;
}
if ( bi->sql_upper_func.bv_val ) {
/*
* UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?))
*/
backsql_strfcat_x( &bb, NULL, "blbbb",
&bi->sql_upper_func,
(ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ),
"(ldap_entries.dn) LIKE ",
&bi->sql_upper_func_open,
&concat,
&bi->sql_upper_func_close );
} else {
/*
* ldap_entries.dn LIKE CONCAT('%,',?)
*/
backsql_strfcat_x( &bb, NULL, "lb",
(ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ),
"ldap_entries.dn LIKE ",
&concat );
}
ch_free( concat.bv_val );
bi->sql_children_cond = bb.bb_val;
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting \"%s\" as default \"children_cond\"\n",
bi->sql_children_cond.bv_val );
}
if ( bi->sql_dn_match_cond.bv_val == NULL ) {
/*
* Prepare concat function for dn match search condition
*/
struct berbuf bb = BB_NULL;
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"DN match search SQL condition not specified "
"(use \"dn_match_cond\" directive in slapd.conf); "
"preparing default\n" );
if ( bi->sql_upper_func.bv_val ) {
/*
* UPPER(ldap_entries.dn)=?
*/
backsql_strfcat_x( &bb, NULL, "blbcb",
&bi->sql_upper_func,
(ber_len_t)STRLENOF( "(ldap_entries.dn)=" ),
"(ldap_entries.dn)=",
&bi->sql_upper_func_open,
'?',
&bi->sql_upper_func_close );
} else {
/*
* ldap_entries.dn=?
*/
backsql_strfcat_x( &bb, NULL, "l",
(ber_len_t)STRLENOF( "ldap_entries.dn=?" ),
"ldap_entries.dn=?" );
}
bi->sql_dn_match_cond = bb.bb_val;
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting \"%s\" as default \"dn_match_cond\"\n",
bi->sql_dn_match_cond.bv_val );
}
if ( bi->sql_oc_query == NULL ) {
if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
bi->sql_oc_query =
ch_strdup( backsql_def_needs_select_oc_query );
} else {
bi->sql_oc_query = ch_strdup( backsql_def_oc_query );
}
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"objectclass mapping SQL statement not specified "
"(use \"oc_query\" directive in slapd.conf)\n" );
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting \"%s\" by default\n", bi->sql_oc_query );
}
if ( bi->sql_at_query == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"attribute mapping SQL statement not specified "
"(use \"at_query\" directive in slapd.conf)\n" );
Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting \"%s\" by default\n",
backsql_def_at_query );
bi->sql_at_query = ch_strdup( backsql_def_at_query );
}
if ( bi->sql_insentry_stmt == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"entry insertion SQL statement not specified "
"(use \"insentry_stmt\" directive in slapd.conf)\n" );
Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting \"%s\" by default\n",
backsql_def_insentry_stmt );
bi->sql_insentry_stmt = ch_strdup( backsql_def_insentry_stmt );
}
if ( bi->sql_delentry_stmt == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"entry deletion SQL statement not specified "
"(use \"delentry_stmt\" directive in slapd.conf)\n" );
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting \"%s\" by default\n",
backsql_def_delentry_stmt );
bi->sql_delentry_stmt = ch_strdup( backsql_def_delentry_stmt );
}
if ( bi->sql_renentry_stmt == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"entry deletion SQL statement not specified "
"(use \"renentry_stmt\" directive in slapd.conf)\n" );
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting \"%s\" by default\n",
backsql_def_renentry_stmt );
bi->sql_renentry_stmt = ch_strdup( backsql_def_renentry_stmt );
}
if ( bi->sql_delobjclasses_stmt == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"objclasses deletion SQL statement not specified "
"(use \"delobjclasses_stmt\" directive in slapd.conf)\n" );
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"setting \"%s\" by default\n",
backsql_def_delobjclasses_stmt );
bi->sql_delobjclasses_stmt = ch_strdup( backsql_def_delobjclasses_stmt );
}
/* This should just be to force schema loading */
connection_fake_init2( &conn, &opbuf, thrctx, 0 );
op = &opbuf.ob_op;
op->o_bd = bd;
if ( backsql_get_db_conn( op, &dbh ) != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"connection failed, exiting\n" );
return 1;
}
if ( backsql_load_schema_map( bi, dbh ) != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"schema mapping failed, exiting\n" );
return 1;
}
if ( backsql_free_db_conn( op, dbh ) != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"connection free failed\n" );
}
if ( !BACKSQL_SCHEMA_LOADED( bi ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
"test failed, schema map not loaded - exiting\n" );
return 1;
}
/*
* Prepare ID selection query
*/
if ( bi->sql_id_query == NULL ) {
/* no custom id_query provided */
if ( bi->sql_upper_func.bv_val == NULL ) {
backsql_strcat_x( &bb, NULL, backsql_id_query, "dn=?", NULL );
} else {
if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
backsql_strcat_x( &bb, NULL, backsql_id_query,
"dn_ru=?", NULL );
} else {
if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
backsql_strfcat_x( &bb, NULL, "sbl",
backsql_id_query,
&bi->sql_upper_func,
(ber_len_t)STRLENOF( "(dn)=?" ), "(dn)=?" );
} else {
backsql_strfcat_x( &bb, NULL, "sblbcb",
backsql_id_query,
&bi->sql_upper_func,
(ber_len_t)STRLENOF( "(dn)=" ), "(dn)=",
&bi->sql_upper_func_open,
'?',
&bi->sql_upper_func_close );
}
}
}
bi->sql_id_query = bb.bb_val.bv_val;
}
/*
* Prepare children count query
*/
BER_BVZERO( &bb.bb_val );
bb.bb_len = 0;
backsql_strfcat_x( &bb, NULL, "sbsb",
"SELECT COUNT(distinct subordinates.id) "
"FROM ldap_entries,ldap_entries ",
&bi->sql_aliasing, "subordinates "
"WHERE subordinates.parent=ldap_entries.id AND ",
&bi->sql_dn_match_cond );
bi->sql_has_children_query = bb.bb_val.bv_val;
/*
* Prepare DN and objectClass aliasing bit of query
*/
BER_BVZERO( &bb.bb_val );
bb.bb_len = 0;
backsql_strfcat_x( &bb, NULL, "sbbsbsbbsb",
" ", &bi->sql_aliasing, &bi->sql_aliasing_quote,
"objectClass", &bi->sql_aliasing_quote,
",ldap_entries.dn ", &bi->sql_aliasing,
&bi->sql_aliasing_quote, "dn", &bi->sql_aliasing_quote );
bi->sql_dn_oc_aliasing = bb.bb_val;
/* should never happen! */
assert( bd->be_nsuffix != NULL );
if ( BER_BVISNULL( &bd->be_nsuffix[ 1 ] ) ) {
/* enable if only one suffix is defined */
bi->sql_flags |= BSQLF_USE_SUBTREE_SHORTCUT;
}
bi->sql_flags |= BSQLF_CHECK_SCHEMA;
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_open(): "
"test succeeded, schema map loaded\n" );
return 0;
}
int
backsql_db_close(
BackendDB *bd,
ConfigReply *cr )
{
backsql_info *bi = (backsql_info*)bd->be_private;
Debug( LDAP_DEBUG_TRACE, "==>backsql_db_close()\n" );
backsql_conn_destroy( bi );
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_close()\n" );
return 0;
}
#if SLAPD_SQL == SLAPD_MOD_DYNAMIC
/* conditionally define the init_module() function */
SLAP_BACKEND_INIT_MODULE( sql )
#endif /* SLAPD_SQL == SLAPD_MOD_DYNAMIC */

View file

@ -1,212 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Masarati.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati.
*/
#include "portable.h"
#include <stdio.h>
#include <sys/types.h>
#include "ac/string.h"
#include "slap.h"
#include "proto-sql.h"
int
backsql_modify( Operation *op, SlapReply *rs )
{
backsql_info *bi = (backsql_info*)op->o_bd->be_private;
SQLHDBC dbh = SQL_NULL_HDBC;
backsql_oc_map_rec *oc = NULL;
backsql_srch_info bsi = { 0 };
Entry m = { 0 }, *e = NULL;
int manageDSAit = wants_manageDSAit( op );
SQLUSMALLINT CompletionType = SQL_ROLLBACK;
/*
* FIXME: in case part of the operation cannot be performed
* (missing mapping, SQL write fails or so) the entire operation
* should be rolled-back
*/
Debug( LDAP_DEBUG_TRACE, "==>backsql_modify(): modifying entry \"%s\"\n",
op->o_req_ndn.bv_val );
rs->sr_err = backsql_get_db_conn( op, &dbh );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modify(): "
"could not get connection handle - exiting\n" );
/*
* FIXME: we don't want to send back
* excessively detailed messages
*/
rs->sr_text = ( rs->sr_err == LDAP_OTHER )
? "SQL-backend error" : NULL;
goto done;
}
bsi.bsi_e = &m;
rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs,
slap_anlist_all_attributes,
( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
switch ( rs->sr_err ) {
case LDAP_SUCCESS:
break;
case LDAP_REFERRAL:
if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
{
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
rs->sr_matched = NULL;
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
break;
}
e = &m;
/* fallthru */
default:
Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
"could not retrieve modifyDN ID - no such entry\n" );
if ( !BER_BVISNULL( &m.e_nname ) ) {
/* FIXME: should always be true! */
e = &m;
} else {
e = NULL;
}
goto done;
}
Debug( LDAP_DEBUG_TRACE, " backsql_modify(): "
"modifying entry \"%s\" (id=" BACKSQL_IDFMT ")\n",
bsi.bsi_base_id.eid_dn.bv_val,
BACKSQL_IDARG(bsi.bsi_base_id.eid_id) );
if ( wants_assert( op ) &&
( test_filter( op, &m, get_assertion( op ) )
!= LDAP_COMPARE_TRUE ))
{
rs->sr_err = LDAP_ASSERTION_FAILED;
e = &m;
goto done;
}
slap_mods_opattrs( op, &op->orm_modlist, 1 );
assert( bsi.bsi_base_id.eid_oc != NULL );
oc = bsi.bsi_base_id.eid_oc;
if ( !acl_check_modlist( op, &m, op->orm_modlist ) ) {
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
e = &m;
goto done;
}
rs->sr_err = backsql_modify_internal( op, rs, dbh, oc,
&bsi.bsi_base_id, op->orm_modlist );
if ( rs->sr_err != LDAP_SUCCESS ) {
e = &m;
goto do_transact;
}
if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
backsql_entry_clean( op, &m );
bsi.bsi_e = &m;
rs->sr_err = backsql_id2entry( &bsi, &bsi.bsi_base_id );
if ( rs->sr_err != LDAP_SUCCESS ) {
e = &m;
goto do_transact;
}
rs->sr_err = entry_schema_check( op, &m, 0, 0, NULL,
&rs->sr_text, textbuf, sizeof( textbuf ) );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modify(\"%s\"): "
"entry failed schema check -- aborting\n",
m.e_name.bv_val );
e = NULL;
goto do_transact;
}
}
do_transact:;
/*
* Commit only if all operations succeed
*/
if ( rs->sr_err == LDAP_SUCCESS && !wants_noop( op ) ) {
assert( e == NULL );
CompletionType = SQL_COMMIT;
}
SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
done:;
if ( e != NULL ) {
if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL,
ACL_DISCLOSE, NULL ) )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
rs->sr_text = NULL;
rs->sr_matched = NULL;
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
}
}
if ( wants_noop( op ) && rs->sr_err == LDAP_SUCCESS ) {
rs->sr_err = LDAP_X_NO_OPERATION;
}
send_ldap_result( op, rs );
slap_graduate_commit_csn( op );
if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
(void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &m.e_nname ) ) {
backsql_entry_clean( op, &m );
}
if ( bsi.bsi_attrs != NULL ) {
op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx );
}
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n" );
return rs->sr_err;
}

View file

@ -1,510 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Masarati.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati.
*/
#include "portable.h"
#include <stdio.h>
#include <sys/types.h>
#include "ac/string.h"
#include "slap.h"
#include "proto-sql.h"
int
backsql_modrdn( Operation *op, SlapReply *rs )
{
backsql_info *bi = (backsql_info*)op->o_bd->be_private;
SQLHDBC dbh = SQL_NULL_HDBC;
SQLHSTMT sth = SQL_NULL_HSTMT;
RETCODE rc;
backsql_entryID e_id = BACKSQL_ENTRYID_INIT,
n_id = BACKSQL_ENTRYID_INIT;
backsql_srch_info bsi = { 0 };
backsql_oc_map_rec *oc = NULL;
struct berval pdn = BER_BVNULL, pndn = BER_BVNULL,
*new_pdn = NULL, *new_npdn = NULL,
realnew_dn = BER_BVNULL;
Entry r = { 0 },
p = { 0 },
n = { 0 },
*e = NULL;
int manageDSAit = wants_manageDSAit( op );
struct berval *newSuperior = op->oq_modrdn.rs_newSup;
Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry \"%s\", "
"newrdn=\"%s\", newSuperior=\"%s\"\n",
op->o_req_dn.bv_val, op->oq_modrdn.rs_newrdn.bv_val,
newSuperior ? newSuperior->bv_val : "(NULL)" );
rs->sr_err = backsql_get_db_conn( op, &dbh );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
"could not get connection handle - exiting\n" );
rs->sr_text = ( rs->sr_err == LDAP_OTHER )
? "SQL-backend error" : NULL;
e = NULL;
goto done;
}
bsi.bsi_e = &r;
rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs,
slap_anlist_all_attributes,
( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
switch ( rs->sr_err ) {
case LDAP_SUCCESS:
break;
case LDAP_REFERRAL:
if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
{
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
rs->sr_matched = NULL;
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
break;
}
e = &r;
/* fallthru */
default:
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
"could not retrieve modrdnDN ID - no such entry\n" );
if ( !BER_BVISNULL( &r.e_nname ) ) {
/* FIXME: should always be true! */
e = &r;
} else {
e = NULL;
}
goto done;
}
Debug( LDAP_DEBUG_TRACE,
" backsql_modrdn(): entry id=" BACKSQL_IDFMT "\n",
BACKSQL_IDARG(e_id.eid_id) );
if ( wants_assert( op ) &&
( test_filter( op, &r, get_assertion( op ) )
!= LDAP_COMPARE_TRUE ) )
{
rs->sr_err = LDAP_ASSERTION_FAILED;
e = &r;
goto done;
}
if ( backsql_has_children( op, dbh, &op->o_req_ndn ) == LDAP_COMPARE_TRUE ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
"entry \"%s\" has children\n",
op->o_req_dn.bv_val );
rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
rs->sr_text = "subtree rename not supported";
e = &r;
goto done;
}
/*
* Check for entry access to target
*/
if ( !access_allowed( op, &r, slap_schema.si_ad_entry,
NULL, ACL_WRITE, NULL ) ) {
Debug( LDAP_DEBUG_TRACE, " no access to entry\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
goto done;
}
dnParent( &op->o_req_dn, &pdn );
dnParent( &op->o_req_ndn, &pndn );
/*
* namingContext "" is not supported
*/
if ( BER_BVISEMPTY( &pdn ) ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
"parent is \"\" - aborting\n" );
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
rs->sr_text = "not allowed within namingContext";
e = NULL;
goto done;
}
/*
* Check for children access to parent
*/
bsi.bsi_e = &p;
e_id = bsi.bsi_base_id;
memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
rs->sr_err = backsql_init_search( &bsi, &pndn,
LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs,
slap_anlist_all_attributes,
BACKSQL_ISF_GET_ENTRY );
Debug( LDAP_DEBUG_TRACE,
" backsql_modrdn(): old parent entry id is " BACKSQL_IDFMT "\n",
BACKSQL_IDARG(bsi.bsi_base_id.eid_id) );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
"could not retrieve renameDN ID - no such entry\n" );
e = &p;
goto done;
}
if ( !access_allowed( op, &p, slap_schema.si_ad_children, NULL,
newSuperior ? ACL_WDEL : ACL_WRITE, NULL ) )
{
Debug( LDAP_DEBUG_TRACE, " no access to parent\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
goto done;
}
if ( newSuperior ) {
(void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
/*
* namingContext "" is not supported
*/
if ( BER_BVISEMPTY( newSuperior ) ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
"newSuperior is \"\" - aborting\n" );
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
rs->sr_text = "not allowed within namingContext";
e = NULL;
goto done;
}
new_pdn = newSuperior;
new_npdn = op->oq_modrdn.rs_nnewSup;
/*
* Check for children access to new parent
*/
bsi.bsi_e = &n;
rs->sr_err = backsql_init_search( &bsi, new_npdn,
LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs,
slap_anlist_all_attributes,
( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
"could not retrieve renameDN ID - no such entry\n" );
e = &n;
goto done;
}
n_id = bsi.bsi_base_id;
Debug( LDAP_DEBUG_TRACE,
" backsql_modrdn(): new parent entry id=" BACKSQL_IDFMT "\n",
BACKSQL_IDARG(n_id.eid_id) );
if ( !access_allowed( op, &n, slap_schema.si_ad_children,
NULL, ACL_WADD, NULL ) ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
"no access to new parent \"%s\"\n",
new_pdn->bv_val );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
e = &n;
goto done;
}
} else {
n_id = bsi.bsi_base_id;
new_pdn = &pdn;
new_npdn = &pndn;
}
memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
if ( newSuperior && dn_match( &pndn, new_npdn ) ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
"newSuperior is equal to old parent - ignored\n" );
newSuperior = NULL;
}
if ( newSuperior && dn_match( &op->o_req_ndn, new_npdn ) ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
"newSuperior is equal to entry being moved "
"- aborting\n" );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "newSuperior is equal to old DN";
e = &r;
goto done;
}
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): new entry dn is \"%s\"\n",
op->orr_newDN.bv_val );
realnew_dn = op->orr_newDN;
if ( backsql_api_dn2odbc( op, rs, &realnew_dn ) ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(\"%s\"): "
"backsql_api_dn2odbc(\"%s\") failed\n",
op->o_req_dn.bv_val, realnew_dn.bv_val );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
e = NULL;
goto done;
}
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
"executing renentry_stmt\n" );
rc = backsql_Prepare( dbh, &sth, bi->sql_renentry_stmt, 0 );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_modrdn(): "
"error preparing renentry_stmt\n" );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
e = NULL;
goto done;
}
rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realnew_dn );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_modrdn(): "
"error binding DN parameter for objectClass %s\n",
oc->bom_oc->soc_cname.bv_val );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
e = NULL;
goto done;
}
rc = backsql_BindParamID( sth, 2, SQL_PARAM_INPUT, &n_id.eid_id );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_modrdn(): "
"error binding parent ID parameter for objectClass %s\n",
oc->bom_oc->soc_cname.bv_val );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
e = NULL;
goto done;
}
rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &e_id.eid_keyval );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_modrdn(): "
"error binding entry ID parameter for objectClass %s\n",
oc->bom_oc->soc_cname.bv_val );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
e = NULL;
goto done;
}
rc = backsql_BindParamID( sth, 4, SQL_PARAM_INPUT, &e_id.eid_id );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
" backsql_modrdn(): "
"error binding ID parameter for objectClass %s\n",
oc->bom_oc->soc_cname.bv_val );
backsql_PrintErrors( bi->sql_db_env, dbh,
sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_text = "SQL-backend error";
rs->sr_err = LDAP_OTHER;
e = NULL;
goto done;
}
rc = SQLExecute( sth );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): "
"could not rename ldap_entries record\n" );
backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
SQLFreeStmt( sth, SQL_DROP );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "SQL-backend error";
e = NULL;
goto done;
}
SQLFreeStmt( sth, SQL_DROP );
slap_mods_opattrs( op, &op->orr_modlist, 1 );
assert( e_id.eid_oc != NULL );
oc = e_id.eid_oc;
if ( op->orr_modlist != NULL ) {
rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, op->orr_modlist );
slap_graduate_commit_csn( op );
if ( rs->sr_err != LDAP_SUCCESS ) {
e = &r;
goto done;
}
}
if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
backsql_entry_clean( op, &r );
(void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
bsi.bsi_e = &r;
rs->sr_err = backsql_init_search( &bsi, &op->orr_nnewDN,
LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs,
slap_anlist_all_attributes,
( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
switch ( rs->sr_err ) {
case LDAP_SUCCESS:
break;
case LDAP_REFERRAL:
if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
dn_match( &op->orr_nnewDN, &bsi.bsi_e->e_nname ) )
{
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
rs->sr_matched = NULL;
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
break;
}
e = &r;
/* fallthru */
default:
Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
"could not retrieve modrdnDN ID - no such entry\n" );
if ( !BER_BVISNULL( &r.e_nname ) ) {
/* FIXME: should always be true! */
e = &r;
} else {
e = NULL;
}
goto done;
}
e_id = bsi.bsi_base_id;
rs->sr_err = entry_schema_check( op, &r, 0, 0, NULL,
&rs->sr_text, textbuf, sizeof( textbuf ) );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(\"%s\"): "
"entry failed schema check -- aborting\n",
r.e_name.bv_val );
e = NULL;
goto done;
}
}
done:;
if ( e != NULL ) {
if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL,
ACL_DISCLOSE, NULL ) )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
rs->sr_text = NULL;
rs->sr_matched = NULL;
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
}
}
/*
* Commit only if all operations succeed
*/
if ( sth != SQL_NULL_HSTMT ) {
SQLUSMALLINT CompletionType = SQL_ROLLBACK;
if ( rs->sr_err == LDAP_SUCCESS && !wants_noop( op ) ) {
CompletionType = SQL_COMMIT;
}
SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
}
if ( wants_noop( op ) && rs->sr_err == LDAP_SUCCESS ) {
rs->sr_err = LDAP_X_NO_OPERATION;
}
send_ldap_result( op, rs );
slap_graduate_commit_csn( op );
if ( !BER_BVISNULL( &realnew_dn ) && realnew_dn.bv_val != op->orr_newDN.bv_val ) {
ch_free( realnew_dn.bv_val );
}
if ( !BER_BVISNULL( &e_id.eid_ndn ) ) {
(void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &n_id.eid_ndn ) ) {
(void)backsql_free_entryID( &n_id, 0, op->o_tmpmemctx );
}
if ( !BER_BVISNULL( &r.e_nname ) ) {
backsql_entry_clean( op, &r );
}
if ( !BER_BVISNULL( &p.e_nname ) ) {
backsql_entry_clean( op, &p );
}
if ( !BER_BVISNULL( &n.e_nname ) ) {
backsql_entry_clean( op, &n );
}
if ( rs->sr_ref ) {
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
}
Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n" );
return rs->sr_err;
}

View file

@ -1,246 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Masarati.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati.
*/
#include "portable.h"
#include <stdio.h>
#include <sys/types.h>
#include "slap.h"
#include "proto-sql.h"
#include "lutil.h"
/*
* sets the supported operational attributes (if required)
*/
Attribute *
backsql_operational_entryUUID( backsql_info *bi, backsql_entryID *id )
{
int rc;
struct berval val, nval;
AttributeDescription *desc = slap_schema.si_ad_entryUUID;
Attribute *a;
backsql_entryUUID( bi, id, &val, NULL );
rc = (*desc->ad_type->sat_equality->smr_normalize)(
SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
desc->ad_type->sat_syntax,
desc->ad_type->sat_equality,
&val, &nval, NULL );
if ( rc != LDAP_SUCCESS ) {
ber_memfree( val.bv_val );
return NULL;
}
a = attr_alloc( desc );
a->a_numvals = 1;
a->a_vals = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
a->a_vals[ 0 ] = val;
BER_BVZERO( &a->a_vals[ 1 ] );
a->a_nvals = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
a->a_nvals[ 0 ] = nval;
BER_BVZERO( &a->a_nvals[ 1 ] );
return a;
}
Attribute *
backsql_operational_entryCSN( Operation *op )
{
char csnbuf[ LDAP_PVT_CSNSTR_BUFSIZE ];
struct berval entryCSN;
Attribute *a;
a = attr_alloc( slap_schema.si_ad_entryCSN );
a->a_numvals = 1;
a->a_vals = ch_malloc( 2 * sizeof( struct berval ) );
BER_BVZERO( &a->a_vals[ 1 ] );
#ifdef BACKSQL_SYNCPROV
if ( op->o_sync && op->o_tag == LDAP_REQ_SEARCH && op->o_private != NULL ) {
assert( op->o_private != NULL );
entryCSN = *((struct berval *)op->o_private);
} else
#endif /* BACKSQL_SYNCPROV */
{
entryCSN.bv_val = csnbuf;
entryCSN.bv_len = sizeof( csnbuf );
slap_get_csn( op, &entryCSN, 0 );
}
ber_dupbv( &a->a_vals[ 0 ], &entryCSN );
a->a_nvals = a->a_vals;
return a;
}
int
backsql_operational(
Operation *op,
SlapReply *rs )
{
backsql_info *bi = (backsql_info*)op->o_bd->be_private;
SQLHDBC dbh = SQL_NULL_HDBC;
int rc = 0;
Attribute **ap;
enum {
BACKSQL_OP_HASSUBORDINATES = 0,
BACKSQL_OP_ENTRYUUID,
BACKSQL_OP_ENTRYCSN,
BACKSQL_OP_LAST
};
int get_conn = BACKSQL_OP_LAST,
got[ BACKSQL_OP_LAST ] = { 0 };
Debug( LDAP_DEBUG_TRACE, "==>backsql_operational(): entry \"%s\"\n",
rs->sr_entry->e_nname.bv_val );
for ( ap = &rs->sr_entry->e_attrs; *ap; ap = &(*ap)->a_next ) {
if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
get_conn--;
got[ BACKSQL_OP_HASSUBORDINATES ] = 1;
} else if ( (*ap)->a_desc == slap_schema.si_ad_entryUUID ) {
get_conn--;
got[ BACKSQL_OP_ENTRYUUID ] = 1;
} else if ( (*ap)->a_desc == slap_schema.si_ad_entryCSN ) {
get_conn--;
got[ BACKSQL_OP_ENTRYCSN ] = 1;
}
}
for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) {
if ( !got[ BACKSQL_OP_HASSUBORDINATES ] &&
(*ap)->a_desc == slap_schema.si_ad_hasSubordinates )
{
get_conn--;
got[ BACKSQL_OP_HASSUBORDINATES ] = 1;
} else if ( !got[ BACKSQL_OP_ENTRYUUID ] &&
(*ap)->a_desc == slap_schema.si_ad_entryUUID )
{
get_conn--;
got[ BACKSQL_OP_ENTRYUUID ] = 1;
} else if ( !got[ BACKSQL_OP_ENTRYCSN ] &&
(*ap)->a_desc == slap_schema.si_ad_entryCSN )
{
get_conn--;
got[ BACKSQL_OP_ENTRYCSN ] = 1;
}
}
if ( !get_conn ) {
return 0;
}
rc = backsql_get_db_conn( op, &dbh );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
"could not get connection handle - exiting\n" );
return 1;
}
if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) )
&& !got[ BACKSQL_OP_HASSUBORDINATES ]
&& attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL )
{
rc = backsql_has_children( op, dbh, &rs->sr_entry->e_nname );
switch( rc ) {
case LDAP_COMPARE_TRUE:
case LDAP_COMPARE_FALSE:
*ap = slap_operational_hasSubordinate( rc == LDAP_COMPARE_TRUE );
assert( *ap != NULL );
ap = &(*ap)->a_next;
rc = 0;
break;
default:
Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
"has_children failed( %d)\n", rc );
return 1;
}
}
if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_entryUUID, rs->sr_attrs ) )
&& !got[ BACKSQL_OP_ENTRYUUID ]
&& attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID ) == NULL )
{
backsql_srch_info bsi = { 0 };
rc = backsql_init_search( &bsi, &rs->sr_entry->e_nname,
LDAP_SCOPE_BASE,
(time_t)(-1), NULL, dbh, op, rs, NULL,
BACKSQL_ISF_GET_ID );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
"could not retrieve entry ID - no such entry\n" );
return 1;
}
*ap = backsql_operational_entryUUID( bi, &bsi.bsi_base_id );
(void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
if ( bsi.bsi_attrs != NULL ) {
op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx );
}
if ( *ap == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
"could not retrieve entryUUID\n" );
return 1;
}
ap = &(*ap)->a_next;
}
if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_entryCSN, rs->sr_attrs ) )
&& !got[ BACKSQL_OP_ENTRYCSN ]
&& attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryCSN ) == NULL )
{
*ap = backsql_operational_entryCSN( op );
if ( *ap == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
"could not retrieve entryCSN\n" );
return 1;
}
ap = &(*ap)->a_next;
}
Debug( LDAP_DEBUG_TRACE, "<==backsql_operational(%d)\n", rc );
return rc;
}

View file

@ -1,313 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Mararati.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati
*/
/*
* The following changes have been addressed:
*
* Enhancements:
* - re-styled code for better readability
* - upgraded backend API to reflect recent changes
* - LDAP schema is checked when loading SQL/LDAP mapping
* - AttributeDescription/ObjectClass pointers used for more efficient
* mapping lookup
* - bervals used where string length is required often
* - atomized write operations by committing at the end of each operation
* and defaulting connection closure to rollback
* - added LDAP access control to write operations
* - fully implemented modrdn (with rdn attrs change, deleteoldrdn,
* access check, parent/children check and more)
* - added parent access control, children control to delete operation
* - added structuralObjectClass operational attribute check and
* value return on search
* - added hasSubordinate operational attribute on demand
* - search limits are appropriately enforced
* - function backsql_strcat() has been made more efficient
* - concat function has been made configurable by means of a pattern
* - added config switches:
* - fail_if_no_mapping write operations fail if there is no mapping
* - has_ldapinfo_dn_ru overrides autodetect
* - concat_pattern a string containing two '?' is used
* (note that "?||?" should be more portable
* than builtin function "CONCAT(?,?)")
* - strcast_func cast of string constants in "SELECT DISTINCT
* statements (needed by PostgreSQL)
* - upper_needs_cast cast the argument of upper when required
* (basically when building dn substring queries)
* - added noop control
* - added values return filter control
* - hasSubordinate can be used in search filters (with limitations)
* - eliminated oc->name; use oc->oc->soc_cname instead
*
* Todo:
* - add security checks for SQL statements that can be injected (?)
* - re-test with previously supported RDBMs
* - replace dn_ru and so with normalized dn (no need for upper() and so
* in dn match)
* - implement a backsql_normalize() function to replace the upper()
* conversion routines
* - note that subtree deletion, subtree renaming and so could be easily
* implemented (rollback and consistency checks are available :)
* - implement "lastmod" and other operational stuff (ldap_entries table ?)
* - check how to allow multiple operations with one statement, to remove
* BACKSQL_REALLOC_STMT from modify.c (a more recent unixODBC lib?)
*/
#ifndef PROTO_SQL_H
#define PROTO_SQL_H
#include "back-sql.h"
/*
* add.c
*/
int backsql_modify_delete_all_values(
Operation *op,
SlapReply *rs,
SQLHDBC dbh,
backsql_entryID *e_id,
backsql_at_map_rec *at );
int backsql_modify_internal(
Operation *op,
SlapReply *rs,
SQLHDBC dbh,
backsql_oc_map_rec *oc,
backsql_entryID *e_id,
Modifications *modlist );
/*
* api.c
*/
int backsql_api_config( backsql_info *bi, const char *name,
int argc, char *argv[] );
int backsql_api_destroy( backsql_info *bi );
int backsql_api_register( backsql_api *ba );
int backsql_api_dn2odbc( Operation *op, SlapReply *rs, struct berval *dn );
int backsql_api_odbc2dn( Operation *op, SlapReply *rs, struct berval *dn );
/*
* entry-id.c
*/
#ifdef BACKSQL_ARBITRARY_KEY
extern struct berval backsql_baseObject_bv;
#endif /* BACKSQL_ARBITRARY_KEY */
/* stores in *id the ID in table ldap_entries corresponding to DN, if any */
extern int
backsql_dn2id( Operation *op, SlapReply *rs, SQLHDBC dbh,
struct berval *ndn, backsql_entryID *id,
int matched, int muck );
/* stores in *nchildren the count of children for an entry */
extern int
backsql_count_children( Operation *op, SQLHDBC dbh,
struct berval *dn, unsigned long *nchildren );
/* returns LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE if the entry corresponding
* to DN has/has not children */
extern int
backsql_has_children( Operation *op, SQLHDBC dbh, struct berval *dn );
/* free *id and return next in list */
extern backsql_entryID *
backsql_free_entryID( backsql_entryID *id, int freeit, void *ctx );
/* turn an ID into an entry */
extern int
backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *id );
/* duplicate an entryID */
extern backsql_entryID *
backsql_entryID_dup( backsql_entryID *eid, void *ctx );
/*
* operational.c
*/
Attribute *backsql_operational_entryUUID( backsql_info *bi, backsql_entryID *id );
Attribute *backsql_operational_entryCSN( Operation *op );
/*
* schema-map.c
*/
int backsql_load_schema_map( backsql_info *si, SQLHDBC dbh );
backsql_oc_map_rec *backsql_oc2oc( backsql_info *si, ObjectClass *oc );
backsql_oc_map_rec *backsql_id2oc( backsql_info *si, unsigned long id );
backsql_oc_map_rec * backsql_name2oc( backsql_info *si,
struct berval *oc_name );
backsql_at_map_rec *backsql_ad2at( backsql_oc_map_rec *objclass,
AttributeDescription *ad );
int backsql_supad2at( backsql_oc_map_rec *objclass,
AttributeDescription *supad, backsql_at_map_rec ***pret );
int backsql_destroy_schema_map( backsql_info *si );
/*
* search.c
*/
int backsql_init_search( backsql_srch_info *bsi,
struct berval *nbase, int scope,
time_t stoptime, Filter *filter, SQLHDBC dbh,
Operation *op, SlapReply *rs, AttributeName *attrs,
unsigned flags );
void backsql_entry_clean( Operation *op, Entry *e );
/*
* sql-wrap.h
*/
RETCODE backsql_Prepare( SQLHDBC dbh, SQLHSTMT *sth, const char* query, int timeout );
#define backsql_BindParamStr( sth, par_ind, io, str, maxlen ) \
SQLBindParameter( (sth), (SQLUSMALLINT)(par_ind), \
(io), SQL_C_CHAR, SQL_VARCHAR, \
(SQLULEN)(maxlen), 0, (SQLPOINTER)(str), \
(SQLLEN)(maxlen), NULL )
#define backsql_BindParamBerVal( sth, par_ind, io, bv ) \
SQLBindParameter( (sth), (SQLUSMALLINT)(par_ind), \
(io), SQL_C_CHAR, SQL_VARCHAR, \
(SQLULEN)(bv)->bv_len, 0, \
(SQLPOINTER)(bv)->bv_val, \
(SQLLEN)(bv)->bv_len, NULL )
#define backsql_BindParamInt( sth, par_ind, io, val ) \
SQLBindParameter( (sth), (SQLUSMALLINT)(par_ind), \
(io), SQL_C_ULONG, SQL_INTEGER, \
0, 0, (SQLPOINTER)(val), 0, (SQLLEN*)NULL )
#define backsql_BindParamNumID( sth, par_ind, io, val ) \
SQLBindParameter( (sth), (SQLUSMALLINT)(par_ind), \
(io), BACKSQL_C_NUMID, SQL_INTEGER, \
0, 0, (SQLPOINTER)(val), 0, (SQLLEN*)NULL )
#ifdef BACKSQL_ARBITRARY_KEY
#define backsql_BindParamID( sth, par_ind, io, id ) \
backsql_BindParamBerVal( (sth), (par_ind), (io), (id) )
#else /* ! BACKSQL_ARBITRARY_KEY */
#define backsql_BindParamID( sth, par_ind, io, id ) \
backsql_BindParamNumID( (sth), (par_ind), (io), (id) )
#endif /* ! BACKSQL_ARBITRARY_KEY */
RETCODE backsql_BindRowAsStrings_x( SQLHSTMT sth, BACKSQL_ROW_NTS *row, void *ctx );
RETCODE backsql_BindRowAsStrings( SQLHSTMT sth, BACKSQL_ROW_NTS *row );
RETCODE backsql_FreeRow_x( BACKSQL_ROW_NTS *row, void *ctx );
RETCODE backsql_FreeRow( BACKSQL_ROW_NTS *row );
void backsql_PrintErrors( SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth, int rc );
int backsql_conn_destroy( backsql_info *bi );
int backsql_init_db_env( backsql_info *si );
int backsql_free_db_env( backsql_info *si );
int backsql_get_db_conn( Operation *op, SQLHDBC *dbh );
int backsql_free_db_conn( Operation *op, SQLHDBC dbh );
/*
* util.c
*/
extern const char
backsql_def_oc_query[],
backsql_def_needs_select_oc_query[],
backsql_def_at_query[],
backsql_def_delentry_stmt[],
backsql_def_renentry_stmt[],
backsql_def_insentry_stmt[],
backsql_def_delobjclasses_stmt[],
backsql_def_subtree_cond[],
backsql_def_upper_subtree_cond[],
backsql_id_query[],
backsql_def_concat_func[],
backsql_check_dn_ru_query[];
struct berbuf * backsql_strcat_x( struct berbuf *dest, void *memctx, ... );
struct berbuf * backsql_strfcat_x( struct berbuf *dest, void *memctx, const char *fmt, ... );
int backsql_entry_addattr( Entry *e, AttributeDescription *ad,
struct berval *at_val, void *memctx );
int backsql_merge_from_clause( backsql_info *bi, struct berbuf *dest_from,
struct berval *src_from );
int backsql_split_pattern( const char *pattern, BerVarray *split_pattern,
int expected );
int backsql_prepare_pattern( BerVarray split_pattern, BerVarray values,
struct berval *res );
int backsql_entryUUID( backsql_info *bi, backsql_entryID *id,
struct berval *entryUUID, void *memctx );
int backsql_entryUUID_decode( struct berval *entryUUID, unsigned long *oc_id,
#ifdef BACKSQL_ARBITRARY_KEY
struct berval *keyval
#else /* ! BACKSQL_ARBITRARY_KEY */
unsigned long *keyval
#endif /* ! BACKSQL_ARBITRARY_KEY */
);
/*
* former external.h
*/
extern BI_init sql_back_initialize;
extern BI_destroy backsql_destroy;
extern BI_db_init backsql_db_init;
extern BI_db_open backsql_db_open;
extern BI_db_close backsql_db_close;
extern BI_db_destroy backsql_db_destroy;
extern BI_db_config backsql_db_config;
extern BI_op_bind backsql_bind;
extern BI_op_search backsql_search;
extern BI_op_compare backsql_compare;
extern BI_op_modify backsql_modify;
extern BI_op_modrdn backsql_modrdn;
extern BI_op_add backsql_add;
extern BI_op_delete backsql_delete;
extern BI_operational backsql_operational;
extern BI_entry_get_rw backsql_entry_get;
extern BI_entry_release_rw backsql_entry_release;
extern BI_connection_destroy backsql_connection_destroy;
int backsql_init_cf( BackendInfo * bi );
#endif /* PROTO_SQL_H */

View file

@ -1,189 +0,0 @@
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.

View file

@ -1,59 +0,0 @@
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)
);

View file

@ -1,5 +0,0 @@
DROP TABLE ldap_referrals;
DROP TABLE ldap_entry_objclasses;
DROP TABLE ldap_attr_mappings;
DROP TABLE ldap_entries;
DROP TABLE ldap_oc_mappings;

View file

@ -1,36 +0,0 @@
# $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"

View file

@ -1,75 +0,0 @@
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
);

View file

@ -1,18 +0,0 @@
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/');

View file

@ -1,5 +0,0 @@
DROP TABLE persons;
DROP TABLE institutes;
DROP TABLE documents;
DROP TABLE authors_docs;
DROP TABLE phones;

View file

@ -1,123 +0,0 @@
--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');

View file

@ -1,100 +0,0 @@
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);

View file

@ -1,14 +0,0 @@
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

View file

@ -1,30 +0,0 @@
# $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 '%'+?"

View file

@ -1,74 +0,0 @@
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

View file

@ -1,24 +0,0 @@
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)

View file

@ -1,39 +0,0 @@
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

View file

@ -1,198 +0,0 @@
-- 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

View file

@ -1,58 +0,0 @@
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)
);

View file

@ -1,7 +0,0 @@
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;

View file

@ -1,32 +0,0 @@
# $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

View file

@ -1,86 +0,0 @@
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
);

View file

@ -1,21 +0,0 @@
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);

View file

@ -1,5 +0,0 @@
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;

View file

@ -1,125 +0,0 @@
-- 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');

View file

@ -1,90 +0,0 @@
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

View file

@ -1,8 +0,0 @@
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;

View file

@ -1,32 +0,0 @@
# $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

View file

@ -1,68 +0,0 @@
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;

View file

@ -1,27 +0,0 @@
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);

View file

@ -1,25 +0,0 @@
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;

View file

@ -1,252 +0,0 @@
-- 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;
/

View file

@ -1,50 +0,0 @@
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)
);

View file

@ -1,4 +0,0 @@
DROP TABLE ldap_entry_objclasses;
DROP TABLE ldap_attr_mappings;
DROP TABLE ldap_entries;
DROP TABLE ldap_oc_mappings;

View file

@ -1,35 +0,0 @@
# $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

View file

@ -1,55 +0,0 @@
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
);

View file

@ -1,21 +0,0 @@
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);

View file

@ -1,13 +0,0 @@
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 ();

View file

@ -1,146 +0,0 @@
-- 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';

View file

@ -1,66 +0,0 @@
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)
);

View file

@ -1,9 +0,0 @@
DROP TABLE ldap_referrals;
DROP TABLE ldap_entry_objclasses;
DROP TABLE ldap_attr_mappings;
DROP TABLE ldap_entries;
DROP TABLE ldap_oc_mappings;

View file

@ -1,4 +0,0 @@
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

View file

@ -1,48 +0,0 @@
## Copyright 1997-2026 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

View file

@ -1,387 +0,0 @@
// Copyright 1997-2026 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;
}

View file

@ -1,31 +0,0 @@
# $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 (?,?,?,?)"

View file

@ -1,36 +0,0 @@
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;

View file

@ -1,16 +0,0 @@
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);

View file

@ -1,5 +0,0 @@
DROP TABLE persons;
DROP TABLE institutes;
DROP TABLE documents;
DROP TABLE authors_docs;
DROP TABLE phones;

View file

@ -1,108 +0,0 @@
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');

View file

@ -1,4 +0,0 @@
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

View file

@ -1,42 +0,0 @@
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;

View file

@ -1,20 +0,0 @@
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);

View file

@ -1,5 +0,0 @@
DROP TABLE persons;
DROP TABLE institutes;
DROP TABLE documents;
DROP TABLE authors_docs;
DROP TABLE phones;

View file

@ -1,122 +0,0 @@
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');

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,529 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Masarati.
* Portions Copyright 2004 Mark Adamson.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati and Mark Adamson.
*/
#include "portable.h"
#include <stdio.h>
#include "ac/string.h"
#include <sys/types.h>
#include "slap.h"
#include "proto-sql.h"
#define MAX_ATTR_LEN 16384
void
backsql_PrintErrors( SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth, int rc )
{
SQLCHAR msg[SQL_MAX_MESSAGE_LENGTH]; /* msg. buffer */
SQLCHAR state[SQL_SQLSTATE_SIZE]; /* statement buf. */
SDWORD iSqlCode; /* return code */
SWORD len = SQL_MAX_MESSAGE_LENGTH - 1; /* return length */
Debug( LDAP_DEBUG_TRACE, "Return code: %d\n", rc );
for ( ; rc = SQLError( henv, hdbc, sth, state, &iSqlCode, msg,
SQL_MAX_MESSAGE_LENGTH - 1, &len ), BACKSQL_SUCCESS( rc ); )
{
Debug( LDAP_DEBUG_TRACE,
" nativeErrCode=%d SQLengineState=%s msg=\"%s\"\n",
(int)iSqlCode, state, msg );
}
}
RETCODE
backsql_Prepare( SQLHDBC dbh, SQLHSTMT *sth, const char *query, int timeout )
{
RETCODE rc;
rc = SQLAllocStmt( dbh, sth );
if ( rc != SQL_SUCCESS ) {
return rc;
}
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>backsql_Prepare()\n" );
#endif /* BACKSQL_TRACE */
#ifdef BACKSQL_MSSQL_WORKAROUND
{
char drv_name[ 30 ];
SWORD len;
SQLGetInfo( dbh, SQL_DRIVER_NAME, drv_name, sizeof( drv_name ), &len );
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_Prepare(): driver name=\"%s\"\n",
drv_name );
#endif /* BACKSQL_TRACE */
ldap_pvt_str2upper( drv_name );
if ( !strncmp( drv_name, "SQLSRV32.DLL", STRLENOF( "SQLSRV32.DLL" ) ) ) {
/*
* stupid default result set in MS SQL Server
* does not support multiple active statements
* on the same connection -- so we are trying
* to make it not to use default result set...
*/
Debug( LDAP_DEBUG_TRACE, "_SQLprepare(): "
"enabling MS SQL Server default result "
"set workaround\n" );
rc = SQLSetStmtOption( *sth, SQL_CONCURRENCY,
SQL_CONCUR_ROWVER );
if ( rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO ) {
Debug( LDAP_DEBUG_TRACE, "backsql_Prepare(): "
"SQLSetStmtOption(SQL_CONCURRENCY,"
"SQL_CONCUR_ROWVER) failed:\n" );
backsql_PrintErrors( SQL_NULL_HENV, dbh, *sth, rc );
SQLFreeStmt( *sth, SQL_DROP );
return rc;
}
}
}
#endif /* BACKSQL_MSSQL_WORKAROUND */
if ( timeout > 0 ) {
Debug( LDAP_DEBUG_TRACE, "_SQLprepare(): "
"setting query timeout to %d sec.\n",
timeout );
rc = SQLSetStmtOption( *sth, SQL_QUERY_TIMEOUT, timeout );
if ( rc != SQL_SUCCESS ) {
backsql_PrintErrors( SQL_NULL_HENV, dbh, *sth, rc );
SQLFreeStmt( *sth, SQL_DROP );
return rc;
}
}
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "<==backsql_Prepare() calling SQLPrepare()\n" );
#endif /* BACKSQL_TRACE */
return SQLPrepare( *sth, (SQLCHAR *)query, SQL_NTS );
}
RETCODE
backsql_BindRowAsStrings_x( SQLHSTMT sth, BACKSQL_ROW_NTS *row, void *ctx )
{
RETCODE rc;
if ( row == NULL ) {
return SQL_ERROR;
}
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==> backsql_BindRowAsStrings()\n" );
#endif /* BACKSQL_TRACE */
rc = SQLNumResultCols( sth, &row->ncols );
if ( rc != SQL_SUCCESS ) {
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings(): "
"SQLNumResultCols() failed:\n" );
#endif /* BACKSQL_TRACE */
backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC, sth, rc );
} else {
SQLCHAR colname[ 64 ];
SQLSMALLINT name_len, col_type, col_scale, col_null;
SQLLEN col_prec;
int i;
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"ncols=%d\n", (int)row->ncols );
#endif /* BACKSQL_TRACE */
row->col_names = (BerVarray)ber_memcalloc_x( row->ncols + 1,
sizeof( struct berval ), ctx );
if ( row->col_names == NULL ) {
goto nomem;
}
row->col_prec = (UDWORD *)ber_memcalloc_x( row->ncols,
sizeof( UDWORD ), ctx );
if ( row->col_prec == NULL ) {
goto nomem;
}
row->col_type = (SQLSMALLINT *)ber_memcalloc_x( row->ncols,
sizeof( SQLSMALLINT ), ctx );
if ( row->col_type == NULL ) {
goto nomem;
}
row->cols = (char **)ber_memcalloc_x( row->ncols + 1,
sizeof( char * ), ctx );
if ( row->cols == NULL ) {
goto nomem;
}
row->value_len = (SQLLEN *)ber_memcalloc_x( row->ncols,
sizeof( SQLLEN ), ctx );
if ( row->value_len == NULL ) {
goto nomem;
}
if ( 0 ) {
nomem:
ber_memfree_x( row->col_names, ctx );
row->col_names = NULL;
ber_memfree_x( row->col_prec, ctx );
row->col_prec = NULL;
ber_memfree_x( row->col_type, ctx );
row->col_type = NULL;
ber_memfree_x( row->cols, ctx );
row->cols = NULL;
ber_memfree_x( row->value_len, ctx );
row->value_len = NULL;
Debug( LDAP_DEBUG_ANY, "backsql_BindRowAsStrings: "
"out of memory\n" );
return LDAP_NO_MEMORY;
}
for ( i = 0; i < row->ncols; i++ ) {
SQLSMALLINT TargetType;
rc = SQLDescribeCol( sth, (SQLSMALLINT)(i + 1), &colname[ 0 ],
(SQLUINTEGER)( sizeof( colname ) - 1 ),
&name_len, &col_type,
&col_prec, &col_scale, &col_null );
/* FIXME: test rc? */
ber_str2bv_x( (char *)colname, 0, 1,
&row->col_names[ i ], ctx );
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"col_name=%s, col_prec[%d]=%d\n",
colname, (int)(i + 1), (int)col_prec );
#endif /* BACKSQL_TRACE */
if ( col_type != SQL_CHAR && col_type != SQL_VARCHAR )
{
col_prec = MAX_ATTR_LEN;
}
row->cols[ i ] = (char *)ber_memcalloc_x( col_prec + 1,
sizeof( char ), ctx );
row->col_prec[ i ] = col_prec;
row->col_type[ i ] = col_type;
/*
* ITS#3386, ITS#3113 - 20070308
* Note: there are many differences between various DPMS and ODBC
* Systems; some support SQL_C_BLOB, SQL_C_BLOB_LOCATOR. YMMV:
* This has only been tested on Linux/MySQL/UnixODBC
* For BINARY-type Fields (BLOB, etc), read the data as BINARY
*/
if ( BACKSQL_IS_BINARY( col_type ) ) {
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"col_name=%s, col_type[%d]=%d: reading binary data\n",
colname, (int)(i + 1), (int)col_type);
#endif /* BACKSQL_TRACE */
TargetType = SQL_C_BINARY;
} else {
/* Otherwise read it as Character data */
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"col_name=%s, col_type[%d]=%d: reading character data\n",
colname, (int)(i + 1), (int)col_type);
#endif /* BACKSQL_TRACE */
TargetType = SQL_C_CHAR;
}
rc = SQLBindCol( sth, (SQLUSMALLINT)(i + 1),
TargetType,
(SQLPOINTER)row->cols[ i ],
col_prec + 1,
&row->value_len[ i ] );
/* FIXME: test rc? */
}
BER_BVZERO( &row->col_names[ i ] );
row->cols[ i ] = NULL;
}
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "<== backsql_BindRowAsStrings()\n" );
#endif /* BACKSQL_TRACE */
return rc;
}
RETCODE
backsql_BindRowAsStrings( SQLHSTMT sth, BACKSQL_ROW_NTS *row )
{
return backsql_BindRowAsStrings_x( sth, row, NULL );
}
RETCODE
backsql_FreeRow_x( BACKSQL_ROW_NTS *row, void *ctx )
{
if ( row->cols == NULL ) {
return SQL_ERROR;
}
ber_bvarray_free_x( row->col_names, ctx );
ber_memfree_x( row->col_prec, ctx );
ber_memfree_x( row->col_type, ctx );
ber_memvfree_x( (void **)row->cols, ctx );
ber_memfree_x( row->value_len, ctx );
return SQL_SUCCESS;
}
RETCODE
backsql_FreeRow( BACKSQL_ROW_NTS *row )
{
return backsql_FreeRow_x( row, NULL );
}
static void
backsql_close_db_handle( SQLHDBC dbh )
{
if ( dbh == SQL_NULL_HDBC ) {
return;
}
Debug( LDAP_DEBUG_TRACE, "==>backsql_close_db_handle(%p)\n",
(void *)dbh );
/*
* Default transact is SQL_ROLLBACK; commit is required only
* by write operations, and it is explicitly performed after
* each atomic operation succeeds.
*/
/* TimesTen */
SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
SQLDisconnect( dbh );
SQLFreeConnect( dbh );
Debug( LDAP_DEBUG_TRACE, "<==backsql_close_db_handle(%p)\n",
(void *)dbh );
}
int
backsql_conn_destroy(
backsql_info *bi )
{
return 0;
}
int
backsql_init_db_env( backsql_info *bi )
{
RETCODE rc;
int ret = SQL_SUCCESS;
Debug( LDAP_DEBUG_TRACE, "==>backsql_init_db_env()\n" );
rc = SQLAllocEnv( &bi->sql_db_env );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "init_db_env: SQLAllocEnv failed:\n" );
backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC,
SQL_NULL_HENV, rc );
ret = SQL_ERROR;
}
Debug( LDAP_DEBUG_TRACE, "<==backsql_init_db_env()=%d\n", ret );
return ret;
}
int
backsql_free_db_env( backsql_info *bi )
{
Debug( LDAP_DEBUG_TRACE, "==>backsql_free_db_env()\n" );
(void)SQLFreeEnv( bi->sql_db_env );
bi->sql_db_env = SQL_NULL_HENV;
/*
* stop, if frontend waits for all threads to shutdown
* before calling this -- then what are we going to delete??
* everything is already deleted...
*/
Debug( LDAP_DEBUG_TRACE, "<==backsql_free_db_env()\n" );
return SQL_SUCCESS;
}
static int
backsql_open_db_handle(
backsql_info *bi,
SQLHDBC *dbhp )
{
/* TimesTen */
char DBMSName[ 32 ];
int rc;
assert( dbhp != NULL );
*dbhp = SQL_NULL_HDBC;
Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_handle()\n" );
rc = SQLAllocConnect( bi->sql_db_env, dbhp );
if ( !BACKSQL_SUCCESS( rc ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
"SQLAllocConnect() failed:\n" );
backsql_PrintErrors( bi->sql_db_env, SQL_NULL_HDBC,
SQL_NULL_HENV, rc );
return LDAP_UNAVAILABLE;
}
rc = SQLConnect( *dbhp,
(SQLCHAR*)bi->sql_dbname, SQL_NTS,
(SQLCHAR*)bi->sql_dbuser, SQL_NTS,
(SQLCHAR*)bi->sql_dbpasswd, SQL_NTS );
if ( rc != SQL_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
"SQLConnect() to database \"%s\" %s.\n",
bi->sql_dbname,
rc == SQL_SUCCESS_WITH_INFO ?
"succeeded with info" : "failed" );
backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc );
if ( rc != SQL_SUCCESS_WITH_INFO ) {
SQLFreeConnect( *dbhp );
return LDAP_UNAVAILABLE;
}
}
/*
* TimesTen : Turn off autocommit. We must explicitly
* commit any transactions.
*/
SQLSetConnectOption( *dbhp, SQL_AUTOCOMMIT,
BACKSQL_AUTOCOMMIT_ON( bi ) ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF );
/*
* See if this connection is to TimesTen. If it is,
* remember that fact for later use.
*/
/* Assume until proven otherwise */
bi->sql_flags &= ~BSQLF_USE_REVERSE_DN;
DBMSName[ 0 ] = '\0';
rc = SQLGetInfo( *dbhp, SQL_DBMS_NAME, (PTR)&DBMSName,
sizeof( DBMSName ), NULL );
if ( rc == SQL_SUCCESS ) {
if ( strcmp( DBMSName, "TimesTen" ) == 0 ||
strcmp( DBMSName, "Front-Tier" ) == 0 )
{
Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
"TimesTen database!\n" );
bi->sql_flags |= BSQLF_USE_REVERSE_DN;
}
} else {
Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): "
"SQLGetInfo() failed.\n" );
backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc );
SQLDisconnect( *dbhp );
SQLFreeConnect( *dbhp );
return LDAP_UNAVAILABLE;
}
/* end TimesTen */
Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_handle()\n" );
return LDAP_SUCCESS;
}
static void *backsql_db_conn_dummy;
static void
backsql_db_conn_keyfree(
void *key,
void *data )
{
(void)backsql_close_db_handle( (SQLHDBC)data );
}
int
backsql_free_db_conn( Operation *op, SQLHDBC dbh )
{
Debug( LDAP_DEBUG_TRACE, "==>backsql_free_db_conn()\n" );
(void)backsql_close_db_handle( dbh );
ldap_pvt_thread_pool_setkey( op->o_threadctx,
&backsql_db_conn_dummy, (void *)SQL_NULL_HDBC,
backsql_db_conn_keyfree, NULL, NULL );
Debug( LDAP_DEBUG_TRACE, "<==backsql_free_db_conn()\n" );
return LDAP_SUCCESS;
}
int
backsql_get_db_conn( Operation *op, SQLHDBC *dbhp )
{
backsql_info *bi = (backsql_info *)op->o_bd->be_private;
int rc = LDAP_SUCCESS;
SQLHDBC dbh = SQL_NULL_HDBC;
Debug( LDAP_DEBUG_TRACE, "==>backsql_get_db_conn()\n" );
assert( dbhp != NULL );
*dbhp = SQL_NULL_HDBC;
if ( op->o_threadctx ) {
void *data = NULL;
ldap_pvt_thread_pool_getkey( op->o_threadctx,
&backsql_db_conn_dummy, &data, NULL );
dbh = (SQLHDBC)data;
} else {
dbh = bi->sql_dbh;
}
if ( dbh == SQL_NULL_HDBC ) {
rc = backsql_open_db_handle( bi, &dbh );
if ( rc != LDAP_SUCCESS ) {
return rc;
}
if ( op->o_threadctx ) {
void *data = (void *)dbh;
ldap_pvt_thread_pool_setkey( op->o_threadctx,
&backsql_db_conn_dummy, data,
backsql_db_conn_keyfree, NULL, NULL );
} else {
bi->sql_dbh = dbh;
}
}
*dbhp = dbh;
Debug( LDAP_DEBUG_TRACE, "<==backsql_get_db_conn()\n" );
return LDAP_SUCCESS;
}

View file

@ -1,572 +0,0 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1999-2026 The OpenLDAP Foundation.
* Portions Copyright 1999 Dmitry Kovalev.
* Portions Copyright 2002 Pierangelo Masarati.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Dmitry Kovalev for inclusion
* by OpenLDAP Software. Additional significant contributors include
* Pierangelo Masarati.
*/
#include "portable.h"
#include <stdio.h>
#include <sys/types.h>
#include "ac/string.h"
#include "ac/ctype.h"
#include "ac/stdarg.h"
#include "slap.h"
#include "proto-sql.h"
#include "lutil.h"
#define BACKSQL_MAX(a,b) ((a)>(b)?(a):(b))
#define BACKSQL_MIN(a,b) ((a)<(b)?(a):(b))
#define BACKSQL_STR_GROW 256
const char backsql_def_oc_query[] =
"SELECT id,name,keytbl,keycol,create_proc,delete_proc,expect_return "
"FROM ldap_oc_mappings";
const char backsql_def_needs_select_oc_query[] =
"SELECT id,name,keytbl,keycol,create_proc,create_keyval,delete_proc,"
"expect_return FROM ldap_oc_mappings";
const char backsql_def_at_query[] =
"SELECT name,sel_expr,from_tbls,join_where,add_proc,delete_proc,"
"param_order,expect_return,sel_expr_u FROM ldap_attr_mappings "
"WHERE oc_map_id=?";
const char backsql_def_delentry_stmt[] = "DELETE FROM ldap_entries WHERE id=?";
const char backsql_def_renentry_stmt[] =
"UPDATE ldap_entries SET dn=?,parent=?,keyval=? WHERE id=?";
const char backsql_def_insentry_stmt[] =
"INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) "
"VALUES (?,?,?,?)";
const char backsql_def_delobjclasses_stmt[] = "DELETE FROM ldap_entry_objclasses "
"WHERE entry_id=?";
const char backsql_def_subtree_cond[] = "ldap_entries.dn LIKE CONCAT('%',?)";
const char backsql_def_upper_subtree_cond[] = "(ldap_entries.dn) LIKE CONCAT('%',?)";
const char backsql_id_query[] = "SELECT id,keyval,oc_map_id,dn FROM ldap_entries WHERE ";
/* better ?||? or cast(?||? as varchar) */
const char backsql_def_concat_func[] = "CONCAT(?,?)";
/* TimesTen */
const char backsql_check_dn_ru_query[] = "SELECT dn_ru FROM ldap_entries";
struct berbuf *
backsql_strcat_x( struct berbuf *dest, void *memctx, ... )
{
va_list strs;
ber_len_t cdlen, cslen, grow;
char *cstr;
assert( dest != NULL );
assert( dest->bb_val.bv_val == NULL
|| dest->bb_val.bv_len == strlen( dest->bb_val.bv_val ) );
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>backsql_strcat()\n" );
#endif /* BACKSQL_TRACE */
va_start( strs, memctx );
if ( dest->bb_val.bv_val == NULL || dest->bb_len == 0 ) {
dest->bb_val.bv_val = (char *)ber_memalloc_x( BACKSQL_STR_GROW * sizeof( char ), memctx );
dest->bb_val.bv_len = 0;
dest->bb_len = BACKSQL_STR_GROW;
}
cdlen = dest->bb_val.bv_len;
while ( ( cstr = va_arg( strs, char * ) ) != NULL ) {
cslen = strlen( cstr );
grow = BACKSQL_MAX( BACKSQL_STR_GROW, cslen );
if ( dest->bb_len - cdlen <= cslen ) {
char *tmp_dest;
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_strcat(): "
"buflen=%d, cdlen=%d, cslen=%d "
"-- reallocating dest\n",
dest->bb_len, cdlen + 1, cslen );
#endif /* BACKSQL_TRACE */
tmp_dest = (char *)ber_memrealloc_x( dest->bb_val.bv_val,
dest->bb_len + grow * sizeof( char ), memctx );
if ( tmp_dest == NULL ) {
Debug( LDAP_DEBUG_ANY, "backsql_strcat(): "
"could not reallocate string buffer.\n" );
va_end( strs );
return NULL;
}
dest->bb_val.bv_val = tmp_dest;
dest->bb_len += grow;
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_strcat(): "
"new buflen=%d, dest=%p\n",
dest->bb_len, dest );
#endif /* BACKSQL_TRACE */
}
AC_MEMCPY( dest->bb_val.bv_val + cdlen, cstr, cslen + 1 );
cdlen += cslen;
}
va_end( strs );
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "<==backsql_strcat() (dest=\"%s\")\n",
dest->bb_val.bv_val );
#endif /* BACKSQL_TRACE */
dest->bb_val.bv_len = cdlen;
return dest;
}
struct berbuf *
backsql_strfcat_x( struct berbuf *dest, void *memctx, const char *fmt, ... )
{
va_list strs;
ber_len_t cdlen;
assert( dest != NULL );
assert( fmt != NULL );
assert( dest->bb_len == 0 || dest->bb_len > dest->bb_val.bv_len );
assert( dest->bb_val.bv_val == NULL
|| dest->bb_val.bv_len == strlen( dest->bb_val.bv_val ) );
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>backsql_strfcat()\n" );
#endif /* BACKSQL_TRACE */
va_start( strs, fmt );
if ( dest->bb_val.bv_val == NULL || dest->bb_len == 0 ) {
dest->bb_val.bv_val = (char *)ber_memalloc_x( BACKSQL_STR_GROW * sizeof( char ), memctx );
dest->bb_val.bv_len = 0;
dest->bb_len = BACKSQL_STR_GROW;
}
cdlen = dest->bb_val.bv_len;
for ( ; fmt[0]; fmt++ ) {
ber_len_t cslen, grow;
char *cstr, cc[ 2 ] = { '\0', '\0' };
struct berval *cbv;
switch ( fmt[ 0 ] ) {
/* berval */
case 'b':
cbv = va_arg( strs, struct berval * );
cstr = cbv->bv_val;
cslen = cbv->bv_len;
break;
/* length + string */
case 'l':
cslen = va_arg( strs, ber_len_t );
cstr = va_arg( strs, char * );
break;
/* string */
case 's':
cstr = va_arg( strs, char * );
cslen = strlen( cstr );
break;
/* char */
case 'c':
/*
* `char' is promoted to `int' when passed through `...'
*/
cc[0] = va_arg( strs, int );
cstr = cc;
cslen = 1;
break;
default:
assert( 0 );
}
grow = BACKSQL_MAX( BACKSQL_STR_GROW, cslen );
if ( dest->bb_len - cdlen <= cslen ) {
char *tmp_dest;
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_strfcat(): "
"buflen=%d, cdlen=%d, cslen=%d "
"-- reallocating dest\n",
dest->bb_len, cdlen + 1, cslen );
#endif /* BACKSQL_TRACE */
tmp_dest = (char *)ber_memrealloc_x( dest->bb_val.bv_val,
( dest->bb_len ) + grow * sizeof( char ), memctx );
if ( tmp_dest == NULL ) {
Debug( LDAP_DEBUG_ANY, "backsql_strfcat(): "
"could not reallocate string buffer.\n" );
va_end( strs );
return NULL;
}
dest->bb_val.bv_val = tmp_dest;
dest->bb_len += grow * sizeof( char );
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_strfcat(): "
"new buflen=%d, dest=%p\n", dest->bb_len, dest );
#endif /* BACKSQL_TRACE */
}
assert( cstr != NULL );
AC_MEMCPY( dest->bb_val.bv_val + cdlen, cstr, cslen + 1 );
cdlen += cslen;
}
va_end( strs );
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "<==backsql_strfcat() (dest=\"%s\")\n",
dest->bb_val.bv_val );
#endif /* BACKSQL_TRACE */
dest->bb_val.bv_len = cdlen;
return dest;
}
int
backsql_entry_addattr(
Entry *e,
AttributeDescription *ad,
struct berval *val,
void *memctx )
{
int rc;
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(\"%s\"): %s=%s\n",
e->e_name.bv_val, ad->ad_cname.bv_val, val->bv_val );
#endif /* BACKSQL_TRACE */
rc = attr_merge_normalize_one( e, ad, val, memctx );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_entry_addattr(\"%s\"): "
"failed to merge value \"%s\" for attribute \"%s\"\n",
e->e_name.bv_val, val->bv_val, ad->ad_cname.bv_val );
return rc;
}
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "<==backsql_entry_addattr(\"%s\")\n",
e->e_name.bv_val );
#endif /* BACKSQL_TRACE */
return LDAP_SUCCESS;
}
static char *
backsql_get_table_spec( backsql_info *bi, char **p )
{
char *s, *q;
struct berbuf res = BB_NULL;
assert( p != NULL );
assert( *p != NULL );
s = *p;
while ( **p && **p != ',' ) {
(*p)++;
}
if ( **p ) {
*(*p)++ = '\0';
}
#define BACKSQL_NEXT_WORD { \
while ( *s && isspace( (unsigned char)*s ) ) s++; \
if ( !*s ) return res.bb_val.bv_val; \
q = s; \
while ( *q && !isspace( (unsigned char)*q ) ) q++; \
if ( *q ) *q++='\0'; \
}
BACKSQL_NEXT_WORD;
/* table name */
backsql_strcat_x( &res, NULL, s, NULL );
s = q;
BACKSQL_NEXT_WORD;
if ( strcasecmp( s, "AS" ) == 0 ) {
s = q;
BACKSQL_NEXT_WORD;
}
/* oracle doesn't understand "AS" :( and other RDBMSes don't need it */
backsql_strfcat_x( &res, NULL, "lbbsb",
STRLENOF( " " ), " ",
&bi->sql_aliasing,
&bi->sql_aliasing_quote,
s,
&bi->sql_aliasing_quote );
return res.bb_val.bv_val;
}
int
backsql_merge_from_clause(
backsql_info *bi,
struct berbuf *dest_from,
struct berval *src_from )
{
char *s, *p, *srcc, *pos, e;
struct berbuf res = BB_NULL;
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>backsql_merge_from_clause(): "
"dest_from=\"%s\",src_from=\"%s\"\n",
dest_from ? dest_from->bb_val.bv_val : "<NULL>",
src_from->bv_val );
#endif /* BACKSQL_TRACE */
srcc = ch_strdup( src_from->bv_val );
p = srcc;
if ( dest_from != NULL ) {
res = *dest_from;
}
while ( *p ) {
s = backsql_get_table_spec( bi, &p );
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_merge_from_clause(): "
"p=\"%s\" s=\"%s\"\n", p, s );
#endif /* BACKSQL_TRACE */
if ( BER_BVISNULL( &res.bb_val ) ) {
backsql_strcat_x( &res, NULL, s, NULL );
} else {
pos = strstr( res.bb_val.bv_val, s );
if ( pos == NULL || ( ( e = pos[ strlen( s ) ] ) != '\0' && e != ',' ) ) {
backsql_strfcat_x( &res, NULL, "cs", ',', s );
}
}
if ( s ) {
ch_free( s );
}
}
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "<==backsql_merge_from_clause()\n" );
#endif /* BACKSQL_TRACE */
free( srcc );
*dest_from = res;
return 1;
}
/*
* splits a pattern in components separated by '?'
* (double ?? are turned into single ? and left in the string)
* expected contains the number of expected occurrences of '?'
* (a negative value means parse as many as possible)
*/
int
backsql_split_pattern(
const char *_pattern,
BerVarray *split_pattern,
int expected )
{
char *pattern, *start, *end;
struct berval bv;
int rc = 0;
#define SPLIT_CHAR '?'
assert( _pattern != NULL );
assert( split_pattern != NULL );
pattern = ch_strdup( _pattern );
start = pattern;
end = strchr( start, SPLIT_CHAR );
for ( ; start; expected-- ) {
char *real_end = end;
ber_len_t real_len;
if ( real_end == NULL ) {
real_end = start + strlen( start );
} else if ( real_end[ 1 ] == SPLIT_CHAR ) {
expected++;
AC_MEMCPY( real_end, real_end + 1, strlen( real_end ) );
end = strchr( real_end + 1, SPLIT_CHAR );
continue;
}
real_len = real_end - start;
if ( real_len == 0 ) {
ber_str2bv( "", 0, 1, &bv );
} else {
ber_str2bv( start, real_len, 1, &bv );
}
ber_bvarray_add( split_pattern, &bv );
if ( expected == 0 ) {
if ( end != NULL ) {
rc = -1;
goto done;
}
break;
}
if ( end != NULL ) {
start = end + 1;
end = strchr( start, SPLIT_CHAR );
}
}
done:;
ch_free( pattern );
return rc;
}
int
backsql_prepare_pattern(
BerVarray split_pattern,
BerVarray values,
struct berval *res )
{
int i;
struct berbuf bb = BB_NULL;
assert( res != NULL );
for ( i = 0; values[i].bv_val; i++ ) {
if ( split_pattern[i].bv_val == NULL ) {
ch_free( bb.bb_val.bv_val );
return -1;
}
backsql_strfcat_x( &bb, NULL, "b", &split_pattern[ i ] );
backsql_strfcat_x( &bb, NULL, "b", &values[ i ] );
}
if ( split_pattern[ i ].bv_val == NULL ) {
ch_free( bb.bb_val.bv_val );
return -1;
}
backsql_strfcat_x( &bb, NULL, "b", &split_pattern[ i ] );
*res = bb.bb_val;
return 0;
}
int
backsql_entryUUID(
backsql_info *bi,
backsql_entryID *id,
struct berval *entryUUID,
void *memctx )
{
char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
struct berval uuid;
#ifdef BACKSQL_ARBITRARY_KEY
int i;
ber_len_t l, lmax;
#endif /* BACKSQL_ARBITRARY_KEY */
/* entryUUID is generated as "%08x-%04x-%04x-0000-eaddrXXX"
* with eid_oc_id as %08x and hi and lo eid_id as %04x-%04x */
assert( bi != NULL );
assert( id != NULL );
assert( entryUUID != NULL );
#ifdef BACKSQL_ARBITRARY_KEY
snprintf( uuidbuf, sizeof( uuidbuf ),
"%08x-0000-0000-0000-000000000000",
( id->eid_oc_id & 0xFFFFFFFF ) );
lmax = id->eid_keyval.bv_len < 12 ? id->eid_keyval.bv_len : 12;
for ( l = 0, i = 9; l < lmax; l++, i += 2 ) {
switch ( i ) {
case STRLENOF( "00000000-0000" ):
case STRLENOF( "00000000-0000-0000" ):
case STRLENOF( "00000000-0000-0000-0000" ):
uuidbuf[ i++ ] = '-';
/* FALLTHRU */
default:
snprintf( &uuidbuf[ i ], 3, "%2x", id->eid_keyval.bv_val[ l ] );
break;
}
}
#else /* ! BACKSQL_ARBITRARY_KEY */
/* note: works only with 32 bit architectures... */
snprintf( uuidbuf, sizeof( uuidbuf ),
"%08x-%04x-%04x-0000-000000000000",
( (unsigned)id->eid_oc_id & 0xFFFFFFFF ),
( ( (unsigned)id->eid_keyval & 0xFFFF0000 ) >> 020 /* 16 */ ),
( (unsigned)id->eid_keyval & 0xFFFF ) );
#endif /* ! BACKSQL_ARBITRARY_KEY */
uuid.bv_val = uuidbuf;
uuid.bv_len = strlen( uuidbuf );
ber_dupbv_x( entryUUID, &uuid, memctx );
return 0;
}
int
backsql_entryUUID_decode(
struct berval *entryUUID,
unsigned long *oc_id,
#ifdef BACKSQL_ARBITRARY_KEY
struct berval *keyval
#else /* ! BACKSQL_ARBITRARY_KEY */
unsigned long *keyval
#endif /* ! BACKSQL_ARBITRARY_KEY */
)
{
#if 0
fprintf( stderr, "==> backsql_entryUUID_decode()\n" );
#endif
*oc_id = ( entryUUID->bv_val[0] << 030 /* 24 */ )
+ ( entryUUID->bv_val[1] << 020 /* 16 */ )
+ ( entryUUID->bv_val[2] << 010 /* 8 */ )
+ entryUUID->bv_val[3];
#ifdef BACKSQL_ARBITRARY_KEY
/* FIXME */
#else /* ! BACKSQL_ARBITRARY_KEY */
*keyval = ( entryUUID->bv_val[4] << 030 /* 24 */ )
+ ( entryUUID->bv_val[5] << 020 /* 16 */ )
+ ( entryUUID->bv_val[6] << 010 /* 8 */ )
+ entryUUID->bv_val[7];
#endif /* ! BACKSQL_ARBITRARY_KEY */
#if 0
fprintf( stderr, "<== backsql_entryUUID_decode(): oc=%lu id=%lu\n",
*oc_id, *keyval );
#endif
return LDAP_SUCCESS;
}

View file

@ -255,7 +255,6 @@ static OidRec OidMacros[] = {
* OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap/meta
* OLcfg{Bk|Db}{Oc|At}:4 -> back-monitor
* OLcfg{Bk|Db}{Oc|At}:5 -> back-relay
* OLcfg{Bk|Db}{Oc|At}:6 -> back-sql
* OLcfg{Bk|Db}{Oc|At}:7 -> back-sock
* OLcfg{Bk|Db}{Oc|At}:8 -> back-null
* OLcfg{Bk|Db}{Oc|At}:9 -> back-passwd

View file

@ -2205,7 +2205,6 @@ config_fp_parse_line(ConfigArgs *c)
"acl-bind", "acl-method", "idassert-bind", /* in back-ldap */
"acl-passwd", "bindpw", /* in back-<ldap/meta> */
"pseudorootpw", /* in back-meta */
"dbpasswd", /* in back-sql */
NULL
};
static char *const raw[] = {

View file

@ -26,12 +26,11 @@ test tests:
# test all backends
alltests: tests
@$(MAKE) sql
@$(MAKE) ldif
@$(MAKE) wt
# parallel test targets
partests: pmdb plloadd psql pldif pwt
partests: pmdb plloadd pldif pwt
pmdb:
@$(MAKE) mdb TESTINST=0 > testout.0
@ -39,9 +38,6 @@ pmdb:
plloadd:
@$(MAKE) lloadd TESTINST=1 > testout.1
psql:
@$(MAKE) sql TESTINST=2 > testout.2
pldif:
@$(MAKE) ldif TESTINST=3 > testout.3
@ -56,14 +52,6 @@ mdb-yes mdb-mod: FORCE
@echo "Initiating LDAP tests for MDB..."
@$(RUN) -b mdb all
sql test-sql: sql-$(BUILD_SQL)
sql-no:
@echo "run configure with --enable-sql to run SQL tests"
sql-yes sql-mod: FORCE
@echo "Initiating LDAP tests for SQL..."
@$(RUN) -b sql sql-all
ldif test-ldif: FORCE
@echo "Initiating LDAP tests for LDIF..."
@$(RUN) -b ldif all

View file

@ -3,9 +3,6 @@ verify basic functionality of the LDAP libraries and slapd.
To run all of the tests, type "make test".
To run MDB tests, type "make mdb".
To run SQL tests, define SLAPD_USE_SQL=<rdbms> and type
"make sql"; define SLAPD_USE_SQLWRITE=yes
to enable write tests as well.
To run WT tests, type "make wt".
To run regression tests, type "make regressions"

View file

@ -1,78 +0,0 @@
# provider slapd config -- for testing
# $OpenLDAP$
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
##
## Copyright 1998-2026 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted only as authorized by the OpenLDAP
## Public License.
##
## A copy of this license is available in the file LICENSE in the
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
#ucdata-path ./ucdata
include @SCHEMADIR@/core.schema
include @SCHEMADIR@/cosine.schema
include @SCHEMADIR@/inetorgperson.schema
include @SCHEMADIR@/openldap.schema
include @SCHEMADIR@/nis.schema
pidfile @TESTDIR@/slapd.1.pid
argsfile @TESTDIR@/slapd.1.args
#sqlmod#modulepath ../servers/slapd/back-sql/
#sqlmod#moduleload back_sql.la
#syncprovmod#modulepath ../servers/slapd/overlays/
#syncprovmod#moduleload syncprov.la
#
# normal installations should protect root dse,
# cn=monitor, cn=schema, and cn=config
#
access to attrs=userpassword
by self =w
by anonymous =x
access to *
by * read
#######################################################################
# sql database definitions
#######################################################################
database sql
suffix "dc=example,dc=com"
rootdn "cn=Manager,dc=example,dc=com"
rootpw secret
dbname example
dbuser manager
dbpasswd secret
#
# rdbms specific directives
#
# IBM db2
#ibmdb2#upper_func "ucase"
#ibmdb2#upper_needs_cast "yes"
#ibmdb2#concat_pattern "?||?"
#ibmdb2#children_cond "ucase(ldap_entries.dn)=ucase(cast(? as varchar(255)))"
#ibmdb2#create_needs_select "yes"
#ibmdb2#insentry_stmt "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select case when max(id) is null then 1 else max(id) + 1 end from ldap_entries),?,?,?,?)"
#
# PostgreSQL
#pgsql#insentry_stmt "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select case when max(id) is null then 1 else max(id) + 1 end from ldap_entries),?,?,?,?)"
#pgsql#upper_func "upper"
#pgsql#strcast_func "text"
#pgsql#concat_pattern "?||?"
#
# MySQL
#mysql#concat_pattern "concat(?,?)"
has_ldapinfo_dn_ru no
overlay syncprov
database monitor

View file

@ -1,74 +0,0 @@
# provider slapd config -- for testing
# $OpenLDAP$
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
##
## Copyright 1998-2026 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted only as authorized by the OpenLDAP
## Public License.
##
## A copy of this license is available in the file LICENSE in the
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
#ucdata-path ./ucdata
include @SCHEMADIR@/core.schema
include @SCHEMADIR@/cosine.schema
include @SCHEMADIR@/inetorgperson.schema
include @SCHEMADIR@/openldap.schema
include @SCHEMADIR@/nis.schema
pidfile @TESTDIR@/slapd.1.pid
argsfile @TESTDIR@/slapd.1.args
#sqlmod#modulepath ../servers/slapd/back-sql/
#sqlmod#moduleload back_sql.la
#
# normal installations should protect root dse,
# cn=monitor, cn=schema, and cn=config
#
access to attrs=userpassword
by self =w
by anonymous =x
access to *
by * read
#######################################################################
# sql database definitions
#######################################################################
database sql
suffix "dc=example,dc=com"
rootdn "cn=Manager,dc=example,dc=com"
rootpw secret
dbname example
dbuser manager
dbpasswd secret
#
# rdbms specific directives
#
# IBM db2
#ibmdb2#upper_func "ucase"
#ibmdb2#upper_needs_cast "yes"
#ibmdb2#concat_pattern "?||?"
#ibmdb2#children_cond "ucase(ldap_entries.dn)=ucase(cast(? as varchar(255)))"
#ibmdb2#create_needs_select "yes"
#ibmdb2#insentry_stmt "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select case when max(id) is null then 1 else max(id) + 1 end from ldap_entries),?,?,?,?)"
#
# PostgreSQL
#pgsql#insentry_stmt "insert into ldap_entries (id,dn,oc_map_id,parent,keyval) values ((select case when max(id) is null then 1 else max(id) + 1 end from ldap_entries),?,?,?,?)"
#pgsql#upper_func "upper"
#pgsql#strcast_func "text"
#pgsql#concat_pattern "?||?"
#
# MySQL
#mysql#concat_pattern "concat(?,?)"
has_ldapinfo_dn_ru no
database monitor

View file

@ -1,9 +0,0 @@
cn=James Jones 1,dc=example,dc=com
objectClass: inetOrgPerson
cn: James Jones 1
givenName: James
sn: Jones 1
userpassword:: amFq
telephoneNumber: +1 313 555 4772
telephoneNumber: +1 313 555 4332
telephoneNumber: +1 313 555 0895

View file

@ -1,10 +0,0 @@
cn=James Jones 2,dc=example,dc=com
objectClass: inetOrgPerson
cn: James Jones 2
givenName: James
sn: Jones 2
userpassword:: amFq
telephoneNumber: +1 313 555 4772
telephoneNumber: +1 313 555 3923
telephoneNumber: +1 313 555 4332
telephoneNumber: +1 313 555 0895

View file

@ -1,10 +0,0 @@
cn=James Jones 3,dc=example,dc=com
objectClass: inetOrgPerson
cn: James Jones 3
givenName: James
sn: Jones 3
userpassword:: amFq
telephoneNumber: +1 313 555 4772
telephoneNumber: +1 313 555 3923
telephoneNumber: +1 313 555 4332
telephoneNumber: +1 313 555 0895

View file

@ -1,10 +0,0 @@
cn=James Jones 4,dc=example,dc=com
objectClass: inetOrgPerson
cn: James Jones 4
givenName: James
sn: Jones 4
userpassword:: amFq
telephoneNumber: +1 313 555 4772
telephoneNumber: +1 313 555 3923
telephoneNumber: +1 313 555 4332
telephoneNumber: +1 313 555 0895

View file

@ -1,2 +0,0 @@
cn=Mitya Kovalev,dc=example,dc=com
mit

View file

@ -1,2 +0,0 @@
cn=Mitya Kovalev,dc=example,dc=com
cn=Torvlobnor Puzdoy,dc=example,dc=com

Some files were not shown because too many files have changed in this diff Show more