schema.h revision 48258c6b4e17f36ab09fba0bd6307d1fec9dcbce
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SCHEMA_H
#define _SCHEMA_H
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Various macros (constant strings) containing:
*
* - CREATE TABLE/INDEX/TRIGGER/VIEW SQL
* - old versions of schema items that have changed
* - SQL to detect the version currently installed in a db
* - SQL to upgrade the schema from any older version to the current
* - the SQL to install the current version of the schema on a
* freshly created db is the SQL used to "upgrade" from "version 0"
*
* There is one set of such macros for the cache DB (CACHE_*) and
* another set for the persistent DB (DB_*). The macros ending in _SQL
* are used in arguments to init_db_instance().
*
* Schema version detection SQL has the following form:
*
* SELECT CASE (SELECT count(*) FROM sqlite_master) WHEN 0 THEN 0 ELSE
* (CASE (SELECT count(*) FROM sqlite_master WHERE sql = <original schema> ...)
* WHEN <correct count> THEN 1 ELSE (CASE (<v2 schema>) WHEN ... THEN 2
* ELSE -1 END) END AS version;
*
* That is, check that there is no schema else that the current schema
* sql matches the original schema, else the next version, ... and
* return an integer identifying the schema. Version numbers returned:
*
* -1 -> unknown schema (shouldn't happen)
* 0 -> no schema (brand new DB, install latest schema)
* 1 -> original schema (if != latest, then upgrade)
* . -> ... (if != latest, then upgrade)
* n -> latest schema (nothing to do)
*
* Upgrade SQL for the cache DB is simple: drop everything, create
* latest schema. This means losing ephemeral mappings, so idmapd must
* tell the kernel about that in its registration call.
*
* Upgrade SQL for the persistent DB is simple: drop the indexes, create
* temporary tables with the latest schema, insert into those from the
* old tables (transforming the data in the process), then drop the old
* tables, create the latest schema, restore the data from the temp.
* tables and drop the temp tables.
*
* Complex, but it avoids all sorts of packaging install/upgrade
* complexity, requiring reboots on patch.
*
* Conventions:
* - each TABLE/INDEX gets its own macro, and the SQL therein must not
* end in a semi-colon (';)
* - macros are named * TABLE_* for tables, INDEX_* for indexes,
* *_VERSION_SQL for SQL for determining version number,
* *_UPGRADE_FROM_v<version>_SQL for SQL for upgrading from some
* schema, *_LATEST_SQL for SQL for installing the latest schema.
* - some macros nest expansions of other macros
*
* The latest schema has two columns for Windows user/group name in
* tables where there used to be one. One of those columns contains the
* name as it came from the user or from AD, the other is set via a
* TRIGGER to be the lower-case version of the first, and we always
* search (and index) by the latter. This is for case-insensitivity.
*/
#define TABLE_IDMAP_CACHE_v1 \
"CREATE TABLE idmap_cache (" \
" sidprefix TEXT," \
" rid INTEGER," \
" windomain TEXT," \
" winname TEXT," \
" pid INTEGER," \
" unixname TEXT," \
" is_user INTEGER," \
" w2u INTEGER," \
" u2w INTEGER," \
" expiration INTEGER" \
")"
#define TABLE_IDMAP_CACHE_v2 \
"CREATE TABLE idmap_cache " \
"(" \
" sidprefix TEXT," \
" rid INTEGER," \
" windomain TEXT," \
" canon_winname TEXT," \
" winname TEXT," \
" pid INTEGER," \
" unixname TEXT," \
" is_user INTEGER," \
" is_wuser INTEGER," \
" w2u INTEGER," \
" u2w INTEGER," \
" expiration INTEGER" \
")"
#define TABLE_IDMAP_CACHE \
"CREATE TABLE idmap_cache " \
"(" \
" sidprefix TEXT," \
" rid INTEGER," \
" windomain TEXT," \
" canon_winname TEXT," \
" winname TEXT," \
" pid INTEGER," \
" unixname TEXT," \
" is_user INTEGER," \
" is_wuser INTEGER," \
" w2u INTEGER," \
" u2w INTEGER," \
" map_type INTEGER," \
" map_dn TEXT, "\
" map_attr TEXT, "\
" map_value TEXT, "\
" map_windomain TEXT, "\
" map_winname TEXT, "\
" map_unixname TEXT, "\
" map_is_nt4 INTEGER, "\
" expiration INTEGER" \
")"
#define INDEX_IDMAP_CACHE_SID_W2U_v1 \
"CREATE UNIQUE INDEX idmap_cache_sid_w2u ON idmap_cache" \
" (sidprefix, rid, w2u)"
#define INDEX_IDMAP_CACHE_SID_W2U \
"CREATE UNIQUE INDEX idmap_cache_sid_w2u ON idmap_cache" \
" (sidprefix, rid, is_user, w2u)"
#define INDEX_IDMAP_CACHE_PID_U2W \
"CREATE UNIQUE INDEX idmap_cache_pid_u2w ON idmap_cache" \
" (pid, is_user, u2w)"
#define TRIGGER_IDMAP_CACHE_TOLOWER_INSERT \
"CREATE TRIGGER idmap_cache_tolower_name_insert " \
"AFTER INSERT ON idmap_cache " \
"BEGIN " \
" UPDATE idmap_cache SET winname = lower_utf8(canon_winname)" \
" WHERE rowid = new.rowid;" \
"END"
#define TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE \
"CREATE TRIGGER idmap_cache_tolower_name_update " \
"AFTER UPDATE ON idmap_cache " \
"BEGIN " \
" UPDATE idmap_cache SET winname = lower_utf8(canon_winname)" \
" WHERE rowid = new.rowid;" \
"END"
#define TABLE_NAME_CACHE \
"CREATE TABLE name_cache (" \
" sidprefix TEXT," \
" rid INTEGER," \
" name TEXT," \
" canon_name TEXT," \
" domain TEXT," \
" type INTEGER," \
" expiration INTEGER" \
")"
#define TABLE_NAME_CACHE_v1 \
"CREATE TABLE name_cache (" \
" sidprefix TEXT," \
" rid INTEGER," \
" name TEXT," \
" domain TEXT," \
" type INTEGER," \
" expiration INTEGER" \
")"
#define TRIGGER_NAME_CACHE_TOLOWER_INSERT \
"CREATE TRIGGER name_cache_tolower_name_insert " \
"AFTER INSERT ON name_cache " \
"BEGIN " \
" UPDATE name_cache SET name = lower_utf8(canon_name)" \
" WHERE rowid = new.rowid;" \
"END"
#define TRIGGER_NAME_CACHE_TOLOWER_UPDATE \
"CREATE TRIGGER name_cache_tolower_name_update " \
"AFTER UPDATE ON name_cache " \
"BEGIN " \
" UPDATE name_cache SET name = lower_utf8(canon_name)" \
" WHERE rowid = new.rowid;" \
"END"
#define INDEX_NAME_CACHE_SID \
"CREATE UNIQUE INDEX name_cache_sid ON name_cache" \
" (sidprefix, rid)"
#define INDEX_NAME_CACHE_NAME \
"CREATE UNIQUE INDEX name_cache_name ON name_cache" \
" (name, domain)"
#define CACHE_INSTALL_SQL \
TABLE_IDMAP_CACHE ";" \
INDEX_IDMAP_CACHE_SID_W2U ";" \
INDEX_IDMAP_CACHE_PID_U2W ";" \
TRIGGER_IDMAP_CACHE_TOLOWER_INSERT ";" \
TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE ";" \
TABLE_NAME_CACHE ";" \
INDEX_NAME_CACHE_SID ";" \
INDEX_NAME_CACHE_NAME ";" \
TRIGGER_NAME_CACHE_TOLOWER_INSERT ";" \
TRIGGER_NAME_CACHE_TOLOWER_UPDATE ";"
#define CACHE_VERSION_SQL \
"SELECT CASE (SELECT count(*) FROM sqlite_master) WHEN 0 THEN 0 ELSE " \
"(CASE (SELECT count(*) FROM sqlite_master WHERE " \
"sql = '" TABLE_IDMAP_CACHE_v1 "' OR " \
"sql = '" INDEX_IDMAP_CACHE_SID_W2U_v1 "' OR " \
"sql = '" INDEX_IDMAP_CACHE_PID_U2W "' OR " \
"sql = '" TABLE_NAME_CACHE_v1 "' OR " \
"sql = '" INDEX_NAME_CACHE_SID "') " \
"WHEN 5 THEN 1 ELSE " \
"(CASE (SELECT count(*) FROM sqlite_master WHERE " \
"sql = '" TABLE_IDMAP_CACHE_v2"' OR " \
"sql = '" INDEX_IDMAP_CACHE_SID_W2U "' OR " \
"sql = '" INDEX_IDMAP_CACHE_PID_U2W "' OR " \
"sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_INSERT "' OR " \
"sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE "' OR " \
"sql = '" TABLE_NAME_CACHE "' OR " \
"sql = '" INDEX_NAME_CACHE_SID "' OR " \
"sql = '" INDEX_NAME_CACHE_NAME "' OR " \
"sql = '" TRIGGER_NAME_CACHE_TOLOWER_INSERT "' OR " \
"sql = '" TRIGGER_NAME_CACHE_TOLOWER_UPDATE "') " \
"WHEN 10 THEN 2 ELSE " \
"(CASE (SELECT count(*) FROM sqlite_master WHERE " \
"sql = '" TABLE_IDMAP_CACHE"' OR " \
"sql = '" INDEX_IDMAP_CACHE_SID_W2U "' OR " \
"sql = '" INDEX_IDMAP_CACHE_PID_U2W "' OR " \
"sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_INSERT "' OR " \
"sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE "' OR " \
"sql = '" TABLE_NAME_CACHE "' OR " \
"sql = '" INDEX_NAME_CACHE_SID "' OR " \
"sql = '" INDEX_NAME_CACHE_NAME "' OR " \
"sql = '" TRIGGER_NAME_CACHE_TOLOWER_INSERT "' OR " \
"sql = '" TRIGGER_NAME_CACHE_TOLOWER_UPDATE "') " \
"WHEN 10 THEN 3 ELSE -1 END) END) END) END AS version;"
#define CACHE_UPGRADE_FROM_v1_SQL \
"DROP TABLE idmap_cache;" \
"DROP TABLE name_cache;" \
CACHE_INSTALL_SQL
#define CACHE_UPGRADE_FROM_v2_SQL \
"DROP TABLE idmap_cache;" \
"DROP TABLE name_cache;" \
CACHE_INSTALL_SQL
#define CACHE_VERSION 3
#define TABLE_NAMERULES_v1 \
"CREATE TABLE namerules (" \
" is_user INTEGER NOT NULL," \
" windomain TEXT," \
" winname TEXT NOT NULL," \
" is_nt4 INTEGER NOT NULL," \
" unixname NOT NULL," \
" w2u_order INTEGER," \
" u2w_order INTEGER" \
")"
#define TABLE_NAMERULES_BODY \
"(" \
" is_user INTEGER NOT NULL," \
" is_wuser INTEGER NOT NULL," \
" windomain TEXT," \
" winname_display TEXT NOT NULL," \
" winname TEXT," \
" is_nt4 INTEGER NOT NULL," \
" unixname NOT NULL," \
" w2u_order INTEGER," \
" u2w_order INTEGER" \
")"
#define TABLE_NAMERULES \
"CREATE TABLE namerules " \
TABLE_NAMERULES_BODY
#define INDEX_NAMERULES_W2U_v1 \
"CREATE UNIQUE INDEX namerules_w2u ON namerules" \
" (winname, windomain, is_user, w2u_order)"
#define INDEX_NAMERULES_W2U \
"CREATE UNIQUE INDEX namerules_w2u ON namerules" \
" (winname, windomain, is_user, is_wuser, w2u_order)"
#define INDEX_NAMERULES_U2W \
"CREATE UNIQUE INDEX namerules_u2w ON namerules" \
" (unixname, is_user, u2w_order)"
#define TRIGGER_NAMERULES_TOLOWER_BODY \
"BEGIN " \
" UPDATE namerules SET winname = lower_utf8(winname_display)" \
" WHERE rowid = new.rowid;" \
"END"
#define TRIGGER_NAMERULES_TOLOWER_INSERT \
"CREATE TRIGGER namerules_tolower_name_insert " \
"AFTER INSERT ON namerules " \
TRIGGER_NAMERULES_TOLOWER_BODY
#define TRIGGER_NAMERULES_TOLOWER_UPDATE \
"CREATE TRIGGER namerules_tolower_name_update " \
"AFTER UPDATE ON namerules " \
TRIGGER_NAMERULES_TOLOWER_BODY
#define TRIGGER_NAMERULES_UNIQUE_BODY \
" SELECT CASE (SELECT count(*) FROM namerules AS n" \
" WHERE n.unixname = NEW.unixname AND" \
" n.is_user = NEW.is_user AND" \
" (n.winname != lower(NEW.winname_display) OR" \
" n.windomain != NEW.windomain ) AND" \
" n.u2w_order = NEW.u2w_order AND" \
" n.is_wuser != NEW.is_wuser) > 0" \
" WHEN 1 THEN" \
" raise(ROLLBACK, 'Conflicting w2u namerules')"\
" END; " \
"END"
#define TRIGGER_NAMERULES_UNIQUE_INSERT \
"CREATE TRIGGER namerules_unique_insert " \
"BEFORE INSERT ON namerules " \
"BEGIN " \
TRIGGER_NAMERULES_UNIQUE_BODY
#define TRIGGER_NAMERULES_UNIQUE_UPDATE \
"CREATE TRIGGER namerules_unique_update " \
"BEFORE INSERT ON namerules " \
"BEGIN " \
TRIGGER_NAMERULES_UNIQUE_BODY
#define DB_INSTALL_SQL \
TABLE_NAMERULES ";" \
INDEX_NAMERULES_W2U ";" \
INDEX_NAMERULES_U2W ";" \
TRIGGER_NAMERULES_TOLOWER_INSERT ";" \
TRIGGER_NAMERULES_TOLOWER_UPDATE ";" \
TRIGGER_NAMERULES_UNIQUE_INSERT ";" \
TRIGGER_NAMERULES_UNIQUE_UPDATE ";"
#define DB_VERSION_SQL \
"SELECT CASE (SELECT count(*) FROM sqlite_master) WHEN 0 THEN 0 ELSE " \
"(CASE (SELECT count(*) FROM sqlite_master WHERE " \
"sql = '" TABLE_NAMERULES_v1 "' OR " \
"sql = '" INDEX_NAMERULES_W2U_v1 "' OR " \
"sql = '" INDEX_NAMERULES_U2W "') " \
"WHEN 3 THEN 1 ELSE "\
"(CASE (SELECT count(*) FROM sqlite_master WHERE " \
"sql = '" TABLE_NAMERULES "' OR " \
"sql = '" INDEX_NAMERULES_W2U "' OR " \
"sql = '" INDEX_NAMERULES_U2W "' OR " \
"sql = '" TRIGGER_NAMERULES_TOLOWER_INSERT "' OR " \
"sql = '" TRIGGER_NAMERULES_TOLOWER_UPDATE "' OR " \
"sql = \"" TRIGGER_NAMERULES_UNIQUE_INSERT "\" OR " \
"sql = \"" TRIGGER_NAMERULES_UNIQUE_UPDATE "\") " \
"WHEN 7 THEN 2 ELSE -1 END) END) END AS version;"
/* SQL for upgrading an existing name rules DB. Includes DB_INSTALL_SQL */
#define DB_UPGRADE_FROM_v1_SQL \
"CREATE TABLE namerules_new " TABLE_NAMERULES_BODY ";" \
"INSERT INTO namerules_new SELECT is_user, is_user, windomain, " \
"winname, winname, is_nt4, unixname, w2u_order, u2w_order " \
"FROM namerules;" \
"DROP TABLE namerules;" \
DB_INSTALL_SQL \
"INSERT INTO namerules SELECT * FROM namerules_new;" \
"DROP TABLE namerules_new;"
#define DB_VERSION 2
#ifdef __cplusplus
}
#endif
#endif /* _SCHEMA_H */