1*5696Snw141292 /* 2*5696Snw141292 * CDDL HEADER START 3*5696Snw141292 * 4*5696Snw141292 * The contents of this file are subject to the terms of the 5*5696Snw141292 * Common Development and Distribution License (the "License"). 6*5696Snw141292 * You may not use this file except in compliance with the License. 7*5696Snw141292 * 8*5696Snw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5696Snw141292 * or http://www.opensolaris.org/os/licensing. 10*5696Snw141292 * See the License for the specific language governing permissions 11*5696Snw141292 * and limitations under the License. 12*5696Snw141292 * 13*5696Snw141292 * When distributing Covered Code, include this CDDL HEADER in each 14*5696Snw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5696Snw141292 * If applicable, add the following below this CDDL HEADER, with the 16*5696Snw141292 * fields enclosed by brackets "[]" replaced with your own identifying 17*5696Snw141292 * information: Portions Copyright [yyyy] [name of copyright owner] 18*5696Snw141292 * 19*5696Snw141292 * CDDL HEADER END 20*5696Snw141292 */ 21*5696Snw141292 /* 22*5696Snw141292 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*5696Snw141292 * Use is subject to license terms. 24*5696Snw141292 */ 25*5696Snw141292 26*5696Snw141292 #ifndef _SCHEMA_H 27*5696Snw141292 #define _SCHEMA_H 28*5696Snw141292 29*5696Snw141292 #pragma ident "%Z%%M% %I% %E% SMI" 30*5696Snw141292 31*5696Snw141292 #ifdef __cplusplus 32*5696Snw141292 extern "C" { 33*5696Snw141292 #endif 34*5696Snw141292 35*5696Snw141292 /* 36*5696Snw141292 * Various macros (constant strings) containing: 37*5696Snw141292 * 38*5696Snw141292 * - CREATE TABLE/INDEX/TRIGGER/VIEW SQL 39*5696Snw141292 * - old versions of schema items that have changed 40*5696Snw141292 * - SQL to detect the version currently installed in a db 41*5696Snw141292 * - SQL to upgrade the schema from any older version to the current 42*5696Snw141292 * - the SQL to install the current version of the schema on a 43*5696Snw141292 * freshly created db is the SQL used to "upgrade" from "version 0" 44*5696Snw141292 * 45*5696Snw141292 * There is one set of such macros for the cache DB (CACHE_*) and 46*5696Snw141292 * another set for the persistent DB (DB_*). The macros ending in _SQL 47*5696Snw141292 * are used in arguments to init_db_instance(). 48*5696Snw141292 * 49*5696Snw141292 * Schema version detection SQL has the following form: 50*5696Snw141292 * 51*5696Snw141292 * SELECT CASE (SELECT count(*) FROM sqlite_master) WHEN 0 THEN 0 ELSE 52*5696Snw141292 * (CASE (SELECT count(*) FROM sqlite_master WHERE sql = <original schema> ...) 53*5696Snw141292 * WHEN <correct count> THEN 1 ELSE (CASE (<v2 schema>) WHEN ... THEN 2 54*5696Snw141292 * ELSE -1 END) END AS version; 55*5696Snw141292 * 56*5696Snw141292 * That is, check that there is no schema else that the current schema 57*5696Snw141292 * sql matches the original schema, else the next version, ... and 58*5696Snw141292 * return an integer identifying the schema. Version numbers returned: 59*5696Snw141292 * 60*5696Snw141292 * -1 -> unknown schema (shouldn't happen) 61*5696Snw141292 * 0 -> no schema (brand new DB, install latest schema) 62*5696Snw141292 * 1 -> original schema (if != latest, then upgrade) 63*5696Snw141292 * . -> ... (if != latest, then upgrade) 64*5696Snw141292 * n -> latest schema (nothing to do) 65*5696Snw141292 * 66*5696Snw141292 * Upgrade SQL for the cache DB is simple: drop everything, create 67*5696Snw141292 * latest schema. This means losing ephemeral mappings, so idmapd must 68*5696Snw141292 * tell the kernel about that in its registration call. 69*5696Snw141292 * 70*5696Snw141292 * Upgrade SQL for the persistent DB is simple: drop the indexes, create 71*5696Snw141292 * temporary tables with the latest schema, insert into those from the 72*5696Snw141292 * old tables (transforming the data in the process), then drop the old 73*5696Snw141292 * tables, create the latest schema, restore the data from the temp. 74*5696Snw141292 * tables and drop the temp tables. 75*5696Snw141292 * 76*5696Snw141292 * Complex, but it avoids all sorts of packaging install/upgrade 77*5696Snw141292 * complexity, requiring reboots on patch. 78*5696Snw141292 * 79*5696Snw141292 * Conventions: 80*5696Snw141292 * - each TABLE/INDEX gets its own macro, and the SQL therein must not 81*5696Snw141292 * end in a semi-colon (';) 82*5696Snw141292 * - macros are named * TABLE_* for tables, INDEX_* for indexes, 83*5696Snw141292 * *_VERSION_SQL for SQL for determining version number, 84*5696Snw141292 * *_UPGRADE_FROM_v<version>_SQL for SQL for upgrading from some 85*5696Snw141292 * schema, *_LATEST_SQL for SQL for installing the latest schema. 86*5696Snw141292 * - some macros nest expansions of other macros 87*5696Snw141292 * 88*5696Snw141292 * The latest schema has two columns for Windows user/group name in 89*5696Snw141292 * tables where there used to be one. One of those columns contains the 90*5696Snw141292 * name as it came from the user or from AD, the other is set via a 91*5696Snw141292 * TRIGGER to be the lower-case version of the first, and we always 92*5696Snw141292 * search (and index) by the latter. This is for case-insensitivity. 93*5696Snw141292 */ 94*5696Snw141292 #define TABLE_IDMAP_CACHE_v1 \ 95*5696Snw141292 "CREATE TABLE idmap_cache (" \ 96*5696Snw141292 " sidprefix TEXT," \ 97*5696Snw141292 " rid INTEGER," \ 98*5696Snw141292 " windomain TEXT," \ 99*5696Snw141292 " winname TEXT," \ 100*5696Snw141292 " pid INTEGER," \ 101*5696Snw141292 " unixname TEXT," \ 102*5696Snw141292 " is_user INTEGER," \ 103*5696Snw141292 " w2u INTEGER," \ 104*5696Snw141292 " u2w INTEGER," \ 105*5696Snw141292 " expiration INTEGER" \ 106*5696Snw141292 ")" 107*5696Snw141292 108*5696Snw141292 #define TABLE_IDMAP_CACHE \ 109*5696Snw141292 "CREATE TABLE idmap_cache " \ 110*5696Snw141292 "(" \ 111*5696Snw141292 " sidprefix TEXT," \ 112*5696Snw141292 " rid INTEGER," \ 113*5696Snw141292 " windomain TEXT," \ 114*5696Snw141292 " canon_winname TEXT," \ 115*5696Snw141292 " winname TEXT," \ 116*5696Snw141292 " pid INTEGER," \ 117*5696Snw141292 " unixname TEXT," \ 118*5696Snw141292 " is_user INTEGER," \ 119*5696Snw141292 " is_wuser INTEGER," \ 120*5696Snw141292 " w2u INTEGER," \ 121*5696Snw141292 " u2w INTEGER," \ 122*5696Snw141292 " expiration INTEGER" \ 123*5696Snw141292 ")" 124*5696Snw141292 125*5696Snw141292 #define INDEX_IDMAP_CACHE_SID_W2U_v1 \ 126*5696Snw141292 "CREATE UNIQUE INDEX idmap_cache_sid_w2u ON idmap_cache" \ 127*5696Snw141292 " (sidprefix, rid, w2u)" 128*5696Snw141292 129*5696Snw141292 #define INDEX_IDMAP_CACHE_SID_W2U \ 130*5696Snw141292 "CREATE UNIQUE INDEX idmap_cache_sid_w2u ON idmap_cache" \ 131*5696Snw141292 " (sidprefix, rid, is_user, w2u)" 132*5696Snw141292 133*5696Snw141292 #define INDEX_IDMAP_CACHE_PID_U2W \ 134*5696Snw141292 "CREATE UNIQUE INDEX idmap_cache_pid_u2w ON idmap_cache" \ 135*5696Snw141292 " (pid, is_user, u2w)" 136*5696Snw141292 137*5696Snw141292 #define TRIGGER_IDMAP_CACHE_TOLOWER_INSERT \ 138*5696Snw141292 "CREATE TRIGGER idmap_cache_tolower_name_insert " \ 139*5696Snw141292 "AFTER INSERT ON idmap_cache " \ 140*5696Snw141292 "BEGIN " \ 141*5696Snw141292 " UPDATE idmap_cache SET winname = lower_utf8(canon_winname)" \ 142*5696Snw141292 " WHERE rowid = new.rowid;" \ 143*5696Snw141292 "END" 144*5696Snw141292 145*5696Snw141292 #define TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE \ 146*5696Snw141292 "CREATE TRIGGER idmap_cache_tolower_name_update " \ 147*5696Snw141292 "AFTER UPDATE ON idmap_cache " \ 148*5696Snw141292 "BEGIN " \ 149*5696Snw141292 " UPDATE idmap_cache SET winname = lower_utf8(canon_winname)" \ 150*5696Snw141292 " WHERE rowid = new.rowid;" \ 151*5696Snw141292 "END" 152*5696Snw141292 153*5696Snw141292 #define TABLE_NAME_CACHE \ 154*5696Snw141292 "CREATE TABLE name_cache (" \ 155*5696Snw141292 " sidprefix TEXT," \ 156*5696Snw141292 " rid INTEGER," \ 157*5696Snw141292 " name TEXT," \ 158*5696Snw141292 " canon_name TEXT," \ 159*5696Snw141292 " domain TEXT," \ 160*5696Snw141292 " type INTEGER," \ 161*5696Snw141292 " expiration INTEGER" \ 162*5696Snw141292 ")" 163*5696Snw141292 164*5696Snw141292 #define TABLE_NAME_CACHE_v1 \ 165*5696Snw141292 "CREATE TABLE name_cache (" \ 166*5696Snw141292 " sidprefix TEXT," \ 167*5696Snw141292 " rid INTEGER," \ 168*5696Snw141292 " name TEXT," \ 169*5696Snw141292 " domain TEXT," \ 170*5696Snw141292 " type INTEGER," \ 171*5696Snw141292 " expiration INTEGER" \ 172*5696Snw141292 ")" 173*5696Snw141292 174*5696Snw141292 #define TRIGGER_NAME_CACHE_TOLOWER_INSERT \ 175*5696Snw141292 "CREATE TRIGGER name_cache_tolower_name_insert " \ 176*5696Snw141292 "AFTER INSERT ON name_cache " \ 177*5696Snw141292 "BEGIN " \ 178*5696Snw141292 " UPDATE name_cache SET name = lower_utf8(canon_name)" \ 179*5696Snw141292 " WHERE rowid = new.rowid;" \ 180*5696Snw141292 "END" 181*5696Snw141292 182*5696Snw141292 #define TRIGGER_NAME_CACHE_TOLOWER_UPDATE \ 183*5696Snw141292 "CREATE TRIGGER name_cache_tolower_name_update " \ 184*5696Snw141292 "AFTER UPDATE ON name_cache " \ 185*5696Snw141292 "BEGIN " \ 186*5696Snw141292 " UPDATE name_cache SET name = lower_utf8(canon_name)" \ 187*5696Snw141292 " WHERE rowid = new.rowid;" \ 188*5696Snw141292 "END" 189*5696Snw141292 190*5696Snw141292 #define INDEX_NAME_CACHE_SID \ 191*5696Snw141292 "CREATE UNIQUE INDEX name_cache_sid ON name_cache" \ 192*5696Snw141292 " (sidprefix, rid)" 193*5696Snw141292 194*5696Snw141292 #define INDEX_NAME_CACHE_NAME \ 195*5696Snw141292 "CREATE UNIQUE INDEX name_cache_name ON name_cache" \ 196*5696Snw141292 " (name, domain)" 197*5696Snw141292 198*5696Snw141292 #define CACHE_INSTALL_SQL \ 199*5696Snw141292 TABLE_IDMAP_CACHE ";" \ 200*5696Snw141292 INDEX_IDMAP_CACHE_SID_W2U ";" \ 201*5696Snw141292 INDEX_IDMAP_CACHE_PID_U2W ";" \ 202*5696Snw141292 TRIGGER_IDMAP_CACHE_TOLOWER_INSERT ";" \ 203*5696Snw141292 TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE ";" \ 204*5696Snw141292 TABLE_NAME_CACHE ";" \ 205*5696Snw141292 INDEX_NAME_CACHE_SID ";" \ 206*5696Snw141292 INDEX_NAME_CACHE_NAME ";" \ 207*5696Snw141292 TRIGGER_NAME_CACHE_TOLOWER_INSERT ";" \ 208*5696Snw141292 TRIGGER_NAME_CACHE_TOLOWER_UPDATE ";" 209*5696Snw141292 210*5696Snw141292 #define CACHE_VERSION_SQL \ 211*5696Snw141292 "SELECT CASE (SELECT count(*) FROM sqlite_master) WHEN 0 THEN 0 ELSE " \ 212*5696Snw141292 "(CASE (SELECT count(*) FROM sqlite_master WHERE " \ 213*5696Snw141292 "sql = '" TABLE_IDMAP_CACHE_v1 "' OR " \ 214*5696Snw141292 "sql = '" INDEX_IDMAP_CACHE_SID_W2U_v1 "' OR " \ 215*5696Snw141292 "sql = '" INDEX_IDMAP_CACHE_PID_U2W "' OR " \ 216*5696Snw141292 "sql = '" TABLE_NAME_CACHE_v1 "' OR " \ 217*5696Snw141292 "sql = '" INDEX_NAME_CACHE_SID "') " \ 218*5696Snw141292 "WHEN 5 THEN 1 ELSE " \ 219*5696Snw141292 "(CASE (SELECT count(*) FROM sqlite_master WHERE " \ 220*5696Snw141292 "sql = '" TABLE_IDMAP_CACHE"' OR " \ 221*5696Snw141292 "sql = '" INDEX_IDMAP_CACHE_SID_W2U "' OR " \ 222*5696Snw141292 "sql = '" INDEX_IDMAP_CACHE_PID_U2W "' OR " \ 223*5696Snw141292 "sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_INSERT "' OR " \ 224*5696Snw141292 "sql = '" TRIGGER_IDMAP_CACHE_TOLOWER_UPDATE "' OR " \ 225*5696Snw141292 "sql = '" TABLE_NAME_CACHE "' OR " \ 226*5696Snw141292 "sql = '" INDEX_NAME_CACHE_SID "' OR " \ 227*5696Snw141292 "sql = '" INDEX_NAME_CACHE_NAME "' OR " \ 228*5696Snw141292 "sql = '" TRIGGER_NAME_CACHE_TOLOWER_INSERT "' OR " \ 229*5696Snw141292 "sql = '" TRIGGER_NAME_CACHE_TOLOWER_UPDATE "') " \ 230*5696Snw141292 "WHEN 10 THEN 2 ELSE -1 END) END) END AS version;" 231*5696Snw141292 232*5696Snw141292 #define CACHE_UPGRADE_FROM_v1_SQL \ 233*5696Snw141292 "DROP TABLE idmap_cache;" \ 234*5696Snw141292 "DROP TABLE name_cache;" \ 235*5696Snw141292 CACHE_INSTALL_SQL 236*5696Snw141292 237*5696Snw141292 #define CACHE_VERSION 2 238*5696Snw141292 239*5696Snw141292 240*5696Snw141292 #define TABLE_NAMERULES_v1 \ 241*5696Snw141292 "CREATE TABLE namerules (" \ 242*5696Snw141292 " is_user INTEGER NOT NULL," \ 243*5696Snw141292 " windomain TEXT," \ 244*5696Snw141292 " winname TEXT NOT NULL," \ 245*5696Snw141292 " is_nt4 INTEGER NOT NULL," \ 246*5696Snw141292 " unixname NOT NULL," \ 247*5696Snw141292 " w2u_order INTEGER," \ 248*5696Snw141292 " u2w_order INTEGER" \ 249*5696Snw141292 ")" 250*5696Snw141292 251*5696Snw141292 #define TABLE_NAMERULES_BODY \ 252*5696Snw141292 "(" \ 253*5696Snw141292 " is_user INTEGER NOT NULL," \ 254*5696Snw141292 " is_wuser INTEGER NOT NULL," \ 255*5696Snw141292 " windomain TEXT," \ 256*5696Snw141292 " winname_display TEXT NOT NULL," \ 257*5696Snw141292 " winname TEXT," \ 258*5696Snw141292 " is_nt4 INTEGER NOT NULL," \ 259*5696Snw141292 " unixname NOT NULL," \ 260*5696Snw141292 " w2u_order INTEGER," \ 261*5696Snw141292 " u2w_order INTEGER" \ 262*5696Snw141292 ")" 263*5696Snw141292 264*5696Snw141292 #define TABLE_NAMERULES \ 265*5696Snw141292 "CREATE TABLE namerules " \ 266*5696Snw141292 TABLE_NAMERULES_BODY 267*5696Snw141292 268*5696Snw141292 #define INDEX_NAMERULES_W2U_v1 \ 269*5696Snw141292 "CREATE UNIQUE INDEX namerules_w2u ON namerules" \ 270*5696Snw141292 " (winname, windomain, is_user, w2u_order)" 271*5696Snw141292 272*5696Snw141292 #define INDEX_NAMERULES_W2U \ 273*5696Snw141292 "CREATE UNIQUE INDEX namerules_w2u ON namerules" \ 274*5696Snw141292 " (winname, windomain, is_user, is_wuser, w2u_order)" 275*5696Snw141292 276*5696Snw141292 #define INDEX_NAMERULES_U2W \ 277*5696Snw141292 "CREATE UNIQUE INDEX namerules_u2w ON namerules" \ 278*5696Snw141292 " (unixname, is_user, u2w_order)" 279*5696Snw141292 280*5696Snw141292 #define TRIGGER_NAMERULES_TOLOWER_BODY \ 281*5696Snw141292 "BEGIN " \ 282*5696Snw141292 " UPDATE namerules SET winname = lower_utf8(winname_display)" \ 283*5696Snw141292 " WHERE rowid = new.rowid;" \ 284*5696Snw141292 "END" 285*5696Snw141292 286*5696Snw141292 #define TRIGGER_NAMERULES_TOLOWER_INSERT \ 287*5696Snw141292 "CREATE TRIGGER namerules_tolower_name_insert " \ 288*5696Snw141292 "AFTER INSERT ON namerules " \ 289*5696Snw141292 TRIGGER_NAMERULES_TOLOWER_BODY 290*5696Snw141292 291*5696Snw141292 #define TRIGGER_NAMERULES_TOLOWER_UPDATE \ 292*5696Snw141292 "CREATE TRIGGER namerules_tolower_name_update " \ 293*5696Snw141292 "AFTER UPDATE ON namerules " \ 294*5696Snw141292 TRIGGER_NAMERULES_TOLOWER_BODY 295*5696Snw141292 296*5696Snw141292 #define TRIGGER_NAMERULES_UNIQUE_BODY \ 297*5696Snw141292 " SELECT CASE (SELECT count(*) FROM namerules AS n" \ 298*5696Snw141292 " WHERE n.unixname = NEW.unixname AND" \ 299*5696Snw141292 " n.is_user = NEW.is_user AND" \ 300*5696Snw141292 " (n.winname != lower(NEW.winname_display) OR" \ 301*5696Snw141292 " n.windomain != NEW.windomain ) AND" \ 302*5696Snw141292 " n.u2w_order = NEW.u2w_order AND" \ 303*5696Snw141292 " n.is_wuser != NEW.is_wuser) > 0" \ 304*5696Snw141292 " WHEN 1 THEN" \ 305*5696Snw141292 " raise(ROLLBACK, 'Conflicting w2u namerules')"\ 306*5696Snw141292 " END; " \ 307*5696Snw141292 "END" 308*5696Snw141292 309*5696Snw141292 #define TRIGGER_NAMERULES_UNIQUE_INSERT \ 310*5696Snw141292 "CREATE TRIGGER namerules_unique_insert " \ 311*5696Snw141292 "BEFORE INSERT ON namerules " \ 312*5696Snw141292 "BEGIN " \ 313*5696Snw141292 TRIGGER_NAMERULES_UNIQUE_BODY 314*5696Snw141292 315*5696Snw141292 #define TRIGGER_NAMERULES_UNIQUE_UPDATE \ 316*5696Snw141292 "CREATE TRIGGER namerules_unique_update " \ 317*5696Snw141292 "BEFORE INSERT ON namerules " \ 318*5696Snw141292 "BEGIN " \ 319*5696Snw141292 TRIGGER_NAMERULES_UNIQUE_BODY 320*5696Snw141292 321*5696Snw141292 #define DB_INSTALL_SQL \ 322*5696Snw141292 TABLE_NAMERULES ";" \ 323*5696Snw141292 INDEX_NAMERULES_W2U ";" \ 324*5696Snw141292 INDEX_NAMERULES_U2W ";" \ 325*5696Snw141292 TRIGGER_NAMERULES_TOLOWER_INSERT ";" \ 326*5696Snw141292 TRIGGER_NAMERULES_TOLOWER_UPDATE ";" \ 327*5696Snw141292 TRIGGER_NAMERULES_UNIQUE_INSERT ";" \ 328*5696Snw141292 TRIGGER_NAMERULES_UNIQUE_UPDATE ";" 329*5696Snw141292 330*5696Snw141292 #define DB_VERSION_SQL \ 331*5696Snw141292 "SELECT CASE (SELECT count(*) FROM sqlite_master) WHEN 0 THEN 0 ELSE " \ 332*5696Snw141292 "(CASE (SELECT count(*) FROM sqlite_master WHERE " \ 333*5696Snw141292 "sql = '" TABLE_NAMERULES_v1 "' OR " \ 334*5696Snw141292 "sql = '" INDEX_NAMERULES_W2U_v1 "' OR " \ 335*5696Snw141292 "sql = '" INDEX_NAMERULES_U2W "') " \ 336*5696Snw141292 "WHEN 3 THEN 1 ELSE "\ 337*5696Snw141292 "(CASE (SELECT count(*) FROM sqlite_master WHERE " \ 338*5696Snw141292 "sql = '" TABLE_NAMERULES "' OR " \ 339*5696Snw141292 "sql = '" INDEX_NAMERULES_W2U "' OR " \ 340*5696Snw141292 "sql = '" INDEX_NAMERULES_U2W "' OR " \ 341*5696Snw141292 "sql = '" TRIGGER_NAMERULES_TOLOWER_INSERT "' OR " \ 342*5696Snw141292 "sql = '" TRIGGER_NAMERULES_TOLOWER_UPDATE "' OR " \ 343*5696Snw141292 "sql = \"" TRIGGER_NAMERULES_UNIQUE_INSERT "\" OR " \ 344*5696Snw141292 "sql = \"" TRIGGER_NAMERULES_UNIQUE_UPDATE "\") " \ 345*5696Snw141292 "WHEN 7 THEN 2 ELSE -1 END) END) END AS version;" 346*5696Snw141292 347*5696Snw141292 /* SQL for upgrading an existing name rules DB. Includes DB_INSTALL_SQL */ 348*5696Snw141292 #define DB_UPGRADE_FROM_v1_SQL \ 349*5696Snw141292 "CREATE TABLE namerules_new " TABLE_NAMERULES_BODY ";" \ 350*5696Snw141292 "INSERT INTO namerules_new SELECT is_user, is_user, windomain, " \ 351*5696Snw141292 "winname, winname, is_nt4, unixname, w2u_order, u2w_order " \ 352*5696Snw141292 "FROM namerules;" \ 353*5696Snw141292 "DROP TABLE namerules;" \ 354*5696Snw141292 DB_INSTALL_SQL \ 355*5696Snw141292 "INSERT INTO namerules SELECT * FROM namerules_new;" \ 356*5696Snw141292 "DROP TABLE namerules_new;" 357*5696Snw141292 358*5696Snw141292 #define DB_VERSION 2 359*5696Snw141292 360*5696Snw141292 #ifdef __cplusplus 361*5696Snw141292 } 362*5696Snw141292 #endif 363*5696Snw141292 364*5696Snw141292 365*5696Snw141292 #endif /* _SCHEMA_H */ 366