Index: trunk/phase3/maintenance/ora/tables.sql |
— | — | @@ -1,443 +1,630 @@ |
| 2 | +DEFINE mw_prefix=''; |
2 | 3 | |
| 4 | + |
3 | 5 | CREATE SEQUENCE user_user_id_seq MINVALUE 0 START WITH 0; |
4 | | - |
5 | | -CREATE TABLE mwuser ( -- replace reserved word 'user' |
6 | | - user_id INTEGER NOT NULL PRIMARY KEY, |
7 | | - user_name VARCHAR(255) NOT NULL UNIQUE, |
8 | | - user_real_name CLOB, |
9 | | - user_password CLOB, |
10 | | - user_newpassword CLOB, |
11 | | - user_newpass_time TIMESTAMP WITH TIME ZONE, |
12 | | - user_token CHAR(32), |
13 | | - user_email CLOB, |
14 | | - user_email_token CHAR(32), |
15 | | - user_email_token_expires TIMESTAMP WITH TIME ZONE, |
16 | | - user_email_authenticated TIMESTAMP WITH TIME ZONE, |
| 6 | +CREATE TABLE &mw_prefix.mwuser ( -- replace reserved word 'user' |
| 7 | + user_id NUMBER NOT NULL, |
| 8 | + user_name VARCHAR2(255) NOT NULL, |
| 9 | + user_real_name VARCHAR2(512), |
| 10 | + user_password VARCHAR2(255), |
| 11 | + user_newpassword VARCHAR2(255), |
| 12 | + user_newpass_time TIMESTAMP(6) WITH TIME ZONE, |
| 13 | + user_token VARCHAR2(32), |
| 14 | + user_email VARCHAR2(255), |
| 15 | + user_email_token VARCHAR2(32), |
| 16 | + user_email_token_expires TIMESTAMP(6) WITH TIME ZONE, |
| 17 | + user_email_authenticated TIMESTAMP(6) WITH TIME ZONE, |
17 | 18 | user_options CLOB, |
18 | | - user_touched TIMESTAMP WITH TIME ZONE, |
19 | | - user_registration TIMESTAMP WITH TIME ZONE, |
20 | | - user_editcount INTEGER |
| 19 | + user_touched TIMESTAMP(6) WITH TIME ZONE, |
| 20 | + user_registration TIMESTAMP(6) WITH TIME ZONE, |
| 21 | + user_editcount NUMBER |
21 | 22 | ); |
22 | | -CREATE INDEX user_email_token_idx ON mwuser (user_email_token); |
| 23 | +ALTER TABLE &mw_prefix.mwuser ADD CONSTRAINT &mw_prefix.mwuser_pk PRIMARY KEY (user_id); |
| 24 | +CREATE UNIQUE INDEX &mw_prefix.mwuser_u01 ON &mw_prefix.mwuser (user_name); |
| 25 | +CREATE INDEX &mw_prefix.mwuser_i01 ON &mw_prefix.mwuser (user_email_token); |
23 | 26 | |
24 | 27 | -- Create a dummy user to satisfy fk contraints especially with revisions |
25 | | -INSERT INTO mwuser |
| 28 | +INSERT INTO &mw_prefix.mwuser |
26 | 29 | VALUES (user_user_id_seq.nextval,'Anonymous','',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, '', current_timestamp, current_timestamp, 0); |
27 | 30 | |
28 | | -CREATE TABLE user_groups ( |
29 | | - ug_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE CASCADE, |
30 | | - ug_group CHAR(16) NOT NULL |
| 31 | +CREATE TABLE &mw_prefix.user_groups ( |
| 32 | + ug_user NUMBER NULL REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE, |
| 33 | + ug_group VARCHAR2(16) NOT NULL |
31 | 34 | ); |
32 | | -CREATE UNIQUE INDEX user_groups_unique ON user_groups (ug_user, ug_group); |
| 35 | +CREATE UNIQUE INDEX &mw_prefix.user_groups_u01 ON &mw_prefix.user_groups (ug_user,ug_group); |
| 36 | +CREATE INDEX &mw_prefix.user_groups_i01 ON &mw_prefix.user_groups (ug_group); |
33 | 37 | |
34 | | -CREATE TABLE user_newtalk ( |
35 | | - user_id INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE, |
36 | | - user_ip VARCHAR(40) NULL |
| 38 | +CREATE TABLE &mw_prefix.user_newtalk ( |
| 39 | + user_id NUMBER NOT NULL REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE, |
| 40 | + user_ip VARCHAR2(40) NULL, |
| 41 | + user_last_timestamp TIMESTAMP(6) WITH TIME ZONE |
37 | 42 | ); |
38 | | -CREATE INDEX user_newtalk_id_idx ON user_newtalk (user_id); |
39 | | -CREATE INDEX user_newtalk_ip_idx ON user_newtalk (user_ip); |
| 43 | +CREATE INDEX &mw_prefix.user_newtalk_i01 ON &mw_prefix.user_newtalk (user_id); |
| 44 | +CREATE INDEX &mw_prefix.user_newtalk_i02 ON &mw_prefix.user_newtalk (user_ip); |
40 | 45 | |
| 46 | +CREATE TABLE &mw_prefix.user_properties ( |
| 47 | + up_user NUMBER NOT NULL, |
| 48 | + up_property VARCHAR2(32) NOT NULL, |
| 49 | + up_value BLOB |
| 50 | +); |
| 51 | +CREATE UNIQUE INDEX &mw_prefix.user_properties_u01 on &mw_prefix.user_properties (up_user,up_property); |
| 52 | +CREATE INDEX &mw_prefix.user_properties_i01 on &mw_prefix.user_properties (up_property); |
| 53 | + |
| 54 | + |
41 | 55 | CREATE SEQUENCE page_page_id_seq; |
42 | | -CREATE TABLE page ( |
43 | | - page_id INTEGER NOT NULL PRIMARY KEY, |
44 | | - page_namespace SMALLINT NOT NULL, |
45 | | - page_title VARCHAR(255) NOT NULL, |
46 | | - page_restrictions CLOB, |
47 | | - page_counter INTEGER DEFAULT 0 NOT NULL, |
48 | | - page_is_redirect CHAR DEFAULT 0 NOT NULL, |
49 | | - page_is_new CHAR DEFAULT 0 NOT NULL, |
50 | | - page_random NUMERIC(15,14) NOT NULL, |
51 | | - page_touched TIMESTAMP WITH TIME ZONE, |
52 | | - page_latest INTEGER NOT NULL, -- FK? |
53 | | - page_len INTEGER NOT NULL |
| 56 | +CREATE TABLE &mw_prefix.page ( |
| 57 | + page_id NUMBER NOT NULL, |
| 58 | + page_namespace NUMBER NOT NULL, |
| 59 | + page_title VARCHAR2(255) NOT NULL, |
| 60 | + page_restrictions VARCHAR2(255), |
| 61 | + page_counter NUMBER DEFAULT 0 NOT NULL, |
| 62 | + page_is_redirect CHAR(1) DEFAULT 0 NOT NULL, |
| 63 | + page_is_new CHAR(1) DEFAULT 0 NOT NULL, |
| 64 | + page_random NUMBER(15,14) NOT NULL, |
| 65 | + page_touched TIMESTAMP(6) WITH TIME ZONE, |
| 66 | + page_latest NUMBER NOT NULL, -- FK? |
| 67 | + page_len NUMBER NOT NULL |
54 | 68 | ); |
55 | | -CREATE UNIQUE INDEX page_unique_name ON page (page_namespace, page_title); |
56 | | -CREATE INDEX page_random_idx ON page (page_random); |
57 | | -CREATE INDEX page_len_idx ON page (page_len); |
| 69 | +ALTER TABLE &mw_prefix.page ADD CONSTRAINT &mw_prefix.page_pk PRIMARY KEY (page_id); |
| 70 | +CREATE UNIQUE INDEX &mw_prefix.page_u01 ON &mw_prefix.page (page_namespace,page_title); |
| 71 | +CREATE INDEX &mw_prefix.page_i01 ON &mw_prefix.page (page_random); |
| 72 | +CREATE INDEX &mw_prefix.page_i02 ON &mw_prefix.page (page_len); |
58 | 73 | |
59 | | -CREATE TRIGGER page_set_random BEFORE INSERT ON page |
| 74 | +CREATE TRIGGER &mw_prefix.page_set_random BEFORE INSERT ON &mw_prefix.page |
60 | 75 | FOR EACH ROW WHEN (new.page_random IS NULL) |
61 | 76 | BEGIN |
62 | | - SELECT dbms_random.value INTO :new.page_random FROM dual; |
| 77 | + SELECT dbms_random.value INTO :NEW.page_random FROM dual; |
63 | 78 | END; |
64 | 79 | / |
65 | 80 | |
66 | 81 | CREATE SEQUENCE rev_rev_id_val; |
67 | | -CREATE TABLE revision ( |
68 | | - rev_id INTEGER NOT NULL PRIMARY KEY, |
69 | | - rev_page INTEGER NULL REFERENCES page (page_id) ON DELETE CASCADE, |
70 | | - rev_text_id INTEGER NULL, -- FK |
71 | | - rev_comment CLOB, |
72 | | - rev_user INTEGER NOT NULL REFERENCES mwuser(user_id), |
73 | | - rev_user_text VARCHAR(255) NOT NULL, |
74 | | - rev_timestamp TIMESTAMP WITH TIME ZONE NOT NULL, |
75 | | - rev_minor_edit CHAR DEFAULT '0' NOT NULL, |
76 | | - rev_deleted CHAR DEFAULT '0' NOT NULL, |
77 | | - rev_len INTEGER NULL, |
78 | | - rev_parent_id INTEGER DEFAULT NULL |
| 82 | +CREATE TABLE &mw_prefix.revision ( |
| 83 | + rev_id NUMBER NOT NULL, |
| 84 | + rev_page NUMBER NULL REFERENCES &mw_prefix.page (page_id) ON DELETE CASCADE, |
| 85 | + rev_text_id NUMBER NULL, |
| 86 | + rev_comment VARCHAR2(255), |
| 87 | + rev_user NUMBER NOT NULL REFERENCES &mw_prefix.mwuser(user_id), |
| 88 | + rev_user_text VARCHAR2(255) NOT NULL, |
| 89 | + rev_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL, |
| 90 | + rev_minor_edit CHAR(1) DEFAULT '0' NOT NULL, |
| 91 | + rev_deleted CHAR(1) DEFAULT '0' NOT NULL, |
| 92 | + rev_len NUMBER NULL, |
| 93 | + rev_parent_id NUMBER DEFAULT NULL |
79 | 94 | ); |
80 | | -CREATE UNIQUE INDEX revision_unique ON revision (rev_page, rev_id); |
81 | | -CREATE INDEX rev_text_id_idx ON revision (rev_text_id); |
82 | | -CREATE INDEX rev_timestamp_idx ON revision (rev_timestamp); |
83 | | -CREATE INDEX rev_user_idx ON revision (rev_user); |
84 | | -CREATE INDEX rev_user_text_idx ON revision (rev_user_text); |
| 95 | +ALTER TABLE &mw_prefix.revision ADD CONSTRAINT &mw_prefix.revision_pk PRIMARY KEY (rev_id); |
| 96 | +CREATE UNIQUE INDEX &mw_prefix.revision_u01 ON &mw_prefix.revision (rev_page, rev_id); |
| 97 | +CREATE INDEX &mw_prefix.revision_i01 ON &mw_prefix.revision (rev_timestamp); |
| 98 | +CREATE INDEX &mw_prefix.revision_i02 ON &mw_prefix.revision (rev_page,rev_timestamp); |
| 99 | +CREATE INDEX &mw_prefix.revision_i03 ON &mw_prefix.revision (rev_user,rev_timestamp); |
| 100 | +CREATE INDEX &mw_prefix.revision_i04 ON &mw_prefix.revision (rev_user_text,rev_timestamp); |
85 | 101 | |
86 | | - |
87 | 102 | CREATE SEQUENCE text_old_id_val; |
88 | | -CREATE TABLE pagecontent ( -- replaces reserved word 'text' |
89 | | - old_id INTEGER NOT NULL PRIMARY KEY, |
| 103 | +CREATE TABLE &mw_prefix.pagecontent ( -- replaces reserved word 'text' |
| 104 | + old_id NUMBER NOT NULL, |
90 | 105 | old_text CLOB, |
91 | | - old_flags CLOB |
| 106 | + old_flags VARCHAR2(255) |
92 | 107 | ); |
| 108 | +ALTER TABLE &mw_prefix.pagecontent ADD CONSTRAINT &mw_prefix.pagecontent_pk PRIMARY KEY (old_id); |
93 | 109 | |
94 | | - |
95 | | -CREATE SEQUENCE pr_id_val; |
96 | | -CREATE TABLE page_restrictions ( |
97 | | - pr_id INTEGER NOT NULL UNIQUE, |
98 | | - pr_page INTEGER NULL REFERENCES page (page_id) ON DELETE CASCADE, |
99 | | - pr_type VARCHAR(255) NOT NULL, |
100 | | - pr_level VARCHAR(255) NOT NULL, |
101 | | - pr_cascade SMALLINT NOT NULL, |
102 | | - pr_user INTEGER NULL, |
103 | | - pr_expiry TIMESTAMP WITH TIME ZONE NULL |
104 | | -); |
105 | | -ALTER TABLE page_restrictions ADD CONSTRAINT page_restrictions_pk PRIMARY KEY (pr_page,pr_type); |
106 | | - |
107 | | -CREATE TABLE archive ( |
108 | | - ar_namespace SMALLINT NOT NULL, |
109 | | - ar_title VARCHAR(255) NOT NULL, |
| 110 | +CREATE TABLE &mw_prefix.archive ( |
| 111 | + ar_namespace NUMBER NOT NULL, |
| 112 | + ar_title VARCHAR2(255) NOT NULL, |
110 | 113 | ar_text CLOB, |
111 | | - ar_comment CLOB, |
112 | | - ar_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, |
113 | | - ar_user_text CLOB NOT NULL, |
114 | | - ar_timestamp TIMESTAMP WITH TIME ZONE NOT NULL, |
115 | | - ar_minor_edit CHAR DEFAULT '0' NOT NULL, |
116 | | - ar_flags CLOB, |
117 | | - ar_rev_id INTEGER, |
118 | | - ar_text_id INTEGER, |
119 | | - ar_deleted INTEGER DEFAULT '0' NOT NULL |
| 114 | + ar_comment VARCHAR2(255), |
| 115 | + ar_user NUMBER NULL REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL, |
| 116 | + ar_user_text VARCHAR2(255) NOT NULL, |
| 117 | + ar_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL, |
| 118 | + ar_minor_edit CHAR(1) DEFAULT '0' NOT NULL, |
| 119 | + ar_flags VARCHAR2(255), |
| 120 | + ar_rev_id NUMBER, |
| 121 | + ar_text_id NUMBER, |
| 122 | + ar_deleted NUMBER DEFAULT '0' NOT NULL |
120 | 123 | ); |
121 | | -CREATE INDEX archive_name_title_timestamp ON archive (ar_namespace,ar_title,ar_timestamp); |
| 124 | +CREATE INDEX &mw_prefix.archive_i01 ON &mw_prefix.archive (ar_namespace,ar_title,ar_timestamp); |
| 125 | +CREATE INDEX &mw_prefix.archive_i02 ON &mw_prefix.archive (ar_user_text,ar_timestamp); |
122 | 126 | |
123 | | -CREATE TABLE redirect ( |
124 | | - rd_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
125 | | - rd_namespace SMALLINT NOT NULL, |
126 | | - rd_title VARCHAR(255) NOT NULL |
| 127 | + |
| 128 | +CREATE TABLE &mw_prefix.pagelinks ( |
| 129 | + pl_from NUMBER NOT NULL REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE, |
| 130 | + pl_namespace NUMBER NOT NULL, |
| 131 | + pl_title VARCHAR2(255) NOT NULL |
127 | 132 | ); |
128 | | -CREATE INDEX redirect_ns_title ON redirect (rd_namespace,rd_title,rd_from); |
| 133 | +CREATE UNIQUE INDEX &mw_prefix.pagelinks_u01 ON &mw_prefix.pagelinks (pl_from,pl_namespace,pl_title); |
| 134 | +CREATE UNIQUE INDEX &mw_prefix.pagelinks_u02 ON &mw_prefix.pagelinks (pl_namespace,pl_title,pl_from); |
129 | 135 | |
130 | | - |
131 | | -CREATE TABLE pagelinks ( |
132 | | - pl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
133 | | - pl_namespace SMALLINT NOT NULL, |
134 | | - pl_title VARCHAR(255) NOT NULL |
| 136 | +CREATE TABLE &mw_prefix.templatelinks ( |
| 137 | + tl_from NUMBER NOT NULL REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE, |
| 138 | + tl_namespace NUMBER NOT NULL, |
| 139 | + tl_title VARCHAR2(255) NOT NULL |
135 | 140 | ); |
136 | | -CREATE UNIQUE INDEX pagelink_unique ON pagelinks (pl_from,pl_namespace,pl_title); |
| 141 | +CREATE UNIQUE INDEX &mw_prefix.templatelinks_u01 ON &mw_prefix.templatelinks (tl_from,tl_namespace,tl_title); |
| 142 | +CREATE UNIQUE INDEX &mw_prefix.templatelinks_u02 ON &mw_prefix.templatelinks (tl_namespace,tl_title,tl_from); |
137 | 143 | |
138 | | -CREATE TABLE templatelinks ( |
139 | | - tl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
140 | | - tl_namespace INTEGER NOT NULL, |
141 | | - tl_title VARCHAR(255) NOT NULL |
| 144 | +CREATE TABLE &mw_prefix.imagelinks ( |
| 145 | + il_from NUMBER NOT NULL REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE, |
| 146 | + il_to VARCHAR2(255) NOT NULL |
142 | 147 | ); |
143 | | -CREATE UNIQUE INDEX templatelinks_unique ON templatelinks (tl_namespace,tl_title,tl_from); |
| 148 | +CREATE UNIQUE INDEX &mw_prefix.imagelinks_u01 ON &mw_prefix.imagelinks (il_from,il_to); |
| 149 | +CREATE UNIQUE INDEX &mw_prefix.imagelinks_u02 ON &mw_prefix.imagelinks (il_to,il_from); |
144 | 150 | |
145 | | -CREATE TABLE imagelinks ( |
146 | | - il_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
147 | | - il_to VARCHAR(255) NOT NULL |
| 151 | + |
| 152 | +CREATE TABLE &mw_prefix.categorylinks ( |
| 153 | + cl_from NUMBER NOT NULL REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE, |
| 154 | + cl_to VARCHAR2(255) NOT NULL, |
| 155 | + cl_sortkey VARCHAR2(255), |
| 156 | + cl_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL |
148 | 157 | ); |
149 | | -CREATE UNIQUE INDEX il_from ON imagelinks (il_to,il_from); |
| 158 | +CREATE UNIQUE INDEX &mw_prefix.categorylinks_u01 ON &mw_prefix.categorylinks (cl_from,cl_to); |
| 159 | +CREATE INDEX &mw_prefix.categorylinks_i01 ON &mw_prefix.categorylinks (cl_to,cl_sortkey,cl_from); |
| 160 | +CREATE INDEX &mw_prefix.categorylinks_i02 ON &mw_prefix.categorylinks (cl_to,cl_timestamp); |
150 | 161 | |
151 | | -CREATE TABLE categorylinks ( |
152 | | - cl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
153 | | - cl_to VARCHAR(255) NOT NULL, |
154 | | - cl_sortkey VARCHAR(86), |
155 | | - cl_timestamp TIMESTAMP WITH TIME ZONE NOT NULL |
| 162 | +CREATE SEQUENCE category_cat_id_val; |
| 163 | +CREATE TABLE &mw_prefix.category ( |
| 164 | + cat_id NUMBER NOT NULL, |
| 165 | + cat_title VARCHAR2(255) NOT NULL, |
| 166 | + cat_pages NUMBER DEFAULT 0 NOT NULL, |
| 167 | + cat_subcats NUMBER DEFAULT 0 NOT NULL, |
| 168 | + cat_files NUMBER DEFAULT 0 NOT NULL, |
| 169 | + cat_hidden NUMBER DEFAULT 0 NOT NULL |
156 | 170 | ); |
157 | | -CREATE UNIQUE INDEX cl_from ON categorylinks (cl_from, cl_to); |
158 | | -CREATE INDEX cl_sortkey ON categorylinks (cl_to, cl_sortkey); |
| 171 | +ALTER TABLE &mw_prefix.category ADD CONSTRAINT &mw_prefix.category_pk PRIMARY KEY (cat_id); |
| 172 | +CREATE UNIQUE INDEX &mw_prefix.category_u01 ON &mw_prefix.category (cat_title); |
| 173 | +CREATE INDEX &mw_prefix.category_i01 ON &mw_prefix.category (cat_pages); |
159 | 174 | |
160 | | -CREATE TABLE externallinks ( |
161 | | - el_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
162 | | - el_to VARCHAR(2048) NOT NULL, |
163 | | - el_index CLOB NOT NULL |
| 175 | +CREATE TABLE &mw_prefix.externallinks ( |
| 176 | + el_from NUMBER NOT NULL REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE, |
| 177 | + el_to VARCHAR2(2048) NOT NULL, |
| 178 | + el_index VARCHAR2(2048) NOT NULL |
164 | 179 | ); |
| 180 | +CREATE INDEX &mw_prefix.externallinks_i01 ON &mw_prefix.externallinks (el_from, el_to); |
| 181 | +CREATE INDEX &mw_prefix.externallinks_i02 ON &mw_prefix.externallinks (el_to, el_from); |
| 182 | +CREATE INDEX &mw_prefix.externallinks_i03 ON &mw_prefix.externallinks (el_index); |
165 | 183 | |
166 | | -CREATE TABLE langlinks ( |
167 | | - ll_from INTEGER NOT NULL REFERENCES page (page_id) ON DELETE CASCADE, |
168 | | - ll_lang VARCHAR(10), |
169 | | - ll_title VARCHAR(255) |
| 184 | +CREATE TABLE &mw_prefix.langlinks ( |
| 185 | + ll_from NUMBER NOT NULL REFERENCES &mw_prefix.page (page_id) ON DELETE CASCADE, |
| 186 | + ll_lang VARCHAR2(20), |
| 187 | + ll_title VARCHAR2(255) |
170 | 188 | ); |
171 | | -CREATE UNIQUE INDEX langlinks_unique ON langlinks (ll_from,ll_lang); |
172 | | -CREATE INDEX langlinks_lang_title ON langlinks (ll_lang,ll_title); |
| 189 | +CREATE UNIQUE INDEX &mw_prefix.langlinks_u01 ON &mw_prefix.langlinks (ll_from, ll_lang); |
| 190 | +CREATE INDEX &mw_prefix.langlinks_i01 ON &mw_prefix.langlinks (ll_lang, ll_title); |
173 | 191 | |
174 | | - |
175 | | -CREATE TABLE site_stats ( |
176 | | - ss_row_id INTEGER NOT NULL UNIQUE, |
177 | | - ss_total_views INTEGER DEFAULT 0, |
178 | | - ss_total_edits INTEGER DEFAULT 0, |
179 | | - ss_good_articles INTEGER DEFAULT 0, |
180 | | - ss_total_pages INTEGER DEFAULT -1, |
181 | | - ss_users INTEGER DEFAULT -1, |
182 | | - ss_admins INTEGER DEFAULT -1, |
183 | | - ss_images INTEGER DEFAULT 0 |
| 192 | +CREATE TABLE &mw_prefix.site_stats ( |
| 193 | + ss_row_id NUMBER NOT NULL , |
| 194 | + ss_total_views NUMBER DEFAULT 0, |
| 195 | + ss_total_edits NUMBER DEFAULT 0, |
| 196 | + ss_good_articles NUMBER DEFAULT 0, |
| 197 | + ss_total_pages NUMBER DEFAULT -1, |
| 198 | + ss_users NUMBER DEFAULT -1, |
| 199 | + ss_active_users NUMBER DEFAULT -1, |
| 200 | + ss_admins NUMBER DEFAULT -1, |
| 201 | + ss_images NUMBER DEFAULT 0 |
184 | 202 | ); |
| 203 | +CREATE UNIQUE INDEX &mw_prefix.site_stats_u01 ON &mw_prefix.site_stats (ss_row_id); |
185 | 204 | |
186 | | -CREATE TABLE hitcounter ( |
187 | | - hc_id INTEGER NOT NULL |
| 205 | +CREATE TABLE &mw_prefix.hitcounter ( |
| 206 | + hc_id NUMBER NOT NULL |
188 | 207 | ); |
189 | 208 | |
190 | | - |
191 | 209 | CREATE SEQUENCE ipblocks_ipb_id_val; |
192 | | -CREATE TABLE ipblocks ( |
193 | | - ipb_id INTEGER NOT NULL PRIMARY KEY, |
194 | | - ipb_address VARCHAR(255) NULL, |
195 | | - ipb_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, |
196 | | - ipb_by INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE, |
197 | | - ipb_reason VARCHAR(255) NOT NULL, |
198 | | - ipb_timestamp TIMESTAMP WITH TIME ZONE NOT NULL, |
199 | | - ipb_auto CHAR DEFAULT '0' NOT NULL, |
200 | | - ipb_anon_only CHAR DEFAULT '0' NOT NULL, |
201 | | - ipb_create_account CHAR DEFAULT '1' NOT NULL, |
202 | | - ipb_enable_autoblock CHAR DEFAULT '1' NOT NULL, |
203 | | - ipb_expiry TIMESTAMP WITH TIME ZONE NOT NULL, |
204 | | - ipb_range_start CHAR(8), |
205 | | - ipb_range_end CHAR(8), |
206 | | - ipb_deleted INTEGER DEFAULT '0' NOT NULL |
| 210 | +CREATE TABLE &mw_prefix.ipblocks ( |
| 211 | + ipb_id NUMBER NOT NULL, |
| 212 | + ipb_address VARCHAR2(255) NULL, |
| 213 | + ipb_user NUMBER NULL REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL, |
| 214 | + ipb_by NUMBER NOT NULL REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE, |
| 215 | + ipb_by_text VARCHAR2(255) NOT NULL, |
| 216 | + ipb_reason VARCHAR2(255) NOT NULL, |
| 217 | + ipb_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL, |
| 218 | + ipb_auto CHAR(1) DEFAULT '0' NOT NULL, |
| 219 | + ipb_anon_only CHAR(1) DEFAULT '0' NOT NULL, |
| 220 | + ipb_create_account CHAR(1) DEFAULT '1' NOT NULL, |
| 221 | + ipb_enable_autoblock CHAR(1) DEFAULT '1' NOT NULL, |
| 222 | + ipb_expiry TIMESTAMP(6) WITH TIME ZONE NOT NULL, |
| 223 | + ipb_range_start VARCHAR2(255), |
| 224 | + ipb_range_end VARCHAR2(255), |
| 225 | + ipb_deleted CHAR(1) DEFAULT '0' NOT NULL, |
| 226 | + ipb_block_email CHAR(1) DEFAULT '0' NOT NULL, |
| 227 | + ipb_allow_usertalk CHAR(1) DEFAULT '0' NOT NULL |
207 | 228 | ); |
208 | | -CREATE INDEX ipb_address ON ipblocks (ipb_address); |
209 | | -CREATE INDEX ipb_user ON ipblocks (ipb_user); |
210 | | -CREATE INDEX ipb_range ON ipblocks (ipb_range_start,ipb_range_end); |
| 229 | +ALTER TABLE &mw_prefix.ipblocks ADD CONSTRAINT &mw_prefix.ipblocks_pk PRIMARY KEY (ipb_id); |
| 230 | +CREATE UNIQUE INDEX &mw_prefix.ipblocks_u01 ON &mw_prefix.ipblocks (ipb_address, ipb_user, ipb_auto, ipb_anon_only); |
| 231 | +CREATE INDEX &mw_prefix.ipblocks_i01 ON &mw_prefix.ipblocks (ipb_user); |
| 232 | +CREATE INDEX &mw_prefix.ipblocks_i02 ON &mw_prefix.ipblocks (ipb_range_start, ipb_range_end); |
| 233 | +CREATE INDEX &mw_prefix.ipblocks_i03 ON &mw_prefix.ipblocks (ipb_timestamp); |
| 234 | +CREATE INDEX &mw_prefix.ipblocks_i04 ON &mw_prefix.ipblocks (ipb_expiry); |
211 | 235 | |
212 | | - |
213 | 236 | CREATE TABLE image ( |
214 | | - img_name VARCHAR(255) NOT NULL PRIMARY KEY, |
215 | | - img_size INTEGER NOT NULL, |
216 | | - img_width INTEGER NOT NULL, |
217 | | - img_height INTEGER NOT NULL, |
| 237 | + img_name VARCHAR2(255) NOT NULL, |
| 238 | + img_size NUMBER NOT NULL, |
| 239 | + img_width NUMBER NOT NULL, |
| 240 | + img_height NUMBER NOT NULL, |
218 | 241 | img_metadata CLOB, |
219 | | - img_bits SMALLINT, |
220 | | - img_media_type CLOB, |
221 | | - img_major_mime CLOB DEFAULT 'unknown', |
222 | | - img_minor_mime CLOB DEFAULT 'unknown', |
223 | | - img_description CLOB, |
224 | | - img_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, |
225 | | - img_user_text CLOB NOT NULL, |
226 | | - img_timestamp TIMESTAMP WITH TIME ZONE |
| 242 | + img_bits NUMBER, |
| 243 | + img_media_type VARCHAR2(32), |
| 244 | + img_major_mime VARCHAR2(32) DEFAULT 'unknown', |
| 245 | + img_minor_mime VARCHAR2(32) DEFAULT 'unknown', |
| 246 | + img_description VARCHAR2(255), |
| 247 | + img_user NUMBER NULL REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL, |
| 248 | + img_user_text VARCHAR2(255) NOT NULL, |
| 249 | + img_timestamp TIMESTAMP(6) WITH TIME ZONE, |
| 250 | + img_sha1 VARCHAR2(32) |
227 | 251 | ); |
228 | | -CREATE INDEX img_size_idx ON image (img_size); |
229 | | -CREATE INDEX img_timestamp_idx ON image (img_timestamp); |
| 252 | +ALTER TABLE &mw_prefix.image ADD CONSTRAINT &mw_prefix.image_pk PRIMARY KEY (img_name); |
| 253 | +CREATE INDEX &mw_prefix.image_i01 ON &mw_prefix.image (img_user_text,img_timestamp); |
| 254 | +CREATE INDEX &mw_prefix.image_i02 ON &mw_prefix.image (img_size); |
| 255 | +CREATE INDEX &mw_prefix.image_i03 ON &mw_prefix.image (img_timestamp); |
| 256 | +CREATE INDEX &mw_prefix.image_i04 ON &mw_prefix.image (img_sha1); |
230 | 257 | |
231 | | -CREATE TABLE oldimage ( |
232 | | - oi_name VARCHAR(255) NOT NULL REFERENCES image(img_name), |
233 | | - oi_archive_name VARCHAR(255), |
234 | | - oi_size INTEGER NOT NULL, |
235 | | - oi_width INTEGER NOT NULL, |
236 | | - oi_height INTEGER NOT NULL, |
237 | | - oi_bits SMALLINT NOT NULL, |
238 | | - oi_description CLOB, |
239 | | - oi_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, |
240 | | - oi_user_text CLOB NOT NULL, |
241 | | - oi_timestamp TIMESTAMP WITH TIME ZONE NOT NULL, |
242 | | - oi_metadata CLOB, |
243 | | - oi_media_type VARCHAR(10) DEFAULT NULL, |
244 | | - oi_major_mime VARCHAR(11) DEFAULT 'unknown', |
245 | | - oi_minor_mime VARCHAR(32) DEFAULT 'unknown', |
246 | | - oi_deleted INTEGER DEFAULT 0 NOT NULL |
| 258 | + |
| 259 | +CREATE TABLE &mw_prefix.oldimage ( |
| 260 | + oi_name VARCHAR2(255) NOT NULL REFERENCES &mw_prefix.image(img_name), |
| 261 | + oi_archive_name VARCHAR2(255), |
| 262 | + oi_size NUMBER NOT NULL, |
| 263 | + oi_width NUMBER NOT NULL, |
| 264 | + oi_height NUMBER NOT NULL, |
| 265 | + oi_bits NUMBER NOT NULL, |
| 266 | + oi_description VARCHAR2(255), |
| 267 | + oi_user NUMBER NULL REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL, |
| 268 | + oi_user_text VARCHAR2(255) NOT NULL, |
| 269 | + oi_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL, |
| 270 | + oi_metadata CLOB, |
| 271 | + oi_media_type VARCHAR2(32) DEFAULT NULL, |
| 272 | + oi_major_mime VARCHAR2(32) DEFAULT 'unknown', |
| 273 | + oi_minor_mime VARCHAR2(32) DEFAULT 'unknown', |
| 274 | + oi_deleted NUMBER DEFAULT 0 NOT NULL, |
| 275 | + oi_sha1 VARCHAR2(32) |
247 | 276 | ); |
248 | | -CREATE INDEX oi_name_timestamp ON oldimage (oi_name,oi_timestamp); |
249 | | -CREATE INDEX oi_name_archive_name ON oldimage (oi_name,oi_archive_name); |
| 277 | +CREATE INDEX &mw_prefix.oldimage_i01 ON &mw_prefix.oldimage (oi_user_text,oi_timestamp); |
| 278 | +CREATE INDEX &mw_prefix.oldimage_i02 ON &mw_prefix.oldimage (oi_name,oi_timestamp); |
| 279 | +CREATE INDEX &mw_prefix.oldimage_i03 ON &mw_prefix.oldimage (oi_name,oi_archive_name); |
| 280 | +CREATE INDEX &mw_prefix.oldimage_i04 ON &mw_prefix.oldimage (oi_sha1); |
250 | 281 | |
| 282 | + |
251 | 283 | CREATE SEQUENCE filearchive_fa_id_seq; |
252 | | -CREATE TABLE filearchive ( |
253 | | - fa_id INTEGER NOT NULL PRIMARY KEY, |
254 | | - fa_name VARCHAR(255) NOT NULL, |
255 | | - fa_archive_name VARCHAR(255), |
256 | | - fa_storage_group VARCHAR(16), |
257 | | - fa_storage_key CHAR(64), |
258 | | - fa_deleted_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, |
259 | | - fa_deleted_timestamp TIMESTAMP WITH TIME ZONE NOT NULL, |
| 284 | +CREATE TABLE &mw_prefix.filearchive ( |
| 285 | + fa_id NUMBER NOT NULL, |
| 286 | + fa_name VARCHAR2(255) NOT NULL, |
| 287 | + fa_archive_name VARCHAR2(255), |
| 288 | + fa_storage_group VARCHAR2(16), |
| 289 | + fa_storage_key VARCHAR2(64), |
| 290 | + fa_deleted_user NUMBER NULL REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL, |
| 291 | + fa_deleted_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL, |
260 | 292 | fa_deleted_reason CLOB, |
261 | | - fa_size SMALLINT NOT NULL, |
262 | | - fa_width SMALLINT NOT NULL, |
263 | | - fa_height SMALLINT NOT NULL, |
| 293 | + fa_size NUMBER NOT NULL, |
| 294 | + fa_width NUMBER NOT NULL, |
| 295 | + fa_height NUMBER NOT NULL, |
264 | 296 | fa_metadata CLOB, |
265 | | - fa_bits SMALLINT, |
266 | | - fa_media_type CLOB, |
267 | | - fa_major_mime CLOB DEFAULT 'unknown', |
268 | | - fa_minor_mime CLOB DEFAULT 'unknown', |
269 | | - fa_description CLOB NOT NULL, |
270 | | - fa_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, |
271 | | - fa_user_text CLOB NOT NULL, |
272 | | - fa_timestamp TIMESTAMP WITH TIME ZONE, |
273 | | - fa_deleted INTEGER DEFAULT '0' NOT NULL |
| 297 | + fa_bits NUMBER, |
| 298 | + fa_media_type VARCHAR2(32) DEFAULT NULL, |
| 299 | + fa_major_mime VARCHAR2(32) DEFAULT 'unknown', |
| 300 | + fa_minor_mime VARCHAR2(32) DEFAULT 'unknown', |
| 301 | + fa_description VARCHAR2(255) NOT NULL, |
| 302 | + fa_user NUMBER NULL REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL, |
| 303 | + fa_user_text VARCHAR2(255) NOT NULL, |
| 304 | + fa_timestamp TIMESTAMP(6) WITH TIME ZONE, |
| 305 | + fa_deleted NUMBER DEFAULT '0' NOT NULL |
274 | 306 | ); |
275 | | -CREATE INDEX fa_name_time ON filearchive (fa_name, fa_timestamp); |
276 | | -CREATE INDEX fa_dupe ON filearchive (fa_storage_group, fa_storage_key); |
277 | | -CREATE INDEX fa_notime ON filearchive (fa_deleted_timestamp); |
278 | | -CREATE INDEX fa_nouser ON filearchive (fa_deleted_user); |
| 307 | +ALTER TABLE &mw_prefix.filearchive ADD CONSTRAINT &mw_prefix.filearchive_pk PRIMARY KEY (fa_id); |
| 308 | +CREATE INDEX &mw_prefix.filearchive_i01 ON &mw_prefix.filearchive (fa_name, fa_timestamp); |
| 309 | +CREATE INDEX &mw_prefix.filearchive_i02 ON &mw_prefix.filearchive (fa_storage_group, fa_storage_key); |
| 310 | +CREATE INDEX &mw_prefix.filearchive_i03 ON &mw_prefix.filearchive (fa_deleted_timestamp); |
| 311 | +CREATE INDEX &mw_prefix.filearchive_i04 ON &mw_prefix.filearchive (fa_user_text,fa_timestamp); |
279 | 312 | |
280 | | - |
281 | 313 | CREATE SEQUENCE rc_rc_id_seq; |
282 | | -CREATE TABLE recentchanges ( |
283 | | - rc_id INTEGER NOT NULL PRIMARY KEY, |
284 | | - rc_timestamp TIMESTAMP WITH TIME ZONE NOT NULL, |
285 | | - rc_cur_time TIMESTAMP WITH TIME ZONE NOT NULL, |
286 | | - rc_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, |
287 | | - rc_user_text CLOB NOT NULL, |
288 | | - rc_namespace SMALLINT NOT NULL, |
289 | | - rc_title VARCHAR(255) NOT NULL, |
290 | | - rc_comment VARCHAR(255), |
291 | | - rc_minor CHAR DEFAULT '0' NOT NULL, |
292 | | - rc_bot CHAR DEFAULT '0' NOT NULL, |
293 | | - rc_new CHAR DEFAULT '0' NOT NULL, |
294 | | - rc_cur_id INTEGER NULL REFERENCES page(page_id) ON DELETE SET NULL, |
295 | | - rc_this_oldid INTEGER NOT NULL, |
296 | | - rc_last_oldid INTEGER NOT NULL, |
297 | | - rc_type CHAR DEFAULT '0' NOT NULL, |
298 | | - rc_moved_to_ns SMALLINT, |
299 | | - rc_moved_to_title CLOB, |
300 | | - rc_patrolled CHAR DEFAULT '0' NOT NULL, |
301 | | - rc_ip VARCHAR(15), |
302 | | - rc_old_len INTEGER, |
303 | | - rc_new_len INTEGER, |
304 | | - rc_deleted INTEGER DEFAULT '0' NOT NULL, |
305 | | - rc_logid INTEGER DEFAULT '0' NOT NULL, |
306 | | - rc_log_type CLOB, |
307 | | - rc_log_action CLOB, |
308 | | - rc_params CLOB |
| 314 | +CREATE TABLE &mw_prefix.recentchanges ( |
| 315 | + rc_id NUMBER NOT NULL, |
| 316 | + rc_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL, |
| 317 | + rc_cur_time TIMESTAMP(6) WITH TIME ZONE NOT NULL, |
| 318 | + rc_user NUMBER NULL REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL, |
| 319 | + rc_user_text VARCHAR2(255) NOT NULL, |
| 320 | + rc_namespace NUMBER NOT NULL, |
| 321 | + rc_title VARCHAR2(255) NOT NULL, |
| 322 | + rc_comment VARCHAR2(255), |
| 323 | + rc_minor CHAR(1) DEFAULT '0' NOT NULL, |
| 324 | + rc_bot CHAR(1) DEFAULT '0' NOT NULL, |
| 325 | + rc_new CHAR(1) DEFAULT '0' NOT NULL, |
| 326 | + rc_cur_id NUMBER NULL REFERENCES &mw_prefix.page(page_id) ON DELETE SET NULL, |
| 327 | + rc_this_oldid NUMBER NOT NULL, |
| 328 | + rc_last_oldid NUMBER NOT NULL, |
| 329 | + rc_type CHAR(1) DEFAULT '0' NOT NULL, |
| 330 | + rc_moved_to_ns NUMBER, |
| 331 | + rc_moved_to_title VARCHAR2(255), |
| 332 | + rc_patrolled CHAR(1) DEFAULT '0' NOT NULL, |
| 333 | + rc_ip VARCHAR2(15), |
| 334 | + rc_old_len NUMBER, |
| 335 | + rc_new_len NUMBER, |
| 336 | + rc_deleted NUMBER DEFAULT '0' NOT NULL, |
| 337 | + rc_logid NUMBER DEFAULT '0' NOT NULL, |
| 338 | + rc_log_type VARCHAR2(255), |
| 339 | + rc_log_action VARCHAR2(255), |
| 340 | + rc_params CLOB |
309 | 341 | ); |
310 | | -CREATE INDEX rc_timestamp ON recentchanges (rc_timestamp); |
311 | | -CREATE INDEX rc_namespace_title ON recentchanges (rc_namespace, rc_title); |
312 | | -CREATE INDEX rc_cur_id ON recentchanges (rc_cur_id); |
313 | | -CREATE INDEX new_name_timestamp ON recentchanges (rc_new, rc_namespace, rc_timestamp); |
314 | | -CREATE INDEX rc_ip ON recentchanges (rc_ip); |
| 342 | +ALTER TABLE &mw_prefix.recentchanges ADD CONSTRAINT &mw_prefix.recentchanges_pk PRIMARY KEY (rc_id); |
| 343 | +CREATE INDEX &mw_prefix.recentchanges_i01 ON &mw_prefix.recentchanges (rc_timestamp); |
| 344 | +CREATE INDEX &mw_prefix.recentchanges_i02 ON &mw_prefix.recentchanges (rc_namespace, rc_title); |
| 345 | +CREATE INDEX &mw_prefix.recentchanges_i03 ON &mw_prefix.recentchanges (rc_cur_id); |
| 346 | +CREATE INDEX &mw_prefix.recentchanges_i04 ON &mw_prefix.recentchanges (rc_new,rc_namespace,rc_timestamp); |
| 347 | +CREATE INDEX &mw_prefix.recentchanges_i05 ON &mw_prefix.recentchanges (rc_ip); |
| 348 | +CREATE INDEX &mw_prefix.recentchanges_i06 ON &mw_prefix.recentchanges (rc_namespace, rc_user_text); |
| 349 | +CREATE INDEX &mw_prefix.recentchanges_i07 ON &mw_prefix.recentchanges (rc_user_text, rc_timestamp); |
315 | 350 | |
316 | | - |
317 | | -CREATE TABLE watchlist ( |
318 | | - wl_user INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE, |
319 | | - wl_namespace SMALLINT DEFAULT 0 NOT NULL, |
320 | | - wl_title VARCHAR(255) NOT NULL, |
321 | | - wl_notificationtimestamp TIMESTAMP WITH TIME ZONE |
| 351 | +CREATE TABLE &mw_prefix.watchlist ( |
| 352 | + wl_user NUMBER NOT NULL REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE, |
| 353 | + wl_namespace NUMBER DEFAULT 0 NOT NULL, |
| 354 | + wl_title VARCHAR2(255) NOT NULL, |
| 355 | + wl_notificationtimestamp TIMESTAMP(6) WITH TIME ZONE |
322 | 356 | ); |
323 | | -CREATE UNIQUE INDEX wl_user_namespace_title ON watchlist (wl_namespace, wl_title, wl_user); |
| 357 | +CREATE UNIQUE INDEX &mw_prefix.watchlist_u01 ON &mw_prefix.watchlist (wl_user, wl_namespace, wl_title); |
| 358 | +CREATE INDEX &mw_prefix.watchlist_i01 ON &mw_prefix.watchlist (wl_namespace, wl_title); |
324 | 359 | |
325 | 360 | |
326 | | -CREATE TABLE math ( |
327 | | - math_inputhash VARCHAR(16) NOT NULL UNIQUE, |
328 | | - math_outputhash VARCHAR(16) NOT NULL, |
329 | | - math_html_conservativeness SMALLINT NOT NULL, |
| 361 | +CREATE TABLE &mw_prefix.math ( |
| 362 | + math_inputhash VARCHAR2(16) NOT NULL, |
| 363 | + math_outputhash VARCHAR2(16) NOT NULL, |
| 364 | + math_html_conservativeness NUMBER NOT NULL, |
330 | 365 | math_html CLOB, |
331 | 366 | math_mathml CLOB |
332 | 367 | ); |
| 368 | +CREATE UNIQUE INDEX &mw_prefix.math_u01 ON &mw_prefix.math (math_inputhash); |
333 | 369 | |
334 | | - |
335 | | -CREATE TABLE interwiki ( |
336 | | - iw_prefix VARCHAR(32) NOT NULL UNIQUE, |
337 | | - iw_url VARCHAR(127) NOT NULL, |
338 | | - iw_local CHAR NOT NULL, |
339 | | - iw_trans CHAR DEFAULT '0' NOT NULL |
| 370 | +CREATE TABLE &mw_prefix.searchindex ( |
| 371 | + si_page NUMBER NOT NULL, |
| 372 | + si_title VARCHAR2(255) DEFAULT '' NOT NULL, |
| 373 | + si_text CLOB NOT NULL |
340 | 374 | ); |
| 375 | +CREATE UNIQUE INDEX &mw_prefix.searchindex_u01 ON &mw_prefix.searchindex (si_page); |
341 | 376 | |
342 | | -CREATE TABLE querycache ( |
343 | | - qc_type CHAR(32) NOT NULL, |
344 | | - qc_value SMALLINT NOT NULL, |
345 | | - qc_namespace SMALLINT NOT NULL, |
346 | | - qc_title CHAR(255) NOT NULL |
| 377 | +CREATE TABLE &mw_prefix.interwiki ( |
| 378 | + iw_prefix VARCHAR2(32) NOT NULL, |
| 379 | + iw_url VARCHAR2(127) NOT NULL, |
| 380 | + iw_local CHAR(1) NOT NULL, |
| 381 | + iw_trans CHAR(1) DEFAULT '0' NOT NULL |
347 | 382 | ); |
348 | | -CREATE INDEX querycache_type_value ON querycache (qc_type, qc_value); |
| 383 | +CREATE UNIQUE INDEX &mw_prefix.interwiki_u01 ON &mw_prefix.interwiki (iw_prefix); |
349 | 384 | |
350 | | -CREATE TABLE querycache_info ( |
351 | | - qci_type VARCHAR(32) UNIQUE, |
352 | | - qci_timestamp TIMESTAMP WITH TIME ZONE NULL |
| 385 | +CREATE TABLE &mw_prefix.querycache ( |
| 386 | + qc_type VARCHAR2(32) NOT NULL, |
| 387 | + qc_value NUMBER NOT NULL, |
| 388 | + qc_namespace NUMBER NOT NULL, |
| 389 | + qc_title VARCHAR2(255) NOT NULL |
353 | 390 | ); |
| 391 | +CREATE INDEX &mw_prefix.querycache_u01 ON &mw_prefix.querycache (qc_type,qc_value); |
354 | 392 | |
355 | | -CREATE TABLE querycachetwo ( |
356 | | - qcc_type CHAR(32) NOT NULL, |
357 | | - qcc_value SMALLINT DEFAULT 0 NOT NULL, |
358 | | - qcc_namespace INTEGER DEFAULT 0 NOT NULL, |
359 | | - qcc_title CHAR(255) DEFAULT '' NOT NULL, |
360 | | - qcc_namespacetwo INTEGER DEFAULT 0 NOT NULL, |
361 | | - qcc_titletwo CHAR(255) DEFAULT '' NOT NULL |
362 | | -); |
363 | | -CREATE INDEX querycachetwo_type_value ON querycachetwo (qcc_type, qcc_value); |
364 | | -CREATE INDEX querycachetwo_title ON querycachetwo (qcc_type,qcc_namespace,qcc_title); |
365 | | -CREATE INDEX querycachetwo_titletwo ON querycachetwo (qcc_type,qcc_namespacetwo,qcc_titletwo); |
366 | | - |
367 | | - |
368 | | -CREATE TABLE objectcache ( |
369 | | - keyname CHAR(255) UNIQUE, |
| 393 | +CREATE TABLE &mw_prefix.objectcache ( |
| 394 | + keyname VARCHAR2(255) , |
370 | 395 | value BLOB, |
371 | | - exptime TIMESTAMP WITH TIME ZONE NOT NULL |
| 396 | + exptime TIMESTAMP(6) WITH TIME ZONE NOT NULL |
372 | 397 | ); |
373 | | -CREATE INDEX objectcacache_exptime ON objectcache (exptime); |
| 398 | +CREATE INDEX &mw_prefix.objectcache_i01 ON &mw_prefix.objectcache (exptime); |
374 | 399 | |
375 | | -CREATE TABLE transcache ( |
376 | | - tc_url VARCHAR(255) NOT NULL UNIQUE, |
| 400 | +CREATE TABLE &mw_prefix.transcache ( |
| 401 | + tc_url VARCHAR2(255) NOT NULL, |
377 | 402 | tc_contents CLOB NOT NULL, |
378 | | - tc_time TIMESTAMP WITH TIME ZONE NOT NULL |
| 403 | + tc_time TIMESTAMP(6) WITH TIME ZONE NOT NULL |
379 | 404 | ); |
| 405 | +CREATE UNIQUE INDEX &mw_prefix.transcache_u01 ON &mw_prefix.transcache (tc_url); |
380 | 406 | |
381 | 407 | |
382 | 408 | CREATE SEQUENCE log_log_id_seq; |
383 | | -CREATE TABLE logging ( |
384 | | - log_type VARCHAR(10) NOT NULL, |
385 | | - log_action VARCHAR(10) NOT NULL, |
386 | | - log_timestamp TIMESTAMP WITH TIME ZONE NOT NULL, |
387 | | - log_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, |
388 | | - log_namespace SMALLINT NOT NULL, |
389 | | - log_title VARCHAR(255) NOT NULL, |
390 | | - log_comment VARCHAR(255), |
| 409 | +CREATE TABLE &mw_prefix.logging ( |
| 410 | + log_id NUMBER NOT NULL, |
| 411 | + log_type VARCHAR2(10) NOT NULL, |
| 412 | + log_action VARCHAR2(10) NOT NULL, |
| 413 | + log_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL, |
| 414 | + log_user NUMBER REFERENCES &mw_prefix.mwuser(user_id) ON DELETE SET NULL, |
| 415 | + log_namespace NUMBER NOT NULL, |
| 416 | + log_title VARCHAR2(255) NOT NULL, |
| 417 | + log_comment VARCHAR2(255), |
391 | 418 | log_params CLOB, |
392 | | - log_deleted INTEGER DEFAULT '0' NOT NULL, |
393 | | - log_id INTEGER NOT NULL PRIMARY KEY |
| 419 | + log_deleted NUMBER DEFAULT '0' NOT NULL |
394 | 420 | ); |
395 | | -CREATE INDEX logging_type_name ON logging (log_type, log_timestamp); |
396 | | -CREATE INDEX logging_user_time ON logging (log_timestamp, log_user); |
397 | | -CREATE INDEX logging_page_time ON logging (log_namespace, log_title, log_timestamp); |
| 421 | +ALTER TABLE &mw_prefix.logging ADD CONSTRAINT &mw_prefix.logging_pk PRIMARY KEY (log_id); |
| 422 | +CREATE INDEX &mw_prefix.logging_i01 ON &mw_prefix.logging (log_type, log_timestamp); |
| 423 | +CREATE INDEX &mw_prefix.logging_i02 ON &mw_prefix.logging (log_user, log_timestamp); |
| 424 | +CREATE INDEX &mw_prefix.logging_i03 ON &mw_prefix.logging (log_namespace, log_title, log_timestamp); |
| 425 | +CREATE INDEX &mw_prefix.logging_i04 ON &mw_prefix.logging (log_timestamp); |
398 | 426 | |
| 427 | +CREATE TABLE &mw_prefix.log_search ( |
| 428 | + ls_field VARCHAR2(32) NOT NULL, |
| 429 | + ls_value VARCHAR2(255) NOT NULL, |
| 430 | + ls_log_id NuMBER DEFAULT 0 NOT NULL |
| 431 | +); |
| 432 | +ALTER TABLE log_search ADD CONSTRAINT log_search_pk PRIMARY KEY (ls_field,ls_value,ls_log_id); |
| 433 | +CREATE INDEX &mw_prefix.log_search_i01 ON &mw_prefix.log_search (ls_log_id); |
| 434 | + |
399 | 435 | CREATE SEQUENCE trackbacks_tb_id_seq; |
400 | | -CREATE TABLE trackbacks ( |
401 | | - tb_id INTEGER NOT NULL PRIMARY KEY, |
402 | | - tb_page INTEGER REFERENCES page(page_id) ON DELETE CASCADE, |
403 | | - tb_title VARCHAR(255) NOT NULL, |
404 | | - tb_url VARCHAR(255) NOT NULL, |
| 436 | +CREATE TABLE &mw_prefix.trackbacks ( |
| 437 | + tb_id NUMBER NOT NULL, |
| 438 | + tb_page NUMBER REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE, |
| 439 | + tb_title VARCHAR2(255) NOT NULL, |
| 440 | + tb_url VARCHAR2(255) NOT NULL, |
405 | 441 | tb_ex CLOB, |
406 | | - tb_name VARCHAR(255) |
| 442 | + tb_name VARCHAR2(255) |
407 | 443 | ); |
408 | | -CREATE INDEX trackback_page ON trackbacks (tb_page); |
| 444 | +ALTER TABLE &mw_prefix.trackbacks ADD CONSTRAINT &mw_prefix.trackbacks_pk PRIMARY KEY (tb_id); |
| 445 | +CREATE INDEX &mw_prefix.trackbacks_i01 ON &mw_prefix.trackbacks (tb_page); |
409 | 446 | |
410 | 447 | CREATE SEQUENCE job_job_id_seq; |
411 | | -CREATE TABLE job ( |
412 | | - job_id INTEGER NOT NULL PRIMARY KEY, |
413 | | - job_cmd VARCHAR(255) NOT NULL, |
414 | | - job_namespace SMALLINT NOT NULL, |
415 | | - job_title VARCHAR(255) NOT NULL, |
| 448 | +CREATE TABLE &mw_prefix.job ( |
| 449 | + job_id NUMBER NOT NULL, |
| 450 | + job_cmd VARCHAR2(60) NOT NULL, |
| 451 | + job_namespace NUMBER NOT NULL, |
| 452 | + job_title VARCHAR2(255) NOT NULL, |
416 | 453 | job_params CLOB NOT NULL |
417 | 454 | ); |
418 | | -CREATE INDEX job_cmd_namespace_title ON job (job_cmd, job_namespace, job_title); |
| 455 | +ALTER TABLE &mw_prefix.job ADD CONSTRAINT &mw_prefix.job_pk PRIMARY KEY (job_id); |
| 456 | +CREATE INDEX &mw_prefix.job_i01 ON &mw_prefix.job (job_cmd, job_namespace, job_title); |
419 | 457 | |
| 458 | +CREATE TABLE &mw_prefix.querycache_info ( |
| 459 | + qci_type VARCHAR2(32) NOT NULL, |
| 460 | + qci_timestamp TIMESTAMP(6) WITH TIME ZONE NULL |
| 461 | +); |
| 462 | +CREATE UNIQUE INDEX &mw_prefix.querycache_info_u01 ON &mw_prefix.querycache_info (qci_type); |
| 463 | + |
| 464 | +CREATE TABLE &mw_prefix.redirect ( |
| 465 | + rd_from NUMBER NOT NULL REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE, |
| 466 | + rd_namespace NUMBER NOT NULL, |
| 467 | + rd_title VARCHAR2(255) NOT NULL |
| 468 | +); |
| 469 | +CREATE INDEX &mw_prefix.redirect_i01 ON &mw_prefix.redirect (rd_namespace,rd_title,rd_from); |
| 470 | + |
| 471 | +CREATE TABLE &mw_prefix.querycachetwo ( |
| 472 | + qcc_type VARCHAR2(32) NOT NULL, |
| 473 | + qcc_value NUMBER DEFAULT 0 NOT NULL, |
| 474 | + qcc_namespace NUMBER DEFAULT 0 NOT NULL, |
| 475 | + qcc_title VARCHAR2(255) DEFAULT '' NOT NULL, |
| 476 | + qcc_namespacetwo NUMBER DEFAULT 0 NOT NULL, |
| 477 | + qcc_titletwo VARCHAR2(255) DEFAULT '' NOT NULL |
| 478 | +); |
| 479 | +CREATE INDEX &mw_prefix.querycachetwo_i01 ON &mw_prefix.querycachetwo (qcc_type,qcc_value); |
| 480 | +CREATE INDEX &mw_prefix.querycachetwo_i02 ON &mw_prefix.querycachetwo (qcc_type,qcc_namespace,qcc_title); |
| 481 | +CREATE INDEX &mw_prefix.querycachetwo_i03 ON &mw_prefix.querycachetwo (qcc_type,qcc_namespacetwo,qcc_titletwo); |
| 482 | + |
| 483 | +CREATE SEQUENCE pr_id_val; |
| 484 | +CREATE TABLE &mw_prefix.page_restrictions ( |
| 485 | + pr_id NUMBER NOT NULL, |
| 486 | + pr_page NUMBER NULL REFERENCES &mw_prefix.page (page_id) ON DELETE CASCADE, |
| 487 | + pr_type VARCHAR2(255) NOT NULL, |
| 488 | + pr_level VARCHAR2(255) NOT NULL, |
| 489 | + pr_cascade NUMBER NOT NULL, |
| 490 | + pr_user NUMBER NULL, |
| 491 | + pr_expiry TIMESTAMP(6) WITH TIME ZONE NULL |
| 492 | +); |
| 493 | +ALTER TABLE &mw_prefix.page_restrictions ADD CONSTRAINT &mw_prefix.page_restrictions_pk PRIMARY KEY (pr_page,pr_type); |
| 494 | +CREATE INDEX &mw_prefix.page_restrictions_i01 ON &mw_prefix.page_restrictions (pr_type,pr_level); |
| 495 | +CREATE INDEX &mw_prefix.page_restrictions_i02 ON &mw_prefix.page_restrictions (pr_level); |
| 496 | +CREATE INDEX &mw_prefix.page_restrictions_i03 ON &mw_prefix.page_restrictions (pr_cascade); |
| 497 | + |
| 498 | +CREATE TABLE &mw_prefix.protected_titles ( |
| 499 | + pt_namespace NUMBER NOT NULL, |
| 500 | + pt_title VARCHAR2(255) NOT NULL, |
| 501 | + pt_user NUMBER NOT NULL, |
| 502 | + pt_reason VARCHAR2(255), |
| 503 | + pt_timestamp TIMESTAMP(6) WITH TIME ZONE NOT NULL, |
| 504 | + pt_expiry VARCHAR2(14) NOT NULL, |
| 505 | + pt_create_perm VARCHAR2(60) NOT NULL |
| 506 | +); |
| 507 | +CREATE UNIQUE INDEX &mw_prefix.protected_titles_u01 ON &mw_prefix.protected_titles (pt_namespace,pt_title); |
| 508 | +CREATE INDEX &mw_prefix.protected_titles_i01 ON &mw_prefix.protected_titles (pt_timestamp); |
| 509 | + |
| 510 | +CREATE TABLE &mw_prefix.page_props ( |
| 511 | + pp_page NUMBER NOT NULL, |
| 512 | + pp_propname VARCHAR2(60) NOT NULL, |
| 513 | + pp_value BLOB NOT NULL |
| 514 | +); |
| 515 | +CREATE UNIQUE INDEX &mw_prefix.page_props_u01 ON &mw_prefix.page_props (pp_page,pp_propname); |
| 516 | + |
| 517 | + |
| 518 | +CREATE TABLE &mw_prefix.updatelog ( |
| 519 | + ul_key VARCHAR2(255) NOT NULL |
| 520 | +); |
| 521 | +ALTER TABLE &mw_prefix.updatelog ADD CONSTRAINT &mw_prefix.updatelog_pk PRIMARY KEY (ul_key); |
| 522 | + |
| 523 | +CREATE TABLE &mw_prefix.change_tag ( |
| 524 | + ct_rc_id NUMBER NULL, |
| 525 | + ct_log_id NUMBER NULL, |
| 526 | + ct_rev_id NUMBER NULL, |
| 527 | + ct_tag VARCHAR2(255) NOT NULL, |
| 528 | + ct_params BLOB NULL |
| 529 | +); |
| 530 | +CREATE UNIQUE INDEX &mw_prefix.change_tag_u01 ON &mw_prefix.change_tag (ct_rc_id,ct_tag); |
| 531 | +CREATE UNIQUE INDEX &mw_prefix.change_tag_u02 ON &mw_prefix.change_tag (ct_log_id,ct_tag); |
| 532 | +CREATE UNIQUE INDEX &mw_prefix.change_tag_u03 ON &mw_prefix.change_tag (ct_rev_id,ct_tag); |
| 533 | +CREATE INDEX &mw_prefix.change_tag_i01 ON &mw_prefix.change_tag (ct_tag,ct_rc_id,ct_rev_id,ct_log_id); |
| 534 | + |
| 535 | +CREATE TABLE &mw_prefix.tag_summary ( |
| 536 | + ts_rc_id NUMBER NULL, |
| 537 | + ts_log_id NUMBER NULL, |
| 538 | + ts_rev_id NUMBER NULL, |
| 539 | + ts_tags BLOB NOT NULL |
| 540 | +); |
| 541 | +CREATE UNIQUE INDEX &mw_prefix.tag_summary_u01 ON &mw_prefix.tag_summary (ts_rc_id); |
| 542 | +CREATE UNIQUE INDEX &mw_prefix.tag_summary_u02 ON &mw_prefix.tag_summary (ts_log_id); |
| 543 | +CREATE UNIQUE INDEX &mw_prefix.tag_summary_u03 ON &mw_prefix.tag_summary (ts_rev_id); |
| 544 | + |
| 545 | +CREATE TABLE &mw_prefix.valid_tag ( |
| 546 | + vt_tag VARCHAR2(255) NOT NULL |
| 547 | +); |
| 548 | +ALTER TABLE &mw_prefix.valid_tag ADD CONSTRAINT &mw_prefix.valid_tag_pk PRIMARY KEY (vt_tag); |
| 549 | + |
420 | 550 | -- This table is not used unless profiling is turned on |
| 551 | +--CREATE TABLE &mw_prefix.profiling ( |
| 552 | +-- pf_count NUMBER DEFAULT 0 NOT NULL, |
421 | 553 | -- pf_time NUMERIC(18,10) DEFAULT 0 NOT NULL, |
422 | 554 | -- pf_name CLOB NOT NULL, |
423 | 555 | -- pf_server CLOB NULL |
424 | 556 | --); |
| 557 | +--CREATE UNIQUE INDEX &mw_prefix.profiling_u01 ON &mw_prefix.profiling (pf_name, pf_server); |
425 | 558 | |
426 | | -CREATE TABLE searchindex ( |
427 | | - si_page INTEGER UNIQUE NOT NULL, |
428 | | - si_title VARCHAR(255) DEFAULT '' NOT NULL, |
429 | | - si_text CLOB NOT NULL |
| 559 | +CREATE INDEX si_title_idx ON &mw_prefix.searchindex(si_title) INDEXTYPE IS ctxsys.context; |
| 560 | +CREATE INDEX si_text_idx ON &mw_prefix.searchindex(si_text) INDEXTYPE IS ctxsys.context; |
| 561 | + |
| 562 | +CREATE TABLE &mw_prefix.wiki_field_info_full ( |
| 563 | +table_name VARCHAR2(35) NOT NULL, |
| 564 | +column_name VARCHAR2(35) NOT NULL, |
| 565 | +data_default VARCHAR2(4000), |
| 566 | +data_length NUMBER NOT NULL, |
| 567 | +data_type VARCHAR2(106), |
| 568 | +not_null CHAR(1) NOT NULL, |
| 569 | +prim NUMBER(1), |
| 570 | +uniq NUMBER(1), |
| 571 | +nonuniq NUMBER(1) |
430 | 572 | ); |
| 573 | +ALTER TABLE &mw_prefix.wiki_field_info_full ADD CONSTRAINT &mw_prefix.wiki_field_info_full_pk PRIMARY KEY (table_name, column_name); |
431 | 574 | |
| 575 | +CREATE PROCEDURE &mw_prefix.fill_wiki_info IS |
| 576 | + BEGIN |
| 577 | + DELETE &mw_prefix.wiki_field_info_full; |
432 | 578 | |
433 | | -CREATE INDEX si_title_idx ON searchindex(si_title) INDEXTYPE IS ctxsys.context; |
434 | | -CREATE INDEX si_text_idx ON searchindex(si_text) INDEXTYPE IS ctxsys.context; |
| 579 | + FOR x_rec IN (SELECT '&mw_prefix.' || t.table_name table_name, t.column_name, |
| 580 | + t.data_default, t.data_length, t.data_type, |
| 581 | + DECODE (t.nullable, 'Y', '1', 'N', '0') not_null, |
| 582 | + (SELECT 1 |
| 583 | + FROM user_cons_columns ucc, |
| 584 | + user_constraints uc |
| 585 | + WHERE ucc.table_name = t.table_name |
| 586 | + AND ucc.column_name = t.column_name |
| 587 | + AND uc.constraint_name = ucc.constraint_name |
| 588 | + AND uc.constraint_type = 'P' |
| 589 | + AND ROWNUM < 2) prim, |
| 590 | + (SELECT 1 |
| 591 | + FROM user_ind_columns uic, |
| 592 | + user_indexes ui |
| 593 | + WHERE uic.table_name = t.table_name |
| 594 | + AND uic.column_name = t.column_name |
| 595 | + AND ui.index_name = uic.index_name |
| 596 | + AND ui.uniqueness = 'UNIQUE' |
| 597 | + AND ROWNUM < 2) uniq, |
| 598 | + (SELECT 1 |
| 599 | + FROM user_ind_columns uic, |
| 600 | + user_indexes ui |
| 601 | + WHERE uic.table_name = t.table_name |
| 602 | + AND uic.column_name = t.column_name |
| 603 | + AND ui.index_name = uic.index_name |
| 604 | + AND ui.uniqueness = 'NONUNIQUE' |
| 605 | + AND ROWNUM < 2) nonuniq |
| 606 | + FROM user_tab_columns t, user_tables ut |
| 607 | + WHERE ut.table_name = t.table_name) |
| 608 | + LOOP |
| 609 | + INSERT INTO &mw_prefix.wiki_field_info_full |
| 610 | + (table_name, column_name, |
| 611 | + data_default, data_length, |
| 612 | + data_type, not_null, prim, |
| 613 | + uniq, nonuniq |
| 614 | + ) |
| 615 | + VALUES (x_rec.table_name, x_rec.column_name, |
| 616 | + x_rec.data_default, x_rec.data_length, |
| 617 | + x_rec.data_type, x_rec.not_null, x_rec.prim, |
| 618 | + x_rec.uniq, x_rec.nonuniq |
| 619 | + ); |
| 620 | + END LOOP; |
| 621 | + COMMIT; |
| 622 | +END; |
| 623 | + |
| 624 | +BEGIN |
| 625 | + &mw_prefix.fill_wiki_info; |
| 626 | +END; |
| 627 | + |
| 628 | +CREATE OR REPLACE FUNCTION BITOR (x IN NUMBER, y IN NUMBER) RETURN NUMBER AS |
| 629 | +BEGIN |
| 630 | + RETURN (x + y - BITAND(x, y)); |
| 631 | +END; |
Index: trunk/phase3/maintenance/ora/user.sql |
— | — | @@ -0,0 +1,13 @@ |
| 2 | +define WIKI_USER=&1 |
| 3 | +define WIKI_PASS=&2 |
| 4 | +define DEF_TS=&3 |
| 5 | +define TEMP_TS=&4 |
| 6 | +create user &&wiki_user identified by &&wiki_pass default tablespace &&def_ts temporary tablespace &&temp_ts quota unlimited on &&def_ts; |
| 7 | +grant connect, resource to &&wiki_user; |
| 8 | +grant alter session to &&wiki_user; |
| 9 | +grant ctxapp to &&wiki_user; |
| 10 | +grant execute on ctx_ddl to &&wiki_user; |
| 11 | +grant create view to &&wiki_user; |
| 12 | +grant create synonym to &&wiki_user; |
| 13 | +grant create table to &&wiki_user; |
| 14 | +grant create sequence to &&wiki_user; |
Index: trunk/phase3/includes/GlobalFunctions.php |
— | — | @@ -1831,8 +1831,8 @@ |
1832 | 1832 | } elseif (preg_match('/^\d{1,13}$/D',$ts)) { |
1833 | 1833 | # TS_UNIX |
1834 | 1834 | $uts = $ts; |
1835 | | - } elseif (preg_match('/^\d{1,2}-...-\d\d(?:\d\d)? \d\d\.\d\d\.\d\d/', $ts)) { |
1836 | | - # TS_ORACLE |
| 1835 | + } elseif (preg_match('/^\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}.\d{6}$/', $ts)) { |
| 1836 | + # TS_ORACLE // session altered to DD-MM-YYYY HH24:MI:SS.FF6 |
1837 | 1837 | $uts = strtotime(preg_replace('/(\d\d)\.(\d\d)\.(\d\d)(\.(\d+))?/', "$1:$2:$3", |
1838 | 1838 | str_replace("+00:00", "UTC", $ts))); |
1839 | 1839 | } elseif (preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.*\d*)?Z$/', $ts, $da)) { |
— | — | @@ -1869,7 +1869,8 @@ |
1870 | 1870 | case TS_RFC2822: |
1871 | 1871 | return gmdate( 'D, d M Y H:i:s', $uts ) . ' GMT'; |
1872 | 1872 | case TS_ORACLE: |
1873 | | - return gmdate( 'd-M-y h.i.s A', $uts) . ' +00:00'; |
| 1873 | + return gmdate( 'd-m-Y H:i:s.000000', $uts); |
| 1874 | + //return gmdate( 'd-M-y h.i.s A', $uts) . ' +00:00'; |
1874 | 1875 | case TS_POSTGRES: |
1875 | 1876 | return gmdate( 'Y-m-d H:i:s', $uts) . ' GMT'; |
1876 | 1877 | case TS_DB2: |
Index: trunk/phase3/includes/db/DatabaseOracle.php |
— | — | @@ -31,40 +31,46 @@ |
32 | 32 | private $cursor; |
33 | 33 | private $stmt; |
34 | 34 | private $nrows; |
35 | | - private $db; |
36 | 35 | |
37 | | - function __construct(&$db, $stmt) { |
| 36 | + private $unique; |
| 37 | + |
| 38 | + function __construct(&$db, $stmt, $unique = false) { |
38 | 39 | $this->db =& $db; |
| 40 | + |
39 | 41 | if (($this->nrows = oci_fetch_all($stmt, $this->rows, 0, -1, OCI_FETCHSTATEMENT_BY_ROW | OCI_NUM)) === false) { |
40 | 42 | $e = oci_error($stmt); |
41 | 43 | $db->reportQueryError($e['message'], $e['code'], '', __FUNCTION__); |
42 | 44 | return; |
43 | 45 | } |
44 | 46 | |
| 47 | + if ($unique) { |
| 48 | + $this->rows = array_unique($this->rows); |
| 49 | + $this->nrows = count($this->rows); |
| 50 | + } |
| 51 | + |
45 | 52 | $this->cursor = 0; |
46 | 53 | $this->stmt = $stmt; |
47 | 54 | } |
48 | 55 | |
49 | | - function free() { |
| 56 | + public function free() { |
50 | 57 | oci_free_statement($this->stmt); |
51 | 58 | } |
52 | 59 | |
53 | | - function seek($row) { |
| 60 | + public function seek($row) { |
54 | 61 | $this->cursor = min($row, $this->nrows); |
55 | 62 | } |
56 | 63 | |
57 | | - function numRows() { |
| 64 | + public function numRows() { |
58 | 65 | return $this->nrows; |
59 | 66 | } |
60 | 67 | |
61 | | - function numFields() { |
| 68 | + public function numFields() { |
62 | 69 | return oci_num_fields($this->stmt); |
63 | 70 | } |
64 | 71 | |
65 | | - function fetchObject() { |
| 72 | + public function fetchObject() { |
66 | 73 | if ($this->cursor >= $this->nrows) |
67 | 74 | return false; |
68 | | - |
69 | 75 | $row = $this->rows[$this->cursor++]; |
70 | 76 | $ret = new stdClass(); |
71 | 77 | foreach ($row as $k => $v) { |
— | — | @@ -75,7 +81,7 @@ |
76 | 82 | return $ret; |
77 | 83 | } |
78 | 84 | |
79 | | - function fetchAssoc() { |
| 85 | + public function fetchRow() { |
80 | 86 | if ($this->cursor >= $this->nrows) |
81 | 87 | return false; |
82 | 88 | |
— | — | @@ -91,8 +97,62 @@ |
92 | 98 | } |
93 | 99 | |
94 | 100 | /** |
| 101 | + * Utility class. |
95 | 102 | * @ingroup Database |
96 | 103 | */ |
| 104 | +class ORAField { |
| 105 | + private $name, $tablename, $default, $max_length, $nullable, |
| 106 | + $is_pk, $is_unique, $is_multiple, $is_key, $type; |
| 107 | + |
| 108 | + function __construct($info) { |
| 109 | + $this->name = $info['column_name']; |
| 110 | + $this->tablename = $info['table_name']; |
| 111 | + $this->default = $info['data_default']; |
| 112 | + $this->max_length = $info['data_length']; |
| 113 | + $this->nullable = $info['not_null']; |
| 114 | + $this->is_pk = isset($info['prim']) && $info['prim'] == 1 ? 1 : 0; |
| 115 | + $this->is_unique = isset($info['uniq']) && $info['uniq'] == 1 ? 1 : 0; |
| 116 | + $this->is_multiple = isset($info['nonuniq']) && $info['nonuniq'] == 1 ? 1 : 0; |
| 117 | + $this->is_key = ($this->is_pk || $this->is_unique || $this->is_multiple); |
| 118 | + $this->type = $info['data_type']; |
| 119 | + } |
| 120 | + |
| 121 | + function name() { |
| 122 | + return $this->name; |
| 123 | + } |
| 124 | + |
| 125 | + function tableName() { |
| 126 | + return $this->tablename; |
| 127 | + } |
| 128 | + |
| 129 | + function defaultValue() { |
| 130 | + return $this->default; |
| 131 | + } |
| 132 | + |
| 133 | + function maxLength() { |
| 134 | + return $this->max_length; |
| 135 | + } |
| 136 | + |
| 137 | + function nullable() { |
| 138 | + return $this->nullable; |
| 139 | + } |
| 140 | + |
| 141 | + function isKey() { |
| 142 | + return $this->is_key; |
| 143 | + } |
| 144 | + |
| 145 | + function isMultipleKey() { |
| 146 | + return $this->is_multiple; |
| 147 | + } |
| 148 | + |
| 149 | + function type() { |
| 150 | + return $this->type; |
| 151 | + } |
| 152 | +} |
| 153 | + |
| 154 | +/** |
| 155 | + * @ingroup Database |
| 156 | + */ |
97 | 157 | class DatabaseOracle extends Database { |
98 | 158 | var $mInsertId = NULL; |
99 | 159 | var $mLastResult = NULL; |
— | — | @@ -101,20 +161,14 @@ |
102 | 162 | var $cursor = 0; |
103 | 163 | var $mAffectedRows; |
104 | 164 | |
| 165 | + var $ignore_DUP_VAL_ON_INDEX = false; |
| 166 | + |
105 | 167 | function DatabaseOracle($server = false, $user = false, $password = false, $dbName = false, |
106 | | - $failFunction = false, $flags = 0 ) |
| 168 | + $failFunction = false, $flags = 0, $tablePrefix = 'get from global' ) |
107 | 169 | { |
108 | | - |
109 | | - global $wgOut; |
110 | | - # Can't get a reference if it hasn't been set yet |
111 | | - if ( !isset( $wgOut ) ) { |
112 | | - $wgOut = NULL; |
113 | | - } |
114 | | - $this->mOut =& $wgOut; |
115 | | - $this->mFailFunction = $failFunction; |
116 | | - $this->mFlags = $flags; |
117 | | - $this->open( $server, $user, $password, $dbName); |
118 | | - |
| 170 | + $tablePrefix = $tablePrefix == 'get from global' ? $tablePrefix : strtoupper($tablePrefix); |
| 171 | + parent::__construct($server, $user, $password, $dbName, $failFunction, $flags, $tablePrefix); |
| 172 | + wfRunHooks( 'DatabaseOraclePostInit', array(&$this)); |
119 | 173 | } |
120 | 174 | |
121 | 175 | function cascadingDeletes() { |
— | — | @@ -153,8 +207,7 @@ |
154 | 208 | if ( !function_exists( 'oci_connect' ) ) { |
155 | 209 | throw new DBConnectionError( $this, "Oracle functions missing, have you compiled PHP with the --with-oci8 option?\n (Note: if you recently installed PHP, you may need to restart your webserver and database)\n" ); |
156 | 210 | } |
157 | | - |
158 | | - # Needed for proper UTF-8 functionality |
| 211 | + |
159 | 212 | putenv("NLS_LANG=AMERICAN_AMERICA.AL32UTF8"); |
160 | 213 | |
161 | 214 | $this->close(); |
— | — | @@ -167,8 +220,11 @@ |
168 | 221 | return; |
169 | 222 | } |
170 | 223 | |
171 | | - error_reporting( E_ALL ); |
172 | | - $this->mConn = oci_connect($user, $password, $dbName); |
| 224 | + //error_reporting( E_ALL ); //whoever had this bright idea |
| 225 | + if ( $this->mFlags & DBO_DEFAULT ) |
| 226 | + $this->mConn = oci_new_connect($user, $password, $dbName); |
| 227 | + else |
| 228 | + $this->mConn = oci_connect($user, $password, $dbName); |
173 | 229 | |
174 | 230 | if ($this->mConn == false) { |
175 | 231 | wfDebug("DB connection error\n"); |
— | — | @@ -178,6 +234,11 @@ |
179 | 235 | } |
180 | 236 | |
181 | 237 | $this->mOpened = true; |
| 238 | + |
| 239 | + #removed putenv calls because they interfere with the system globaly |
| 240 | + $this->doQuery('ALTER SESSION SET NLS_TIMESTAMP_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\''); |
| 241 | + $this->doQuery('ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT=\'DD-MM-YYYY HH24:MI:SS.FF6\''); |
| 242 | + |
182 | 243 | return $this->mConn; |
183 | 244 | } |
184 | 245 | |
— | — | @@ -204,18 +265,36 @@ |
205 | 266 | throw new MWException("SQL encoding is invalid"); |
206 | 267 | } |
207 | 268 | |
| 269 | + //handle some oracle specifics |
| 270 | + //remove AS column/table/subquery namings |
| 271 | + $sql = preg_replace('/ as /i', ' ', $sql); |
| 272 | + // Oracle has issues with UNION clause if the statement includes LOB fields |
| 273 | + // So we do a UNION ALL and then filter the results array with array_unique |
| 274 | + $union_unique = (preg_match('/\/\* UNION_UNIQUE \*\/ /', $sql) != 0); |
| 275 | + //EXPLAIN syntax in Oracle is EXPLAIN PLAN FOR and it return nothing |
| 276 | + //you have to select data from plan table after explain |
| 277 | + $explain_id = date('dmYHis'); |
| 278 | + $sql = preg_replace('/^EXPLAIN /', 'EXPLAIN PLAN SET STATEMENT_ID = \''.$explain_id.'\' FOR', $sql, 1, $explain_count); |
| 279 | + |
| 280 | + |
208 | 281 | if (($this->mLastResult = $stmt = oci_parse($this->mConn, $sql)) === false) { |
209 | 282 | $e = oci_error($this->mConn); |
210 | 283 | $this->reportQueryError($e['message'], $e['code'], $sql, __FUNCTION__); |
211 | 284 | } |
212 | 285 | |
| 286 | + $olderr = error_reporting(E_ERROR); |
213 | 287 | if (oci_execute($stmt, $this->execFlags()) == false) { |
214 | 288 | $e = oci_error($stmt); |
215 | | - $this->reportQueryError($e['message'], $e['code'], $sql, __FUNCTION__); |
| 289 | + if (!$this->ignore_DUP_VAL_ON_INDEX || $e['code'] != '1') |
| 290 | + $this->reportQueryError($e['message'], $e['code'], $sql, __FUNCTION__); |
216 | 291 | } |
217 | | - if (oci_statement_type($stmt) == "SELECT") |
218 | | - return new ORAResult($this, $stmt); |
219 | | - else { |
| 292 | + error_reporting($olderr); |
| 293 | + |
| 294 | + if ($explain_count > 0) { |
| 295 | + return $this->doQuery('SELECT id, cardinality "ROWS" FROM plan_table WHERE statement_id = \''.$explain_id.'\''); |
| 296 | + } elseif (oci_statement_type($stmt) == "SELECT") { |
| 297 | + return new ORAResult($this, $stmt, $union_unique); |
| 298 | + } else { |
220 | 299 | $this->mAffectedRows = oci_num_rows($stmt); |
221 | 300 | return true; |
222 | 301 | } |
— | — | @@ -226,27 +305,47 @@ |
227 | 306 | } |
228 | 307 | |
229 | 308 | function freeResult($res) { |
230 | | - $res->free(); |
| 309 | + if ( $res instanceof ORAResult ) { |
| 310 | + $res->free(); |
| 311 | + } else { |
| 312 | + $res->result->free(); |
| 313 | + } |
231 | 314 | } |
232 | 315 | |
233 | 316 | function fetchObject($res) { |
234 | | - return $res->fetchObject(); |
| 317 | + if ( $res instanceof ORAResult ) { |
| 318 | + return $res->numRows(); |
| 319 | + } else { |
| 320 | + return $res->result->fetchObject(); |
| 321 | + } |
235 | 322 | } |
236 | 323 | |
237 | 324 | function fetchRow($res) { |
238 | | - return $res->fetchAssoc(); |
| 325 | + if ( $res instanceof ORAResult ) { |
| 326 | + return $res->fetchRow(); |
| 327 | + } else { |
| 328 | + return $res->result->fetchRow(); |
| 329 | + } |
239 | 330 | } |
240 | 331 | |
241 | 332 | function numRows($res) { |
242 | | - return $res->numRows(); |
| 333 | + if ( $res instanceof ORAResult ) { |
| 334 | + return $res->numRows(); |
| 335 | + } else { |
| 336 | + return $res->result->numRows(); |
| 337 | + } |
243 | 338 | } |
244 | 339 | |
245 | 340 | function numFields($res) { |
246 | | - return $res->numFields(); |
| 341 | + if ( $res instanceof ORAResult ) { |
| 342 | + return $res->numFields(); |
| 343 | + } else { |
| 344 | + return $res->result->numFields(); |
| 345 | + } |
247 | 346 | } |
248 | 347 | |
249 | 348 | function fieldName($stmt, $n) { |
250 | | - return pg_field_name($stmt, $n); |
| 349 | + return oci_field_name($stmt, $n); |
251 | 350 | } |
252 | 351 | |
253 | 352 | /** |
— | — | @@ -257,7 +356,11 @@ |
258 | 357 | } |
259 | 358 | |
260 | 359 | function dataSeek($res, $row) { |
261 | | - $res->seek($row); |
| 360 | + if ( $res instanceof ORAResult ) { |
| 361 | + $res->seek($row); |
| 362 | + } else { |
| 363 | + $res->result->seek($row); |
| 364 | + } |
262 | 365 | } |
263 | 366 | |
264 | 367 | function lastError() { |
— | — | @@ -284,63 +387,56 @@ |
285 | 388 | * Returns information about an index |
286 | 389 | * If errors are explicitly ignored, returns NULL on failure |
287 | 390 | */ |
288 | | - function indexInfo( $table, $index, $fname = 'Database::indexExists' ) { |
| 391 | + function indexInfo( $table, $index, $fname = 'DatabaseOracle::indexExists' ) { |
289 | 392 | return false; |
290 | 393 | } |
291 | 394 | |
292 | | - function indexUnique ($table, $index, $fname = 'Database::indexUnique' ) { |
| 395 | + function indexUnique ($table, $index, $fname = 'DatabaseOracle::indexUnique' ) { |
293 | 396 | return false; |
294 | 397 | } |
295 | 398 | |
296 | | - function insert( $table, $a, $fname = 'Database::insert', $options = array() ) { |
| 399 | + function insert( $table, $a, $fname = 'DatabaseOracle::insert', $options = array() ) { |
| 400 | + if ( !count( $a ) ) |
| 401 | + return true; |
| 402 | + |
297 | 403 | if (!is_array($options)) |
298 | 404 | $options = array($options); |
299 | 405 | |
300 | | - #if (in_array('IGNORE', $options)) |
301 | | - # $oldIgnore = $this->ignoreErrors(true); |
| 406 | + if (in_array('IGNORE', $options)) |
| 407 | + $this->ignore_DUP_VAL_ON_INDEX = true; |
302 | 408 | |
303 | | - # IGNORE is performed using single-row inserts, ignoring errors in each |
304 | | - # FIXME: need some way to distiguish between key collision and other types of error |
305 | | - //$oldIgnore = $this->ignoreErrors(true); |
306 | 409 | if (!is_array(reset($a))) { |
307 | 410 | $a = array($a); |
308 | 411 | } |
309 | 412 | foreach ($a as $row) { |
310 | 413 | $this->insertOneRow($table, $row, $fname); |
311 | 414 | } |
312 | | - //$this->ignoreErrors($oldIgnore); |
313 | 415 | $retVal = true; |
314 | 416 | |
315 | | - //if (in_array('IGNORE', $options)) |
316 | | - // $this->ignoreErrors($oldIgnore); |
| 417 | + if (in_array('IGNORE', $options)) |
| 418 | + $this->ignore_DUP_VAL_ON_INDEX = false; |
317 | 419 | |
318 | 420 | return $retVal; |
319 | 421 | } |
320 | 422 | |
321 | 423 | function insertOneRow($table, $row, $fname) { |
| 424 | + global $wgLang; |
| 425 | + |
322 | 426 | // "INSERT INTO tables (a, b, c)" |
323 | 427 | $sql = "INSERT INTO " . $this->tableName($table) . " (" . join(',', array_keys($row)) . ')'; |
324 | 428 | $sql .= " VALUES ("; |
325 | 429 | |
326 | 430 | // for each value, append ":key" |
327 | 431 | $first = true; |
328 | | - $returning = ''; |
329 | 432 | foreach ($row as $col => $val) { |
330 | | - if (is_object($val)) { |
331 | | - $what = "EMPTY_BLOB()"; |
332 | | - assert($returning === ''); |
333 | | - $returning = " RETURNING $col INTO :bval"; |
334 | | - $blobcol = $col; |
335 | | - } else |
336 | | - $what = ":$col"; |
337 | | - |
338 | 433 | if ($first) |
339 | | - $sql .= "$what"; |
| 434 | + $sql .= ':'.$col; |
340 | 435 | else |
341 | | - $sql.= ", $what"; |
| 436 | + $sql.= ', :'.$col; |
| 437 | + |
342 | 438 | $first = false; |
343 | 439 | } |
344 | | - $sql .= ") $returning"; |
| 440 | + $sql .= ')'; |
345 | 441 | |
346 | 442 | $stmt = oci_parse($this->mConn, $sql); |
347 | 443 | foreach ($row as $col => $val) { |
— | — | @@ -349,39 +445,136 @@ |
350 | 446 | $this->reportQueryError($this->lastErrno(), $this->lastError(), $sql, __METHOD__); |
351 | 447 | } |
352 | 448 | } |
353 | | - |
354 | | - if (($bval = oci_new_descriptor($this->mConn, OCI_D_LOB)) === false) { |
355 | | - $e = oci_error($stmt); |
356 | | - throw new DBUnexpectedError($this, "Cannot create LOB descriptor: " . $e['message']); |
| 449 | + |
| 450 | + $stmt = oci_parse($this->mConn, $sql); |
| 451 | + foreach ($row as $col => $val) { |
| 452 | + $col_type=$this->fieldInfo($this->tableName($table), $col)->type(); |
| 453 | + if ($col_type != 'BLOB' && $col_type != 'CLOB') { |
| 454 | + if (is_object($val)) |
| 455 | + $val = $val->getData(); |
| 456 | + |
| 457 | + if (preg_match('/^timestamp.*/i', $col_type) == 1 && strtolower($val) == 'infinity') |
| 458 | + $val = '31-12-2030 12:00:00.000000'; |
| 459 | + |
| 460 | + if (oci_bind_by_name($stmt, ":$col", $wgLang->checkTitleEncoding($val)) === false) |
| 461 | + $this->reportQueryError($this->lastErrno(), $this->lastError(), $sql, __METHOD__); |
| 462 | + } else { |
| 463 | + if (($lob[$col] = oci_new_descriptor($this->mConn, OCI_D_LOB)) === false) { |
| 464 | + $e = oci_error($stmt); |
| 465 | + throw new DBUnexpectedError($this, "Cannot create LOB descriptor: " . $e['message']); |
| 466 | + } |
| 467 | + |
| 468 | + if (is_object($val)) { |
| 469 | + $lob[$col]->writeTemporary($val->getData()); |
| 470 | + oci_bind_by_name($stmt, ":$col", $lob[$col], -1, SQLT_BLOB); |
| 471 | + } else { |
| 472 | + $lob[$col]->writeTemporary($val); |
| 473 | + oci_bind_by_name($stmt, ":$col", $lob[$col], -1, OCI_B_CLOB); |
| 474 | + } |
| 475 | + } |
357 | 476 | } |
358 | | - |
359 | | - if (strlen($returning)) |
360 | | - oci_bind_by_name($stmt, ":bval", $bval, -1, SQLT_BLOB); |
361 | | - |
| 477 | + |
| 478 | + $olderr = error_reporting(E_ERROR); |
362 | 479 | if (oci_execute($stmt, OCI_DEFAULT) === false) { |
363 | 480 | $e = oci_error($stmt); |
364 | | - $this->reportQueryError($e['message'], $e['code'], $sql, __METHOD__); |
| 481 | + |
| 482 | + if (!$this->ignore_DUP_VAL_ON_INDEX || $e['code'] != '1') |
| 483 | + $this->reportQueryError($e['message'], $e['code'], $sql, __METHOD__); |
| 484 | + else |
| 485 | + $this->mAffectedRows = oci_num_rows($stmt); |
| 486 | + } else |
| 487 | + $this->mAffectedRows = oci_num_rows($stmt); |
| 488 | + error_reporting($olderr); |
| 489 | + |
| 490 | + if (isset($lob)){ |
| 491 | + foreach ($lob as $lob_i => $lob_v) { |
| 492 | + $lob_v->free(); |
| 493 | + } |
365 | 494 | } |
366 | | - if (strlen($returning)) { |
367 | | - $bval->save($row[$blobcol]->getData()); |
368 | | - $bval->free(); |
369 | | - } |
| 495 | + |
370 | 496 | if (!$this->mTrxLevel) |
371 | 497 | oci_commit($this->mConn); |
372 | | - |
| 498 | + |
373 | 499 | oci_free_statement($stmt); |
374 | 500 | } |
375 | 501 | |
| 502 | + function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = 'DatabaseOracle::insertSelect', |
| 503 | + $insertOptions = array(), $selectOptions = array() ) |
| 504 | + { |
| 505 | + $destTable = $this->tableName( $destTable ); |
| 506 | + if( !is_array( $selectOptions ) ) { |
| 507 | + $selectOptions = array( $selectOptions ); |
| 508 | + } |
| 509 | + list( $startOpts, $useIndex, $tailOpts ) = $this->makeSelectOptions( $selectOptions ); |
| 510 | + if( is_array( $srcTable ) ) { |
| 511 | + $srcTable = implode( ',', array_map( array( &$this, 'tableName' ), $srcTable ) ); |
| 512 | + } else { |
| 513 | + $srcTable = $this->tableName( $srcTable ); |
| 514 | + } |
| 515 | + $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' . |
| 516 | + " SELECT $startOpts " . implode( ',', $varMap ) . |
| 517 | + " FROM $srcTable $useIndex "; |
| 518 | + if ( $conds != '*' ) { |
| 519 | + $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND ); |
| 520 | + } |
| 521 | + $sql .= " $tailOpts"; |
| 522 | + |
| 523 | + if (in_array('IGNORE', $insertOptions)) |
| 524 | + $this->ignore_DUP_VAL_ON_INDEX = true; |
| 525 | + |
| 526 | + $retval = $this->query( $sql, $fname ); |
| 527 | + |
| 528 | + if (in_array('IGNORE', $insertOptions)) |
| 529 | + $this->ignore_DUP_VAL_ON_INDEX = false; |
| 530 | + |
| 531 | + return $retval; |
| 532 | + } |
| 533 | + |
376 | 534 | function tableName( $name ) { |
377 | | - # Replace reserved words with better ones |
| 535 | + global $wgSharedDB, $wgSharedPrefix, $wgSharedTables; |
| 536 | + /* |
| 537 | + Replace reserved words with better ones |
| 538 | + Useing uppercase, because that's the only way oracle can handle |
| 539 | + quoted tablenames |
| 540 | + */ |
378 | 541 | switch( $name ) { |
379 | 542 | case 'user': |
380 | | - return 'mwuser'; |
| 543 | + $name = 'MWUSER'; break; |
381 | 544 | case 'text': |
382 | | - return 'pagecontent'; |
383 | | - default: |
384 | | - return $name; |
| 545 | + $name = 'PAGECONTENT'; break; |
385 | 546 | } |
| 547 | + |
| 548 | + /* |
| 549 | + The rest of procedure is equal to generic Databse class |
| 550 | + except for the quoting style |
| 551 | + */ |
| 552 | + if ( $name[0] == '"' && substr( $name, -1, 1 ) == '"' ) return $name; |
| 553 | + |
| 554 | + if( preg_match( '/(^|\s)(DISTINCT|JOIN|ON|AS)(\s|$)/i', $name ) !== 0 ) return $name; |
| 555 | + $dbDetails = array_reverse( explode( '.', $name, 2 ) ); |
| 556 | + if( isset( $dbDetails[1] ) ) @list( $table, $database ) = $dbDetails; |
| 557 | + else @list( $table ) = $dbDetails; |
| 558 | + |
| 559 | + $prefix = $this->mTablePrefix; |
| 560 | + |
| 561 | + if( isset($database) ) $table = ( $table[0] == '`' ? $table : "`{$table}`" ); |
| 562 | + |
| 563 | + if( !isset( $database ) |
| 564 | + && isset( $wgSharedDB ) |
| 565 | + && $table[0] != '"' |
| 566 | + && isset( $wgSharedTables ) |
| 567 | + && is_array( $wgSharedTables ) |
| 568 | + && in_array( $table, $wgSharedTables ) ) { |
| 569 | + $database = $wgSharedDB; |
| 570 | + $prefix = isset( $wgSharedPrefix ) ? $wgSharedPrefix : $prefix; |
| 571 | + } |
| 572 | + |
| 573 | + if( isset($database) ) $database = ( $database[0] == '"' ? $database : "\"{$database}\"" ); |
| 574 | + $table = ( $table[0] == '"' ? $table : "\"{$prefix}{$table}\"" ); |
| 575 | + |
| 576 | + $tableName = ( isset($database) ? "{$database}.{$table}" : "{$table}" ); |
| 577 | + |
| 578 | + return strtoupper($tableName); |
386 | 579 | } |
387 | 580 | |
388 | 581 | /** |
— | — | @@ -411,7 +604,7 @@ |
412 | 605 | # It may be more efficient to leave off unique indexes which are unlikely to collide. |
413 | 606 | # However if you do this, you run the risk of encountering errors which wouldn't have |
414 | 607 | # occurred in MySQL |
415 | | - function replace( $table, $uniqueIndexes, $rows, $fname = 'Database::replace' ) { |
| 608 | + function replace( $table, $uniqueIndexes, $rows, $fname = 'DatabaseOracle::replace' ) { |
416 | 609 | $table = $this->tableName($table); |
417 | 610 | |
418 | 611 | if (count($rows)==0) { |
— | — | @@ -454,16 +647,14 @@ |
455 | 648 | } |
456 | 649 | |
457 | 650 | # Now insert the row |
458 | | - $sql = "INSERT INTO $table (" . $this->makeList( array_keys( $row ), LIST_NAMES ) .') VALUES (' . |
459 | | - $this->makeList( $row, LIST_COMMA ) . ')'; |
460 | | - $this->query($sql, $fname); |
| 651 | + $this->insert( $table, $row, $fname ); |
461 | 652 | } |
462 | 653 | } |
463 | 654 | |
464 | 655 | # DELETE where the condition is a join |
465 | | - function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = "Database::deleteJoin" ) { |
| 656 | + function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = "DatabaseOracle::deleteJoin" ) { |
466 | 657 | if ( !$conds ) { |
467 | | - throw new DBUnexpectedError($this, 'Database::deleteJoin() called with empty $conds' ); |
| 658 | + throw new DBUnexpectedError($this, 'DatabaseOracle::deleteJoin() called with empty $conds' ); |
468 | 659 | } |
469 | 660 | |
470 | 661 | $delTable = $this->tableName( $delTable ); |
— | — | @@ -502,9 +693,15 @@ |
503 | 694 | function limitResult($sql, $limit, $offset) { |
504 | 695 | if ($offset === false) |
505 | 696 | $offset = 0; |
506 | | - return "SELECT * FROM ($sql) WHERE rownum >= (1 + $offset) AND rownum < 1 + $limit + $offset"; |
| 697 | + return "SELECT * FROM ($sql) WHERE rownum >= (1 + $offset) AND rownum < (1 + $limit + $offset)"; |
507 | 698 | } |
508 | 699 | |
| 700 | + |
| 701 | + function unionQueries($sqls, $all = false) { |
| 702 | + $glue = ' UNION ALL '; |
| 703 | + return 'SELECT * '.($all?'':'/* UNION_UNIQUE */ ').'FROM ('.implode( $glue, $sqls ).')' ; |
| 704 | + } |
| 705 | + |
509 | 706 | /** |
510 | 707 | * Returns an SQL expression for a simple conditional. |
511 | 708 | * Uses CASE on Oracle |
— | — | @@ -540,12 +737,12 @@ |
541 | 738 | ++$this->mErrorCount; |
542 | 739 | |
543 | 740 | if ($ignore || $tempIgnore) { |
544 | | -echo "error ignored! query = [$sql]\n"; |
| 741 | +//echo "error ignored! query = [$sql]\n"; |
545 | 742 | wfDebug("SQL ERROR (ignored): $error\n"); |
546 | 743 | $this->ignoreErrors( $ignore ); |
547 | 744 | } |
548 | 745 | else { |
549 | | -echo "error!\n"; |
| 746 | +//echo "error!\n"; |
550 | 747 | $message = "A database error has occurred\n" . |
551 | 748 | "Query: $sql\n" . |
552 | 749 | "Function: $fname\n" . |
— | — | @@ -572,24 +769,51 @@ |
573 | 770 | * Query whether a given table exists (in the given schema, or the default mw one if not given) |
574 | 771 | */ |
575 | 772 | function tableExists($table) { |
576 | | - $etable= $this->addQuotes($table); |
577 | | - $SQL = "SELECT 1 FROM user_tables WHERE table_name='$etable'"; |
578 | | - $res = $this->query($SQL); |
579 | | - $count = $res ? oci_num_rows($res) : 0; |
580 | | - if ($res) |
581 | | - $this->freeResult($res); |
| 773 | + $SQL = "SELECT 1 FROM user_tables WHERE table_name='$table'"; |
| 774 | + $res = $this->doQuery($SQL); |
| 775 | + if ($res) { |
| 776 | + $count = $res->numRows(); |
| 777 | + $res->free(); |
| 778 | + } else { |
| 779 | + $count = 0; |
| 780 | + } |
582 | 781 | return $count; |
583 | 782 | } |
584 | 783 | |
585 | 784 | /** |
586 | 785 | * Query whether a given column exists in the mediawiki schema |
| 786 | + * based on prebuilt table to simulate MySQL field info and keep query speed minimal |
587 | 787 | */ |
588 | 788 | function fieldExists( $table, $field ) { |
589 | | - return true; // XXX |
| 789 | + if (!isset($this->fieldInfo_stmt)) |
| 790 | + $this->fieldInfo_stmt = oci_parse($this->mConn, 'SELECT * FROM wiki_field_info_full WHERE table_name = upper(:tab) and column_name = UPPER(:col)'); |
| 791 | + |
| 792 | + oci_bind_by_name($this->fieldInfo_stmt, ':tab', trim($table, '"')); |
| 793 | + oci_bind_by_name($this->fieldInfo_stmt, ':col', $field); |
| 794 | + |
| 795 | + if (oci_execute($this->fieldInfo_stmt, OCI_DEFAULT) === false) { |
| 796 | + $e = oci_error($this->fieldInfo_stmt); |
| 797 | + $this->reportQueryError($e['message'], $e['code'], 'fieldInfo QUERY', __METHOD__); |
| 798 | + return false; |
| 799 | + } |
| 800 | + $res = new ORAResult($this,$this->fieldInfo_stmt); |
| 801 | + return $res->numRows() != 0; |
590 | 802 | } |
591 | 803 | |
592 | 804 | function fieldInfo( $table, $field ) { |
593 | | - return false; // XXX |
| 805 | + if (!isset($this->fieldInfo_stmt)) |
| 806 | + $this->fieldInfo_stmt = oci_parse($this->mConn, 'SELECT * FROM wiki_field_info_full WHERE table_name = upper(:tab) and column_name = UPPER(:col)'); |
| 807 | + |
| 808 | + oci_bind_by_name($this->fieldInfo_stmt, ':tab', trim($table, '"')); |
| 809 | + oci_bind_by_name($this->fieldInfo_stmt, ':col', $field); |
| 810 | + |
| 811 | + if (oci_execute($this->fieldInfo_stmt, OCI_DEFAULT) === false) { |
| 812 | + $e = oci_error($this->fieldInfo_stmt); |
| 813 | + $this->reportQueryError($e['message'], $e['code'], 'fieldInfo QUERY', __METHOD__); |
| 814 | + return false; |
| 815 | + } |
| 816 | + $res = new ORAResult($this,$this->fieldInfo_stmt); |
| 817 | + return new ORAField($res->fetchRow()); |
594 | 818 | } |
595 | 819 | |
596 | 820 | function begin( $fname = '' ) { |
— | — | @@ -620,8 +844,9 @@ |
621 | 845 | } |
622 | 846 | |
623 | 847 | function addQuotes( $s ) { |
624 | | - global $wgLang; |
625 | | - $s = $wgLang->checkTitleEncoding($s); |
| 848 | + global $wgLang; |
| 849 | + if (isset($wgLang->mLoaded) && $wgLang->mLoaded) |
| 850 | + $s = $wgLang->checkTitleEncoding($s); |
626 | 851 | return "'" . $this->strencode($s) . "'"; |
627 | 852 | } |
628 | 853 | |
— | — | @@ -634,6 +859,15 @@ |
635 | 860 | return true; |
636 | 861 | } |
637 | 862 | |
| 863 | + function selectRow( $table, $vars, $conds, $fname = 'DatabaseOracle::selectRow', $options = array(), $join_conds = array() ) { |
| 864 | + if (is_array($table)) |
| 865 | + foreach ($table as $tab) |
| 866 | + $tab = $this->tableName($tab); |
| 867 | + else |
| 868 | + $table = $this->tableName($table); |
| 869 | + return parent::selectRow($table, $vars, $conds, $fname, $options, $join_conds); |
| 870 | + } |
| 871 | + |
638 | 872 | /** |
639 | 873 | * Returns an optional USE INDEX clause to go after the table, and a |
640 | 874 | * string to go at the end of the query |
— | — | @@ -658,12 +892,6 @@ |
659 | 893 | if ( isset( $options['GROUP BY'] ) ) $preLimitTail .= " GROUP BY {$options['GROUP BY']}"; |
660 | 894 | if ( isset( $options['ORDER BY'] ) ) $preLimitTail .= " ORDER BY {$options['ORDER BY']}"; |
661 | 895 | |
662 | | - if (isset($options['LIMIT'])) { |
663 | | - // $tailOpts .= $this->limitResult('', $options['LIMIT'], |
664 | | - // isset($options['OFFSET']) ? $options['OFFSET'] |
665 | | - // : false); |
666 | | - } |
667 | | - |
668 | 896 | #if ( isset( $noKeyOptions['FOR UPDATE'] ) ) $tailOpts .= ' FOR UPDATE'; |
669 | 897 | #if ( isset( $noKeyOptions['LOCK IN SHARE MODE'] ) ) $tailOpts .= ' LOCK IN SHARE MODE'; |
670 | 898 | if ( isset( $noKeyOptions['DISTINCT'] ) || isset( $noKeyOptions['DISTINCTROW'] ) ) $startOpts .= 'DISTINCT'; |
— | — | @@ -677,6 +905,38 @@ |
678 | 906 | return array( $startOpts, $useIndex, $preLimitTail, $postLimitTail ); |
679 | 907 | } |
680 | 908 | |
| 909 | + public function makeList( $a, $mode = LIST_COMMA ) { |
| 910 | + if ( !is_array( $a ) ) { |
| 911 | + throw new DBUnexpectedError( $this, 'DatabaseOracle::makeList called with incorrect parameters' ); |
| 912 | + } |
| 913 | + $a2 = array(); |
| 914 | + foreach ($a as $key => $value) { |
| 915 | + if (strpos($key, ' & ') !== FALSE) |
| 916 | + $a2[preg_replace('/(.*)\s&\s(.*)/', 'BITAND($1, $2)', $key)] = $value; |
| 917 | + elseif (strpos($key, ' | ') !== FALSE) |
| 918 | + $a2[preg_replace('/(.*)\s|\s(.*)/', 'BITOR($1, $2)', $key)] = $value; |
| 919 | + elseif (!is_array($value)) { |
| 920 | + if (strpos($value, ' = ') !== FALSE) { |
| 921 | + if (strpos($value, ' & ') !== FALSE) |
| 922 | + $a2[$key] = preg_replace('/(.*)\s&\s(.*?)\s=\s(.*)/', 'BITAND($1, $2) = $3', $value); |
| 923 | + elseif (strpos($value, ' | ') !== FALSE) |
| 924 | + $a2[$key] = preg_replace('/(.*)\s|\s(.*?)\s=\s(.*)/', 'BITOR($1, $2) = $3', $value); |
| 925 | + else $a2[$key] = $value; |
| 926 | + } |
| 927 | + elseif (strpos($value, ' & ') !== FALSE) |
| 928 | + $a2[$key] = preg_replace('/(.*)\s&\s(.*)/', 'BITAND($1, $2)', $value); |
| 929 | + elseif (strpos($value, ' | ') !== FALSE) |
| 930 | + $a2[$key] = preg_replace('/(.*)\s|\s(.*)/', 'BITOR($1, $2)', $value); |
| 931 | + else |
| 932 | + $a2[$key] = $value; |
| 933 | + } |
| 934 | + else |
| 935 | + $a2[$key] = $value; |
| 936 | + } |
| 937 | + |
| 938 | + return parent::makeList($a2, $mode); |
| 939 | + } |
| 940 | + |
681 | 941 | public function setTimeout( $timeout ) { |
682 | 942 | // @todo fixme no-op |
683 | 943 | } |
Index: trunk/phase3/includes/SearchOracle.php |
— | — | @@ -38,6 +38,9 @@ |
39 | 39 | * @return OracleSearchResultSet |
40 | 40 | */ |
41 | 41 | function searchText( $term ) { |
| 42 | + if ($term == '') |
| 43 | + return new OracleSearchResultSet(false, ''); |
| 44 | + |
42 | 45 | $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), true))); |
43 | 46 | return new OracleSearchResultSet($resultSet, $this->searchTerms); |
44 | 47 | } |
— | — | @@ -49,6 +52,9 @@ |
50 | 53 | * @return ORacleSearchResultSet |
51 | 54 | */ |
52 | 55 | function searchTitle($term) { |
| 56 | + if ($term == '') |
| 57 | + return new OracleSearchResultSet(false, ''); |
| 58 | + |
53 | 59 | $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), false))); |
54 | 60 | return new MySQLSearchResultSet($resultSet, $this->searchTerms); |
55 | 61 | } |
— | — | @@ -214,6 +220,7 @@ |
215 | 221 | * @ingroup Search |
216 | 222 | */ |
217 | 223 | class OracleSearchResultSet extends SearchResultSet { |
| 224 | + |
218 | 225 | function __construct($resultSet, $terms) { |
219 | 226 | $this->mResultSet = $resultSet; |
220 | 227 | $this->mTerms = $terms; |
— | — | @@ -224,10 +231,16 @@ |
225 | 232 | } |
226 | 233 | |
227 | 234 | function numRows() { |
228 | | - return $this->mResultSet->numRows(); |
| 235 | + if ($this->mResultSet === false ) |
| 236 | + return 0; |
| 237 | + else |
| 238 | + return $this->mResultSet->numRows(); |
229 | 239 | } |
230 | 240 | |
231 | 241 | function next() { |
| 242 | + if ($this->mResultSet === false ) |
| 243 | + return false; |
| 244 | + |
232 | 245 | $row = $this->mResultSet->fetchObject(); |
233 | 246 | if ($row === false) |
234 | 247 | return false; |
Index: trunk/phase3/includes/specials/SpecialUnusedimages.php |
— | — | @@ -25,9 +25,16 @@ |
26 | 26 | global $wgCountCategorizedImagesAsUsed, $wgDBtype; |
27 | 27 | $dbr = wfGetDB( DB_SLAVE ); |
28 | 28 | |
29 | | - $epoch = $wgDBtype == 'mysql' ? |
30 | | - 'UNIX_TIMESTAMP(img_timestamp)' : |
31 | | - 'EXTRACT(epoch FROM img_timestamp)'; |
| 29 | + switch ($wgDBtype) { |
| 30 | + case 'mysql': |
| 31 | + $epoch = 'UNIX_TIMESTAMP(img_timestamp)'; |
| 32 | + break; |
| 33 | + case 'oracle': |
| 34 | + $epoch = '((trunc(img_timestamp) - to_date(\'19700101\',\'YYYYMMDD\')) * 86400)'; |
| 35 | + break; |
| 36 | + default: |
| 37 | + $epoch = 'EXTRACT(epoch FROM img_timestamp)'; |
| 38 | + } |
32 | 39 | |
33 | 40 | if ( $wgCountCategorizedImagesAsUsed ) { |
34 | 41 | list( $page, $image, $imagelinks, $categorylinks ) = $dbr->tableNamesN( 'page', 'image', 'imagelinks', 'categorylinks' ); |
Index: trunk/phase3/includes/specials/SpecialAncientpages.php |
— | — | @@ -25,8 +25,18 @@ |
26 | 26 | $db = wfGetDB( DB_SLAVE ); |
27 | 27 | $page = $db->tableName( 'page' ); |
28 | 28 | $revision = $db->tableName( 'revision' ); |
29 | | - $epoch = $wgDBtype == 'mysql' ? 'UNIX_TIMESTAMP(rev_timestamp)' : |
30 | | - 'EXTRACT(epoch FROM rev_timestamp)'; |
| 29 | + |
| 30 | + switch ($wgDBtype) { |
| 31 | + case 'mysql': |
| 32 | + $epoch = 'UNIX_TIMESTAMP(rev_timestamp)'; |
| 33 | + break; |
| 34 | + case 'oracle': |
| 35 | + $epoch = '((trunc(rev_timestamp) - to_date(\'19700101\',\'YYYYMMDD\')) * 86400)'; |
| 36 | + break; |
| 37 | + default: |
| 38 | + $epoch = 'EXTRACT(epoch FROM rev_timestamp)'; |
| 39 | + } |
| 40 | + |
31 | 41 | return |
32 | 42 | "SELECT 'Ancientpages' as type, |
33 | 43 | page_namespace as namespace, |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -37,6 +37,8 @@ |
38 | 38 | which was already effectively treating the namespace as if it had subpages. |
39 | 39 | * (bug 10837) $wgVariant is a user variant selected in the user's preferences |
40 | 40 | if the $wgContLang does not have variant, then the $wgLang is used instead. |
| 41 | +* Oracle: maintenance/ora/user.sql script for creating DB user on oracle with |
| 42 | + appropriate privileges |
41 | 43 | |
42 | 44 | === New features in 1.16 === |
43 | 45 | |