mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-06-08 16:22:09 -04:00
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:
commit
38d68e0785
111 changed files with 7 additions and 19786 deletions
|
|
@ -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
|
||||
|
|
|
|||
85
configure.ac
85
configure.ac
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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__ */
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 = ≻
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
The SQL backend is described in the slapd-sql(5) manual page.
|
||||
|
|
@ -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).
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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 */
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
@ -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/');
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
DROP TABLE persons;
|
||||
DROP TABLE institutes;
|
||||
DROP TABLE documents;
|
||||
DROP TABLE authors_docs;
|
||||
DROP TABLE phones;
|
||||
|
|
@ -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');
|
||||
|
|
@ -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);
|
||||
|
|
@ -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
|
||||
|
|
@ -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 '%'+?"
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
@ -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');
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
/
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
DROP TABLE ldap_entry_objclasses;
|
||||
DROP TABLE ldap_attr_mappings;
|
||||
DROP TABLE ldap_entries;
|
||||
DROP TABLE ldap_oc_mappings;
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
@ -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 ();
|
||||
|
||||
|
|
@ -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';
|
||||
|
||||
|
|
@ -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)
|
||||
);
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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 (?,?,?,?)"
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
DROP TABLE persons;
|
||||
DROP TABLE institutes;
|
||||
DROP TABLE documents;
|
||||
DROP TABLE authors_docs;
|
||||
DROP TABLE phones;
|
||||
|
|
@ -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');
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
DROP TABLE persons;
|
||||
DROP TABLE institutes;
|
||||
DROP TABLE documents;
|
||||
DROP TABLE authors_docs;
|
||||
DROP TABLE phones;
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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[] = {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
cn=Mitya Kovalev,dc=example,dc=com
|
||||
mit
|
||||
|
|
@ -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
Loading…
Reference in a new issue