4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 #pragma ident "%Z%%M% %I% %E% SMI"
36 * Various macros (constant strings) containing:
38 * - CREATE TABLE/INDEX/TRIGGER/VIEW SQL
39 * - old versions of schema items that have changed
40 * - SQL to detect the version currently installed in a db
41 * - SQL to upgrade the schema from any older version to the current
42 * - the SQL to install the current version of the schema on a
43 * freshly created db is the SQL used to "upgrade" from "version 0"
45 * There is one set of such macros for the cache DB (CACHE_*) and
46 * another set for the persistent DB (DB_*). The macros ending in _SQL
47 * are used in arguments to init_db_instance().
49 * Schema version detection SQL has the following form:
51 * SELECT CASE (SELECT count(*) FROM sqlite_master) WHEN 0 THEN 0 ELSE
52 * (CASE (SELECT count(*) FROM sqlite_master WHERE sql = <original schema> ...)
53 * WHEN <correct count> THEN 1 ELSE (CASE (<v2 schema>) WHEN ... THEN 2
54 * ELSE -1 END) END AS version;
56 * That is, check that there is no schema else that the current schema
57 * sql matches the original schema, else the next version, ... and
58 * return an integer identifying the schema. Version numbers returned:
60 * -1 -> unknown schema (shouldn't happen)
61 * 0 -> no schema (brand new DB, install latest schema)
62 * 1 -> original schema (if != latest, then upgrade)
63 * . -> ... (if != latest, then upgrade)
64 * n -> latest schema (nothing to do)
66 * Upgrade SQL for the cache DB is simple: drop everything, create
67 * latest schema. This means losing ephemeral mappings, so idmapd must
68 * tell the kernel about that in its registration call.
70 * Upgrade SQL for the persistent DB is simple: drop the indexes, create
71 * temporary tables with the latest schema, insert into those from the
72 * old tables (transforming the data in the process), then drop the old
73 * tables, create the latest schema, restore the data from the temp.
74 * tables and drop the temp tables.
76 * Complex, but it avoids all sorts of packaging install/upgrade
77 * complexity, requiring reboots on patch.
80 * - each TABLE/INDEX gets its own macro, and the SQL therein must not
81 * end in a semi-colon (';)
82 * - macros are named * TABLE_* for tables, INDEX_* for indexes,
83 * *_VERSION_SQL for SQL for determining version number,
84 * *_UPGRADE_FROM_v<version>_SQL for SQL for upgrading from some
85 * schema, *_LATEST_SQL for SQL for installing the latest schema.
86 * - some macros nest expansions of other macros
88 * The latest schema has two columns for Windows user/group name in
89 * tables where there used to be one. One of those columns contains the
90 * name as it came from the user or from AD, the other is set via a
91 * TRIGGER to be the lower-case version of the first, and we always
92 * search (and index) by the latter. This is for case-insensitivity.
94 #define TABLE_IDMAP_CACHE_v1 \
95 "CREATE TABLE idmap_cache (" \
102 " is_user INTEGER," \
105 " expiration INTEGER" \
108 #define TABLE_IDMAP_CACHE_v2 \
109 "CREATE TABLE idmap_cache " \
114 " canon_winname TEXT," \
118 " is_user INTEGER," \
119 " is_wuser INTEGER," \
122 " expiration INTEGER" \
125 #define TABLE_IDMAP_CACHE \
126 "CREATE TABLE idmap_cache " \
131 " canon_winname TEXT," \
135 " is_user INTEGER," \
136 " is_wuser INTEGER," \
139 " map_type INTEGER," \
143 " map_windomain TEXT, "\
144 " map_winname TEXT, "\
145 " map_unixname TEXT, "\
146 " map_is_nt4 INTEGER, "\
147 " expiration INTEGER" \
150 #define INDEX_IDMAP_CACHE_SID_W2U_v1 \
151 "CREATE UNIQUE INDEX idmap_cache_sid_w2u ON idmap_cache" \
152 " (sidprefix, rid, w2u)"
154 #define INDEX_IDMAP_CACHE_SID_W2U \
155 "CREATE UNIQUE INDEX idmap_cache_sid_w2u ON idmap_cache" \
156 " (sidprefix, rid, is_user, w2u)"
158 #define INDEX_IDMAP_CACHE_PID_U2W \
159 "CREATE UNIQUE INDEX idmap_cache_pid_u2w ON idmap_cache" \
160 " (pid, is_user, u2w)"
162 #define TRIGGER_IDMAP_CACHE_TOLOWER_INSERT \
163 "CREATE TRIGGER idmap_cache_tolower_name_insert " \
164 "AFTER INSERT ON idmap_cache " \
166 " UPDATE idmap_cache SET winname = lower_utf8(canon_winname)" \
167 " WHERE rowid = new.rowid;" \
170 #define TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE \
171 "CREATE TRIGGER idmap_cache_tolower_name_update " \
172 "AFTER UPDATE ON idmap_cache " \
174 " UPDATE idmap_cache SET winname = lower_utf8(canon_winname)" \
175 " WHERE rowid = new.rowid;" \
178 #define TABLE_NAME_CACHE \
179 "CREATE TABLE name_cache (" \
183 " canon_name TEXT," \
186 " expiration INTEGER" \
189 #define TABLE_NAME_CACHE_v1 \
190 "CREATE TABLE name_cache (" \
196 " expiration INTEGER" \
199 #define TRIGGER_NAME_CACHE_TOLOWER_INSERT \
200 "CREATE TRIGGER name_cache_tolower_name_insert " \
201 "AFTER INSERT ON name_cache " \
203 " UPDATE name_cache SET name = lower_utf8(canon_name)" \
204 " WHERE rowid = new.rowid;" \
207 #define TRIGGER_NAME_CACHE_TOLOWER_UPDATE \
208 "CREATE TRIGGER name_cache_tolower_name_update " \
209 "AFTER UPDATE ON name_cache " \
211 " UPDATE name_cache SET name = lower_utf8(canon_name)" \
212 " WHERE rowid = new.rowid;" \
215 #define INDEX_NAME_CACHE_SID \
216 "CREATE UNIQUE INDEX name_cache_sid ON name_cache" \
219 #define INDEX_NAME_CACHE_NAME \
220 "CREATE UNIQUE INDEX name_cache_name ON name_cache" \
223 #define CACHE_INSTALL_SQL \
224 TABLE_IDMAP_CACHE ";" \
225 INDEX_IDMAP_CACHE_SID_W2U ";" \
226 INDEX_IDMAP_CACHE_PID_U2W ";" \
227 TRIGGER_IDMAP_CACHE_TOLOWER_INSERT ";" \
228 TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE ";" \
229 TABLE_NAME_CACHE ";" \
230 INDEX_NAME_CACHE_SID ";" \
231 INDEX_NAME_CACHE_NAME ";" \
232 TRIGGER_NAME_CACHE_TOLOWER_INSERT ";" \
233 TRIGGER_NAME_CACHE_TOLOWER_UPDATE ";"
235 #define CACHE_VERSION_SQL \
236 "SELECT CASE (SELECT count(*) FROM sqlite_master) WHEN 0 THEN 0 ELSE " \
237 "(CASE (SELECT count(*) FROM sqlite_master WHERE " \
238 "sql = '" TABLE_IDMAP_CACHE_v1 "' OR " \
239 "sql = '" INDEX_IDMAP_CACHE_SID_W2U_v1 "' OR " \
240 "sql = '" INDEX_IDMAP_CACHE_PID_U2W "' OR " \
241 "sql = '" TABLE_NAME_CACHE_v1 "' OR " \
242 "sql = '" INDEX_NAME_CACHE_SID "') " \
243 "WHEN 5 THEN 1 ELSE " \
244 "(CASE (SELECT count(*) FROM sqlite_master WHERE " \
245 "sql = '" TABLE_IDMAP_CACHE_v2"' OR " \
246 "sql = '" INDEX_IDMAP_CACHE_SID_W2U "' OR " \
247 "sql = '" INDEX_IDMAP_CACHE_PID_U2W "' OR " \
248 "sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_INSERT "' OR " \
249 "sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE "' OR " \
250 "sql = '" TABLE_NAME_CACHE "' OR " \
251 "sql = '" INDEX_NAME_CACHE_SID "' OR " \
252 "sql = '" INDEX_NAME_CACHE_NAME "' OR " \
253 "sql = '" TRIGGER_NAME_CACHE_TOLOWER_INSERT "' OR " \
254 "sql = '" TRIGGER_NAME_CACHE_TOLOWER_UPDATE "') " \
255 "WHEN 10 THEN 2 ELSE " \
256 "(CASE (SELECT count(*) FROM sqlite_master WHERE " \
257 "sql = '" TABLE_IDMAP_CACHE"' OR " \
258 "sql = '" INDEX_IDMAP_CACHE_SID_W2U "' OR " \
259 "sql = '" INDEX_IDMAP_CACHE_PID_U2W "' OR " \
260 "sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_INSERT "' OR " \
261 "sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE "' OR " \
262 "sql = '" TABLE_NAME_CACHE "' OR " \
263 "sql = '" INDEX_NAME_CACHE_SID "' OR " \
264 "sql = '" INDEX_NAME_CACHE_NAME "' OR " \
265 "sql = '" TRIGGER_NAME_CACHE_TOLOWER_INSERT "' OR " \
266 "sql = '" TRIGGER_NAME_CACHE_TOLOWER_UPDATE "') " \
267 "WHEN 10 THEN 3 ELSE -1 END) END) END) END AS version;"
269 #define CACHE_UPGRADE_FROM_v1_SQL \
270 "DROP TABLE idmap_cache;" \
271 "DROP TABLE name_cache;" \
274 #define CACHE_UPGRADE_FROM_v2_SQL \
275 "DROP TABLE idmap_cache;" \
276 "DROP TABLE name_cache;" \
279 #define CACHE_VERSION 3
282 #define TABLE_NAMERULES_v1 \
283 "CREATE TABLE namerules (" \
284 " is_user INTEGER NOT NULL," \
286 " winname TEXT NOT NULL," \
287 " is_nt4 INTEGER NOT NULL," \
288 " unixname NOT NULL," \
289 " w2u_order INTEGER," \
290 " u2w_order INTEGER" \
293 #define TABLE_NAMERULES_BODY \
295 " is_user INTEGER NOT NULL," \
296 " is_wuser INTEGER NOT NULL," \
298 " winname_display TEXT NOT NULL," \
300 " is_nt4 INTEGER NOT NULL," \
301 " unixname NOT NULL," \
302 " w2u_order INTEGER," \
303 " u2w_order INTEGER" \
306 #define TABLE_NAMERULES \
307 "CREATE TABLE namerules " \
310 #define INDEX_NAMERULES_W2U_v1 \
311 "CREATE UNIQUE INDEX namerules_w2u ON namerules" \
312 " (winname, windomain, is_user, w2u_order)"
314 #define INDEX_NAMERULES_W2U \
315 "CREATE UNIQUE INDEX namerules_w2u ON namerules" \
316 " (winname, windomain, is_user, is_wuser, w2u_order)"
318 #define INDEX_NAMERULES_U2W \
319 "CREATE UNIQUE INDEX namerules_u2w ON namerules" \
320 " (unixname, is_user, u2w_order)"
322 #define TRIGGER_NAMERULES_TOLOWER_BODY \
324 " UPDATE namerules SET winname = lower_utf8(winname_display)" \
325 " WHERE rowid = new.rowid;" \
328 #define TRIGGER_NAMERULES_TOLOWER_INSERT \
329 "CREATE TRIGGER namerules_tolower_name_insert " \
330 "AFTER INSERT ON namerules " \
331 TRIGGER_NAMERULES_TOLOWER_BODY
333 #define TRIGGER_NAMERULES_TOLOWER_UPDATE \
334 "CREATE TRIGGER namerules_tolower_name_update " \
335 "AFTER UPDATE ON namerules " \
336 TRIGGER_NAMERULES_TOLOWER_BODY
338 #define TRIGGER_NAMERULES_UNIQUE_BODY \
339 " SELECT CASE (SELECT count(*) FROM namerules AS n" \
340 " WHERE n.unixname = NEW.unixname AND" \
341 " n.is_user = NEW.is_user AND" \
342 " (n.winname != lower(NEW.winname_display) OR" \
343 " n.windomain != NEW.windomain ) AND" \
344 " n.u2w_order = NEW.u2w_order AND" \
345 " n.is_wuser != NEW.is_wuser) > 0" \
347 " raise(ROLLBACK, 'Conflicting w2u namerules')"\
351 #define TRIGGER_NAMERULES_UNIQUE_INSERT \
352 "CREATE TRIGGER namerules_unique_insert " \
353 "BEFORE INSERT ON namerules " \
355 TRIGGER_NAMERULES_UNIQUE_BODY
357 #define TRIGGER_NAMERULES_UNIQUE_UPDATE \
358 "CREATE TRIGGER namerules_unique_update " \
359 "BEFORE INSERT ON namerules " \
361 TRIGGER_NAMERULES_UNIQUE_BODY
363 #define DB_INSTALL_SQL \
364 TABLE_NAMERULES ";" \
365 INDEX_NAMERULES_W2U ";" \
366 INDEX_NAMERULES_U2W ";" \
367 TRIGGER_NAMERULES_TOLOWER_INSERT ";" \
368 TRIGGER_NAMERULES_TOLOWER_UPDATE ";" \
369 TRIGGER_NAMERULES_UNIQUE_INSERT ";" \
370 TRIGGER_NAMERULES_UNIQUE_UPDATE ";"
372 #define DB_VERSION_SQL \
373 "SELECT CASE (SELECT count(*) FROM sqlite_master) WHEN 0 THEN 0 ELSE " \
374 "(CASE (SELECT count(*) FROM sqlite_master WHERE " \
375 "sql = '" TABLE_NAMERULES_v1 "' OR " \
376 "sql = '" INDEX_NAMERULES_W2U_v1 "' OR " \
377 "sql = '" INDEX_NAMERULES_U2W "') " \
378 "WHEN 3 THEN 1 ELSE "\
379 "(CASE (SELECT count(*) FROM sqlite_master WHERE " \
380 "sql = '" TABLE_NAMERULES "' OR " \
381 "sql = '" INDEX_NAMERULES_W2U "' OR " \
382 "sql = '" INDEX_NAMERULES_U2W "' OR " \
383 "sql = '" TRIGGER_NAMERULES_TOLOWER_INSERT "' OR " \
384 "sql = '" TRIGGER_NAMERULES_TOLOWER_UPDATE "' OR " \
385 "sql = \"" TRIGGER_NAMERULES_UNIQUE_INSERT "\" OR " \
386 "sql = \"" TRIGGER_NAMERULES_UNIQUE_UPDATE "\") " \
387 "WHEN 7 THEN 2 ELSE -1 END) END) END AS version;"
389 /* SQL for upgrading an existing name rules DB. Includes DB_INSTALL_SQL */
390 #define DB_UPGRADE_FROM_v1_SQL \
391 "CREATE TABLE namerules_new " TABLE_NAMERULES_BODY ";" \
392 "INSERT INTO namerules_new SELECT is_user, is_user, windomain, " \
393 "winname, winname, is_nt4, unixname, w2u_order, u2w_order " \
395 "DROP TABLE namerules;" \
397 "INSERT INTO namerules SELECT * FROM namerules_new;" \
398 "DROP TABLE namerules_new;"
407 #endif /* _SCHEMA_H */