Index: trunk/phase3/maintenance/ibm_db2/tables.sql |
— | — | @@ -1,604 +1,604 @@ |
2 | | -
|
3 | | -
|
4 | | -
|
5 | | -
|
6 | | -
|
7 | | -CREATE SEQUENCE user_user_id_seq AS INTEGER START WITH 0 INCREMENT BY 1;
|
8 | | -CREATE TABLE mwuser ( -- replace reserved word 'user'
|
9 | | - user_id INTEGER NOT NULL PRIMARY KEY, -- DEFAULT nextval('user_user_id_seq'),
|
10 | | - user_name VARCHAR(255) NOT NULL UNIQUE,
|
11 | | - user_real_name VARCHAR(255),
|
12 | | - user_password clob(1K),
|
13 | | - user_newpassword clob(1K),
|
14 | | - user_newpass_time TIMESTAMP,
|
15 | | - user_token VARCHAR(255),
|
16 | | - user_email VARCHAR(255),
|
17 | | - user_email_token VARCHAR(255),
|
18 | | - user_email_token_expires TIMESTAMP,
|
19 | | - user_email_authenticated TIMESTAMP,
|
20 | | - user_options CLOB(64K),
|
21 | | - user_touched TIMESTAMP,
|
22 | | - user_registration TIMESTAMP,
|
23 | | - user_editcount INTEGER
|
24 | | -);
|
25 | | -CREATE INDEX user_email_token_idx ON mwuser (user_email_token);
|
26 | | -
|
27 | | -INSERT INTO mwuser
|
28 | | - VALUES (NEXTVAL FOR user_user_id_seq,'Anonymous','', NULL,NULL,CURRENT_TIMESTAMP,NULL, NULL,NULL,NULL,NULL, NULL,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,0);
|
29 | | -
|
30 | | -CREATE TABLE user_groups (
|
31 | | - ug_user INTEGER REFERENCES mwuser(user_id) ON DELETE CASCADE,
|
32 | | - ug_group VARCHAR(255) NOT NULL
|
33 | | -);
|
34 | | -CREATE UNIQUE INDEX user_groups_unique ON user_groups (ug_user, ug_group);
|
35 | | -
|
36 | | -CREATE TABLE user_newtalk (
|
37 | | - user_id INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE,
|
38 | | - user_ip VARCHAR(255),
|
39 | | - user_last_timestamp TIMESTAMP
|
40 | | -);
|
41 | | -CREATE INDEX user_newtalk_id_idx ON user_newtalk (user_id);
|
42 | | -CREATE INDEX user_newtalk_ip_idx ON user_newtalk (user_ip);
|
43 | | -
|
44 | | -
|
45 | | -CREATE SEQUENCE page_page_id_seq;
|
46 | | -CREATE TABLE page (
|
47 | | - page_id INTEGER NOT NULL PRIMARY KEY, -- DEFAULT NEXT VALUE FOR user_user_id_seq,
|
48 | | - page_namespace SMALLINT NOT NULL,
|
49 | | - page_title VARCHAR(255) NOT NULL,
|
50 | | - page_restrictions clob(1K),
|
51 | | - page_counter BIGINT NOT NULL DEFAULT 0,
|
52 | | - page_is_redirect SMALLINT NOT NULL DEFAULT 0,
|
53 | | - page_is_new SMALLINT NOT NULL DEFAULT 0,
|
54 | | - page_random NUMERIC(15,14) NOT NULL,
|
55 | | - page_touched TIMESTAMP,
|
56 | | - page_latest INTEGER NOT NULL, -- FK?
|
57 | | - page_len INTEGER NOT NULL
|
58 | | -);
|
59 | | -CREATE UNIQUE INDEX page_unique_name ON page (page_namespace, page_title);
|
60 | | -CREATE INDEX page_random_idx ON page (page_random);
|
61 | | -CREATE INDEX page_len_idx ON page (page_len);
|
62 | | -
|
63 | | -
|
64 | | -
|
65 | | -CREATE SEQUENCE rev_rev_id_val;
|
66 | | -CREATE TABLE revision (
|
67 | | - rev_id INTEGER NOT NULL UNIQUE, --DEFAULT nextval('rev_rev_id_val'),
|
68 | | - rev_page INTEGER REFERENCES page (page_id) ON DELETE CASCADE,
|
69 | | - rev_text_id INTEGER, -- FK
|
70 | | - rev_comment clob(1K), -- changed from VARCHAR(255)
|
71 | | - rev_user INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE RESTRICT,
|
72 | | - rev_user_text VARCHAR(255) NOT NULL,
|
73 | | - rev_timestamp TIMESTAMP NOT NULL,
|
74 | | - rev_minor_edit SMALLINT NOT NULL DEFAULT 0,
|
75 | | - rev_deleted SMALLINT NOT NULL DEFAULT 0,
|
76 | | - rev_len INTEGER,
|
77 | | - rev_parent_id INTEGER
|
78 | | -);
|
79 | | -CREATE UNIQUE INDEX revision_unique ON revision (rev_page, rev_id);
|
80 | | -CREATE INDEX rev_text_id_idx ON revision (rev_text_id);
|
81 | | -CREATE INDEX rev_timestamp_idx ON revision (rev_timestamp);
|
82 | | -CREATE INDEX rev_user_idx ON revision (rev_user);
|
83 | | -CREATE INDEX rev_user_text_idx ON revision (rev_user_text);
|
84 | | -
|
85 | | -
|
86 | | -CREATE SEQUENCE text_old_id_val;
|
87 | | -CREATE TABLE pagecontent ( -- replaces reserved word 'text'
|
88 | | - old_id INTEGER NOT NULL,
|
89 | | - --PRIMARY KEY DEFAULT nextval('text_old_id_val'),
|
90 | | - old_text CLOB(16M),
|
91 | | - old_flags clob(1K)
|
92 | | -);
|
93 | | -
|
94 | | -CREATE SEQUENCE pr_id_val;
|
95 | | -CREATE TABLE page_restrictions (
|
96 | | - pr_id INTEGER NOT NULL UNIQUE,
|
97 | | - --DEFAULT nextval('pr_id_val'),
|
98 | | - pr_page INTEGER NOT NULL
|
99 | | - --(used to be nullable)
|
100 | | - REFERENCES page (page_id) ON DELETE CASCADE,
|
101 | | - pr_type VARCHAR(255) NOT NULL,
|
102 | | - pr_level VARCHAR(255) NOT NULL,
|
103 | | - pr_cascade SMALLINT NOT NULL,
|
104 | | - pr_user INTEGER,
|
105 | | - pr_expiry TIMESTAMP,
|
106 | | - PRIMARY KEY (pr_page, pr_type)
|
107 | | -);
|
108 | | -
|
109 | | -CREATE TABLE page_props (
|
110 | | - pp_page INTEGER NOT NULL REFERENCES page (page_id) ON DELETE CASCADE,
|
111 | | - pp_propname VARCHAR(255) NOT NULL,
|
112 | | - pp_value CLOB(64K) NOT NULL,
|
113 | | - PRIMARY KEY (pp_page,pp_propname)
|
114 | | -);
|
115 | | -CREATE INDEX page_props_propname ON page_props (pp_propname);
|
116 | | -
|
117 | | -
|
118 | | -
|
119 | | -CREATE TABLE archive (
|
120 | | - ar_namespace SMALLINT NOT NULL,
|
121 | | - ar_title VARCHAR(255) NOT NULL,
|
122 | | - ar_text CLOB(16M),
|
123 | | - ar_page_id INTEGER,
|
124 | | - ar_parent_id INTEGER,
|
125 | | - ar_comment clob(1K),
|
126 | | - ar_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL,
|
127 | | - ar_user_text VARCHAR(255) NOT NULL,
|
128 | | - ar_timestamp TIMESTAMP NOT NULL,
|
129 | | - ar_minor_edit SMALLINT NOT NULL DEFAULT 0,
|
130 | | - ar_flags clob(1K),
|
131 | | - ar_rev_id INTEGER,
|
132 | | - ar_text_id INTEGER,
|
133 | | - ar_deleted SMALLINT NOT NULL DEFAULT 0,
|
134 | | - ar_len INTEGER
|
135 | | -);
|
136 | | -CREATE INDEX archive_name_title_timestamp ON archive (ar_namespace,ar_title,ar_timestamp);
|
137 | | -CREATE INDEX archive_user_text ON archive (ar_user_text);
|
138 | | -
|
139 | | -
|
140 | | -
|
141 | | -CREATE TABLE redirect (
|
142 | | - rd_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
|
143 | | - rd_namespace SMALLINT NOT NULL,
|
144 | | - rd_title VARCHAR(255) NOT NULL
|
145 | | -);
|
146 | | -CREATE INDEX redirect_ns_title ON redirect (rd_namespace,rd_title,rd_from);
|
147 | | -
|
148 | | -
|
149 | | -CREATE TABLE pagelinks (
|
150 | | - pl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
|
151 | | - pl_namespace SMALLINT NOT NULL,
|
152 | | - pl_title VARCHAR(255) NOT NULL
|
153 | | -);
|
154 | | -CREATE UNIQUE INDEX pagelink_unique ON pagelinks (pl_from,pl_namespace,pl_title);
|
155 | | -
|
156 | | -CREATE TABLE templatelinks (
|
157 | | - tl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
|
158 | | - tl_namespace SMALLINT NOT NULL,
|
159 | | - tl_title VARCHAR(255) NOT NULL
|
160 | | -);
|
161 | | -CREATE UNIQUE INDEX templatelinks_unique ON templatelinks (tl_namespace,tl_title,tl_from);
|
162 | | -
|
163 | | -CREATE TABLE imagelinks (
|
164 | | - il_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
|
165 | | - il_to VARCHAR(255) NOT NULL
|
166 | | -);
|
167 | | -CREATE UNIQUE INDEX il_from ON imagelinks (il_to,il_from);
|
168 | | -
|
169 | | -CREATE TABLE categorylinks (
|
170 | | - cl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
|
171 | | - cl_to VARCHAR(255) NOT NULL,
|
172 | | - cl_sortkey VARCHAR(255),
|
173 | | - cl_timestamp TIMESTAMP NOT NULL
|
174 | | -);
|
175 | | -CREATE UNIQUE INDEX cl_from ON categorylinks (cl_from, cl_to);
|
176 | | -CREATE INDEX cl_sortkey ON categorylinks (cl_to, cl_sortkey, cl_from);
|
177 | | -
|
178 | | -
|
179 | | -
|
180 | | -CREATE TABLE externallinks (
|
181 | | - el_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE,
|
182 | | - el_to VARCHAR(255) NOT NULL,
|
183 | | - el_index VARCHAR(255) NOT NULL
|
184 | | -);
|
185 | | -CREATE INDEX externallinks_from_to ON externallinks (el_from,el_to);
|
186 | | -CREATE INDEX externallinks_index ON externallinks (el_index);
|
187 | | -
|
188 | | -CREATE TABLE langlinks (
|
189 | | - ll_from INTEGER NOT NULL REFERENCES page (page_id) ON DELETE CASCADE,
|
190 | | - ll_lang VARCHAR(255),
|
191 | | - ll_title VARCHAR(255)
|
192 | | -);
|
193 | | -CREATE UNIQUE INDEX langlinks_unique ON langlinks (ll_from,ll_lang);
|
194 | | -CREATE INDEX langlinks_lang_title ON langlinks (ll_lang,ll_title);
|
195 | | -
|
196 | | -
|
197 | | -CREATE TABLE site_stats (
|
198 | | - ss_row_id INTEGER NOT NULL UNIQUE,
|
199 | | - ss_total_views INTEGER DEFAULT 0,
|
200 | | - ss_total_edits INTEGER DEFAULT 0,
|
201 | | - ss_good_articles INTEGER DEFAULT 0,
|
202 | | - ss_total_pages INTEGER DEFAULT -1,
|
203 | | - ss_users INTEGER DEFAULT -1,
|
204 | | - ss_admins INTEGER DEFAULT -1,
|
205 | | - ss_images INTEGER DEFAULT 0
|
206 | | -);
|
207 | | -
|
208 | | -CREATE TABLE hitcounter (
|
209 | | - hc_id BIGINT NOT NULL
|
210 | | -);
|
211 | | -
|
212 | | -CREATE SEQUENCE ipblocks_ipb_id_val;
|
213 | | -CREATE TABLE ipblocks (
|
214 | | - ipb_id INTEGER NOT NULL PRIMARY KEY,
|
215 | | - --DEFAULT nextval('ipblocks_ipb_id_val'),
|
216 | | - ipb_address VARCHAR(255),
|
217 | | - ipb_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL,
|
218 | | - ipb_by INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE,
|
219 | | - ipb_by_text VARCHAR(255) NOT NULL DEFAULT '',
|
220 | | - ipb_reason VARCHAR(255) NOT NULL,
|
221 | | - ipb_timestamp TIMESTAMP NOT NULL,
|
222 | | - ipb_auto SMALLINT NOT NULL DEFAULT 0,
|
223 | | - ipb_anon_only SMALLINT NOT NULL DEFAULT 0,
|
224 | | - ipb_create_account SMALLINT NOT NULL DEFAULT 1,
|
225 | | - ipb_enable_autoblock SMALLINT NOT NULL DEFAULT 1,
|
226 | | - ipb_expiry TIMESTAMP NOT NULL,
|
227 | | - ipb_range_start VARCHAR(255),
|
228 | | - ipb_range_end VARCHAR(255),
|
229 | | - ipb_deleted SMALLINT NOT NULL DEFAULT 0,
|
230 | | - ipb_block_email SMALLINT NOT NULL DEFAULT 0
|
231 | | -
|
232 | | -);
|
233 | | -CREATE INDEX ipb_address ON ipblocks (ipb_address);
|
234 | | -CREATE INDEX ipb_user ON ipblocks (ipb_user);
|
235 | | -CREATE INDEX ipb_range ON ipblocks (ipb_range_start,ipb_range_end);
|
236 | | -
|
237 | | -
|
238 | | -
|
239 | | -CREATE TABLE image (
|
240 | | - img_name VARCHAR(255) NOT NULL PRIMARY KEY,
|
241 | | - img_size INTEGER NOT NULL,
|
242 | | - img_width INTEGER NOT NULL,
|
243 | | - img_height INTEGER NOT NULL,
|
244 | | - img_metadata CLOB(16M) NOT NULL DEFAULT '',
|
245 | | - img_bits SMALLINT,
|
246 | | - img_media_type VARCHAR(255),
|
247 | | - img_major_mime VARCHAR(255) DEFAULT 'unknown',
|
248 | | - img_minor_mime VARCHAR(255) DEFAULT 'unknown',
|
249 | | - img_description clob(1K) NOT NULL DEFAULT '',
|
250 | | - img_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL,
|
251 | | - img_user_text VARCHAR(255) NOT NULL DEFAULT '',
|
252 | | - img_timestamp TIMESTAMP,
|
253 | | - img_sha1 VARCHAR(255) NOT NULL DEFAULT ''
|
254 | | -);
|
255 | | -CREATE INDEX img_size_idx ON image (img_size);
|
256 | | -CREATE INDEX img_timestamp_idx ON image (img_timestamp);
|
257 | | -CREATE INDEX img_sha1 ON image (img_sha1);
|
258 | | -
|
259 | | -CREATE TABLE oldimage (
|
260 | | - oi_name VARCHAR(255) NOT NULL,
|
261 | | - oi_archive_name VARCHAR(255) NOT NULL,
|
262 | | - oi_size INTEGER NOT NULL,
|
263 | | - oi_width INTEGER NOT NULL,
|
264 | | - oi_height INTEGER NOT NULL,
|
265 | | - oi_bits SMALLINT NOT NULL,
|
266 | | - oi_description clob(1K),
|
267 | | - oi_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL,
|
268 | | - oi_user_text VARCHAR(255) NOT NULL,
|
269 | | - oi_timestamp TIMESTAMP NOT NULL,
|
270 | | - oi_metadata CLOB(16M) NOT NULL DEFAULT '',
|
271 | | - oi_media_type VARCHAR(255) ,
|
272 | | - oi_major_mime VARCHAR(255) NOT NULL DEFAULT 'unknown',
|
273 | | - oi_minor_mime VARCHAR(255) NOT NULL DEFAULT 'unknown',
|
274 | | - oi_deleted SMALLINT NOT NULL DEFAULT 0,
|
275 | | - oi_sha1 VARCHAR(255) NOT NULL DEFAULT '',
|
276 | | - FOREIGN KEY (oi_name) REFERENCES image(img_name) ON DELETE CASCADE
|
277 | | -);
|
278 | | -CREATE INDEX oi_name_timestamp ON oldimage (oi_name,oi_timestamp);
|
279 | | -CREATE INDEX oi_name_archive_name ON oldimage (oi_name,oi_archive_name);
|
280 | | -CREATE INDEX oi_sha1 ON oldimage (oi_sha1);
|
281 | | -
|
282 | | -
|
283 | | -CREATE SEQUENCE filearchive_fa_id_seq;
|
284 | | -CREATE TABLE filearchive (
|
285 | | - fa_id INTEGER NOT NULL PRIMARY KEY,
|
286 | | - --PRIMARY KEY DEFAULT nextval('filearchive_fa_id_seq'),
|
287 | | - fa_name VARCHAR(255) NOT NULL,
|
288 | | - fa_archive_name VARCHAR(255),
|
289 | | - fa_storage_group VARCHAR(255),
|
290 | | - fa_storage_key VARCHAR(255),
|
291 | | - fa_deleted_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL,
|
292 | | - fa_deleted_timestamp TIMESTAMP NOT NULL,
|
293 | | - fa_deleted_reason VARCHAR(255),
|
294 | | - fa_size INTEGER NOT NULL,
|
295 | | - fa_width INTEGER NOT NULL,
|
296 | | - fa_height INTEGER NOT NULL,
|
297 | | - fa_metadata CLOB(16M) NOT NULL DEFAULT '',
|
298 | | - fa_bits SMALLINT,
|
299 | | - fa_media_type VARCHAR(255),
|
300 | | - fa_major_mime VARCHAR(255) DEFAULT 'unknown',
|
301 | | - fa_minor_mime VARCHAR(255) DEFAULT 'unknown',
|
302 | | - fa_description clob(1K) NOT NULL,
|
303 | | - fa_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL,
|
304 | | - fa_user_text VARCHAR(255) NOT NULL,
|
305 | | - fa_timestamp TIMESTAMP,
|
306 | | - fa_deleted SMALLINT NOT NULL DEFAULT 0
|
307 | | -);
|
308 | | -CREATE INDEX fa_name_time ON filearchive (fa_name, fa_timestamp);
|
309 | | -CREATE INDEX fa_dupe ON filearchive (fa_storage_group, fa_storage_key);
|
310 | | -CREATE INDEX fa_notime ON filearchive (fa_deleted_timestamp);
|
311 | | -CREATE INDEX fa_nouser ON filearchive (fa_deleted_user);
|
312 | | -
|
313 | | -CREATE SEQUENCE rc_rc_id_seq;
|
314 | | -CREATE TABLE recentchanges (
|
315 | | - rc_id INTEGER NOT NULL PRIMARY KEY,
|
316 | | - --PRIMARY KEY DEFAULT nextval('rc_rc_id_seq'),
|
317 | | - rc_timestamp TIMESTAMP NOT NULL,
|
318 | | - rc_cur_time TIMESTAMP NOT NULL,
|
319 | | - rc_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL,
|
320 | | - rc_user_text VARCHAR(255) NOT NULL,
|
321 | | - rc_namespace SMALLINT NOT NULL,
|
322 | | - rc_title VARCHAR(255) NOT NULL,
|
323 | | - rc_comment VARCHAR(255),
|
324 | | - rc_minor SMALLINT NOT NULL DEFAULT 0,
|
325 | | - rc_bot SMALLINT NOT NULL DEFAULT 0,
|
326 | | - rc_new SMALLINT NOT NULL DEFAULT 0,
|
327 | | - rc_cur_id INTEGER REFERENCES page(page_id) ON DELETE SET NULL,
|
328 | | - rc_this_oldid INTEGER NOT NULL,
|
329 | | - rc_last_oldid INTEGER NOT NULL,
|
330 | | - rc_type SMALLINT NOT NULL DEFAULT 0,
|
331 | | - rc_moved_to_ns SMALLINT,
|
332 | | - rc_moved_to_title VARCHAR(255),
|
333 | | - rc_patrolled SMALLINT NOT NULL DEFAULT 0,
|
334 | | - rc_ip VARCHAR(255), -- was CIDR type
|
335 | | - rc_old_len INTEGER,
|
336 | | - rc_new_len INTEGER,
|
337 | | - rc_deleted SMALLINT NOT NULL DEFAULT 0,
|
338 | | - rc_logid INTEGER NOT NULL DEFAULT 0,
|
339 | | - rc_log_type VARCHAR(255),
|
340 | | - rc_log_action VARCHAR(255),
|
341 | | - rc_params CLOB(64K)
|
342 | | -);
|
343 | | -CREATE INDEX rc_timestamp ON recentchanges (rc_timestamp);
|
344 | | -CREATE INDEX rc_namespace_title ON recentchanges (rc_namespace, rc_title);
|
345 | | -CREATE INDEX rc_cur_id ON recentchanges (rc_cur_id);
|
346 | | -CREATE INDEX new_name_timestamp ON recentchanges (rc_new, rc_namespace, rc_timestamp);
|
347 | | -CREATE INDEX rc_ip ON recentchanges (rc_ip);
|
348 | | -
|
349 | | -
|
350 | | -
|
351 | | -CREATE TABLE watchlist (
|
352 | | - wl_user INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE,
|
353 | | - wl_namespace SMALLINT NOT NULL DEFAULT 0,
|
354 | | - wl_title VARCHAR(255) NOT NULL,
|
355 | | - wl_notificationtimestamp TIMESTAMP
|
356 | | -);
|
357 | | -CREATE UNIQUE INDEX wl_user_namespace_title ON watchlist (wl_namespace, wl_title, wl_user);
|
358 | | -
|
359 | | -
|
360 | | -CREATE TABLE math (
|
361 | | - math_inputhash VARGRAPHIC(255) NOT NULL UNIQUE,
|
362 | | - math_outputhash VARGRAPHIC(255) NOT NULL,
|
363 | | - math_html_conservativeness SMALLINT NOT NULL,
|
364 | | - math_html VARCHAR(255),
|
365 | | - math_mathml VARCHAR(255)
|
366 | | -);
|
367 | | -
|
368 | | -
|
369 | | -CREATE TABLE interwiki (
|
370 | | - iw_prefix VARCHAR(255) NOT NULL UNIQUE,
|
371 | | - iw_url CLOB(64K) NOT NULL,
|
372 | | - iw_local SMALLINT NOT NULL,
|
373 | | - iw_trans SMALLINT NOT NULL DEFAULT 0
|
374 | | -);
|
375 | | -
|
376 | | -
|
377 | | -CREATE TABLE querycache (
|
378 | | - qc_type VARCHAR(255) NOT NULL,
|
379 | | - qc_value INTEGER NOT NULL,
|
380 | | - qc_namespace SMALLINT NOT NULL,
|
381 | | - qc_title VARCHAR(255) NOT NULL
|
382 | | -);
|
383 | | -CREATE INDEX querycache_type_value ON querycache (qc_type, qc_value);
|
384 | | -
|
385 | | -
|
386 | | -
|
387 | | -CREATE TABLE querycache_info (
|
388 | | - qci_type VARCHAR(255) UNIQUE NOT NULL,
|
389 | | - qci_timestamp TIMESTAMP
|
390 | | -);
|
391 | | -
|
392 | | -
|
393 | | -CREATE TABLE querycachetwo (
|
394 | | - qcc_type VARCHAR(255) NOT NULL,
|
395 | | - qcc_value INTEGER NOT NULL DEFAULT 0,
|
396 | | - qcc_namespace INTEGER NOT NULL DEFAULT 0,
|
397 | | - qcc_title VARCHAR(255) NOT NULL DEFAULT '',
|
398 | | - qcc_namespacetwo INTEGER NOT NULL DEFAULT 0,
|
399 | | - qcc_titletwo VARCHAR(255) NOT NULL DEFAULT ''
|
400 | | -);
|
401 | | -CREATE INDEX querycachetwo_type_value ON querycachetwo (qcc_type, qcc_value);
|
402 | | -CREATE INDEX querycachetwo_title ON querycachetwo (qcc_type,qcc_namespace,qcc_title);
|
403 | | -CREATE INDEX querycachetwo_titletwo ON querycachetwo (qcc_type,qcc_namespacetwo,qcc_titletwo);
|
404 | | -
|
405 | | -CREATE TABLE objectcache (
|
406 | | - keyname VARCHAR(255) NOT NULL UNIQUE, -- was nullable
|
407 | | - value CLOB(16M) NOT NULL DEFAULT '',
|
408 | | - exptime TIMESTAMP NOT NULL
|
409 | | -);
|
410 | | -CREATE INDEX objectcacache_exptime ON objectcache (exptime);
|
411 | | -
|
412 | | -
|
413 | | -
|
414 | | -CREATE TABLE transcache (
|
415 | | - tc_url VARCHAR(255) NOT NULL UNIQUE,
|
416 | | - tc_contents VARCHAR(255) NOT NULL,
|
417 | | - tc_time TIMESTAMP NOT NULL
|
418 | | -);
|
419 | | -
|
420 | | -CREATE SEQUENCE log_log_id_seq;
|
421 | | -CREATE TABLE logging (
|
422 | | - log_id INTEGER NOT NULL PRIMARY KEY,
|
423 | | - --PRIMARY KEY DEFAULT nextval('log_log_id_seq'),
|
424 | | - log_type VARCHAR(255) NOT NULL,
|
425 | | - log_action VARCHAR(255) NOT NULL,
|
426 | | - log_timestamp TIMESTAMP NOT NULL,
|
427 | | - log_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL,
|
428 | | - log_namespace SMALLINT NOT NULL,
|
429 | | - log_title VARCHAR(255) NOT NULL,
|
430 | | - log_comment VARCHAR(255),
|
431 | | - log_params CLOB(64K),
|
432 | | - log_deleted SMALLINT NOT NULL DEFAULT 0
|
433 | | -);
|
434 | | -CREATE INDEX logging_type_name ON logging (log_type, log_timestamp);
|
435 | | -CREATE INDEX logging_user_time ON logging (log_timestamp, log_user);
|
436 | | -CREATE INDEX logging_page_time ON logging (log_namespace, log_title, log_timestamp);
|
437 | | -
|
438 | | -CREATE SEQUENCE trackbacks_tb_id_seq;
|
439 | | -CREATE TABLE trackbacks (
|
440 | | - tb_id INTEGER NOT NULL PRIMARY KEY,
|
441 | | - --PRIMARY KEY DEFAULT nextval('trackbacks_tb_id_seq'),
|
442 | | - tb_page INTEGER REFERENCES page(page_id) ON DELETE CASCADE,
|
443 | | - tb_title VARCHAR(255) NOT NULL,
|
444 | | - tb_url CLOB(64K) NOT NULL,
|
445 | | - tb_ex VARCHAR(255),
|
446 | | - tb_name VARCHAR(255)
|
447 | | -);
|
448 | | -CREATE INDEX trackback_page ON trackbacks (tb_page);
|
449 | | -
|
450 | | -
|
451 | | -CREATE SEQUENCE job_job_id_seq;
|
452 | | -CREATE TABLE job (
|
453 | | - job_id INTEGER NOT NULL PRIMARY KEY,
|
454 | | - --PRIMARY KEY DEFAULT nextval('job_job_id_seq'),
|
455 | | - job_cmd VARCHAR(255) NOT NULL,
|
456 | | - job_namespace SMALLINT NOT NULL,
|
457 | | - job_title VARCHAR(255) NOT NULL,
|
458 | | - job_params CLOB(64K) NOT NULL
|
459 | | -);
|
460 | | -CREATE INDEX job_cmd_namespace_title ON job (job_cmd, job_namespace, job_title);
|
461 | | -
|
462 | | -
|
463 | | -
|
464 | | -
|
465 | | -
|
466 | | -
|
467 | | -
|
468 | | -
|
469 | | -
|
470 | | -
|
471 | | -
|
472 | | -CREATE TABLE searchindex (
|
473 | | - si_page int NOT NULL,
|
474 | | - si_title varchar(255) NOT NULL default '',
|
475 | | - si_text clob NOT NULL
|
476 | | -);
|
477 | | -
|
478 | | -CREATE TABLE profiling (
|
479 | | - pf_count INTEGER NOT NULL DEFAULT 0,
|
480 | | - pf_time NUMERIC(18,10) NOT NULL DEFAULT 0,
|
481 | | - pf_memory NUMERIC(18,10) NOT NULL DEFAULT 0,
|
482 | | - pf_name VARCHAR(255) NOT NULL,
|
483 | | - pf_server VARCHAR(255)
|
484 | | -);
|
485 | | -CREATE UNIQUE INDEX pf_name_server ON profiling (pf_name, pf_server);
|
486 | | -
|
487 | | -CREATE TABLE protected_titles (
|
488 | | - pt_namespace SMALLINT NOT NULL,
|
489 | | - pt_title VARCHAR(255) NOT NULL,
|
490 | | - pt_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL,
|
491 | | - pt_reason clob(1K),
|
492 | | - pt_timestamp TIMESTAMP NOT NULL,
|
493 | | - pt_expiry TIMESTAMP ,
|
494 | | - pt_create_perm VARCHAR(255) NOT NULL DEFAULT ''
|
495 | | -);
|
496 | | -CREATE UNIQUE INDEX protected_titles_unique ON protected_titles(pt_namespace, pt_title);
|
497 | | -
|
498 | | -
|
499 | | -
|
500 | | -CREATE TABLE updatelog (
|
501 | | - ul_key VARCHAR(255) NOT NULL PRIMARY KEY
|
502 | | -);
|
503 | | -
|
504 | | -CREATE SEQUENCE category_id_seq;
|
505 | | -CREATE TABLE category (
|
506 | | - cat_id INTEGER NOT NULL PRIMARY KEY,
|
507 | | - --PRIMARY KEY DEFAULT nextval('category_id_seq'),
|
508 | | - cat_title VARCHAR(255) NOT NULL,
|
509 | | - cat_pages INTEGER NOT NULL DEFAULT 0,
|
510 | | - cat_subcats INTEGER NOT NULL DEFAULT 0,
|
511 | | - cat_files INTEGER NOT NULL DEFAULT 0,
|
512 | | - cat_hidden SMALLINT NOT NULL DEFAULT 0
|
513 | | -);
|
514 | | -CREATE UNIQUE INDEX category_title ON category(cat_title);
|
515 | | -CREATE INDEX category_pages ON category(cat_pages);
|
516 | | -
|
517 | | -CREATE TABLE mediawiki_version (
|
518 | | - type VARCHAR(255) NOT NULL,
|
519 | | - mw_version VARCHAR(255) NOT NULL,
|
520 | | - notes VARCHAR(255) ,
|
521 | | -
|
522 | | - pg_version VARCHAR(255) ,
|
523 | | - pg_dbname VARCHAR(255) ,
|
524 | | - pg_user VARCHAR(255) ,
|
525 | | - pg_port VARCHAR(255) ,
|
526 | | - mw_schema VARCHAR(255) ,
|
527 | | - ts2_schema VARCHAR(255) ,
|
528 | | - ctype VARCHAR(255) ,
|
529 | | -
|
530 | | - sql_version VARCHAR(255) ,
|
531 | | - sql_date VARCHAR(255) ,
|
532 | | - cdate TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP
|
533 | | -);
|
534 | | -
|
535 | | -INSERT INTO mediawiki_version (type,mw_version,sql_version,sql_date)
|
536 | | - VALUES ('Creation','??','$LastChangedRevision: 34049 $','$LastChangedDate: 2008-04-30 10:20:36 -0400 (Wed, 30 Apr 2008) $');
|
537 | | -
|
| 2 | +-- DB2 |
| 3 | + |
| 4 | +-- SQL to create the initial tables for the MediaWiki database. |
| 5 | +-- This is read and executed by the install script; you should |
| 6 | +-- not have to run it by itself unless doing a manual install. |
| 7 | +-- This is the IBM DB2 version. |
| 8 | +-- For information about each table, please see the notes in maintenance/tables.sql |
| 9 | +-- Please make sure all dollar-quoting uses $mw$ at the start of the line |
| 10 | +-- TODO: Change CHAR/SMALLINT to BOOL (still used in a non-bool fashion in PHP code) |
| 11 | + |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +CREATE SEQUENCE user_user_id_seq AS INTEGER START WITH 0 INCREMENT BY 1; |
| 16 | +CREATE TABLE mwuser ( -- replace reserved word 'user' |
| 17 | + user_id INTEGER NOT NULL PRIMARY KEY, -- DEFAULT nextval('user_user_id_seq'), |
| 18 | + user_name VARCHAR(255) NOT NULL UNIQUE, |
| 19 | + user_real_name VARCHAR(255), |
| 20 | + user_password clob(1K), |
| 21 | + user_newpassword clob(1K), |
| 22 | + user_newpass_time TIMESTAMP, |
| 23 | + user_token VARCHAR(255), |
| 24 | + user_email VARCHAR(255), |
| 25 | + user_email_token VARCHAR(255), |
| 26 | + user_email_token_expires TIMESTAMP, |
| 27 | + user_email_authenticated TIMESTAMP, |
| 28 | + user_options CLOB(64K), |
| 29 | + user_touched TIMESTAMP, |
| 30 | + user_registration TIMESTAMP, |
| 31 | + user_editcount INTEGER |
| 32 | +); |
| 33 | +CREATE INDEX user_email_token_idx ON mwuser (user_email_token); |
| 34 | + |
| 35 | +-- Create a dummy user to satisfy fk contraints especially with revisions |
| 36 | +INSERT INTO mwuser |
| 37 | + VALUES (NEXTVAL FOR user_user_id_seq,'Anonymous','', NULL,NULL,CURRENT_TIMESTAMP,NULL, NULL,NULL,NULL,NULL, NULL,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,0); |
| 38 | + |
| 39 | +CREATE TABLE user_groups ( |
| 40 | + ug_user INTEGER REFERENCES mwuser(user_id) ON DELETE CASCADE, |
| 41 | + ug_group VARCHAR(255) NOT NULL |
| 42 | +); |
| 43 | +CREATE UNIQUE INDEX user_groups_unique ON user_groups (ug_user, ug_group); |
| 44 | + |
| 45 | +CREATE TABLE user_newtalk ( |
| 46 | + user_id INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE, |
| 47 | + user_ip VARCHAR(255), |
| 48 | + user_last_timestamp TIMESTAMP |
| 49 | +); |
| 50 | +CREATE INDEX user_newtalk_id_idx ON user_newtalk (user_id); |
| 51 | +CREATE INDEX user_newtalk_ip_idx ON user_newtalk (user_ip); |
| 52 | + |
| 53 | + |
| 54 | +CREATE SEQUENCE page_page_id_seq; |
| 55 | +CREATE TABLE page ( |
| 56 | + page_id INTEGER NOT NULL PRIMARY KEY, -- DEFAULT NEXT VALUE FOR user_user_id_seq, |
| 57 | + page_namespace SMALLINT NOT NULL, |
| 58 | + page_title VARCHAR(255) NOT NULL, |
| 59 | + page_restrictions clob(1K), |
| 60 | + page_counter BIGINT NOT NULL DEFAULT 0, |
| 61 | + page_is_redirect SMALLINT NOT NULL DEFAULT 0, |
| 62 | + page_is_new SMALLINT NOT NULL DEFAULT 0, |
| 63 | + page_random NUMERIC(15,14) NOT NULL, |
| 64 | + page_touched TIMESTAMP, |
| 65 | + page_latest INTEGER NOT NULL, -- FK? |
| 66 | + page_len INTEGER NOT NULL |
| 67 | +); |
| 68 | +CREATE UNIQUE INDEX page_unique_name ON page (page_namespace, page_title); |
| 69 | +--CREATE INDEX page_main_title ON page (page_title) WHERE page_namespace = 0; |
| 70 | +--CREATE INDEX page_talk_title ON page (page_title) WHERE page_namespace = 1; |
| 71 | +--CREATE INDEX page_user_title ON page (page_title) WHERE page_namespace = 2; |
| 72 | +--CREATE INDEX page_utalk_title ON page (page_title) WHERE page_namespace = 3; |
| 73 | +--CREATE INDEX page_project_title ON page (page_title) WHERE page_namespace = 4; |
| 74 | +CREATE INDEX page_random_idx ON page (page_random); |
| 75 | +CREATE INDEX page_len_idx ON page (page_len); |
| 76 | + |
| 77 | +--CREATE FUNCTION page_deleted() RETURNS TRIGGER LANGUAGE plpgsql AS |
| 78 | +--$mw$ |
| 79 | +--BEGIN |
| 80 | +--DELETE FROM recentchanges WHERE rc_namespace = OLD.page_namespace AND rc_title = OLD.page_title; |
| 81 | +--RETURN NULL; |
| 82 | +--END; |
| 83 | +--$mw$; |
| 84 | + |
| 85 | +--CREATE TRIGGER page_deleted AFTER DELETE ON page |
| 86 | +-- FOR EACH ROW EXECUTE PROCEDURE page_deleted(); |
| 87 | + |
| 88 | +CREATE SEQUENCE rev_rev_id_val; |
| 89 | +CREATE TABLE revision ( |
| 90 | + rev_id INTEGER NOT NULL UNIQUE, --DEFAULT nextval('rev_rev_id_val'), |
| 91 | + rev_page INTEGER REFERENCES page (page_id) ON DELETE CASCADE, |
| 92 | + rev_text_id INTEGER, -- FK |
| 93 | + rev_comment clob(1K), -- changed from VARCHAR(255) |
| 94 | + rev_user INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE RESTRICT, |
| 95 | + rev_user_text VARCHAR(255) NOT NULL, |
| 96 | + rev_timestamp TIMESTAMP NOT NULL, |
| 97 | + rev_minor_edit SMALLINT NOT NULL DEFAULT 0, |
| 98 | + rev_deleted SMALLINT NOT NULL DEFAULT 0, |
| 99 | + rev_len INTEGER, |
| 100 | + rev_parent_id INTEGER |
| 101 | +); |
| 102 | +CREATE UNIQUE INDEX revision_unique ON revision (rev_page, rev_id); |
| 103 | +CREATE INDEX rev_text_id_idx ON revision (rev_text_id); |
| 104 | +CREATE INDEX rev_timestamp_idx ON revision (rev_timestamp); |
| 105 | +CREATE INDEX rev_user_idx ON revision (rev_user); |
| 106 | +CREATE INDEX rev_user_text_idx ON revision (rev_user_text); |
| 107 | + |
| 108 | + |
| 109 | +CREATE SEQUENCE text_old_id_val; |
| 110 | +CREATE TABLE pagecontent ( -- replaces reserved word 'text' |
| 111 | + old_id INTEGER NOT NULL, |
| 112 | + --PRIMARY KEY DEFAULT nextval('text_old_id_val'), |
| 113 | + old_text CLOB(16M), |
| 114 | + old_flags clob(1K) |
| 115 | +); |
| 116 | + |
| 117 | +CREATE SEQUENCE pr_id_val; |
| 118 | +CREATE TABLE page_restrictions ( |
| 119 | + pr_id INTEGER NOT NULL UNIQUE, |
| 120 | + --DEFAULT nextval('pr_id_val'), |
| 121 | + pr_page INTEGER NOT NULL |
| 122 | + --(used to be nullable) |
| 123 | + REFERENCES page (page_id) ON DELETE CASCADE, |
| 124 | + pr_type VARCHAR(255) NOT NULL, |
| 125 | + pr_level VARCHAR(255) NOT NULL, |
| 126 | + pr_cascade SMALLINT NOT NULL, |
| 127 | + pr_user INTEGER, |
| 128 | + pr_expiry TIMESTAMP, |
| 129 | + PRIMARY KEY (pr_page, pr_type) |
| 130 | +); |
| 131 | +--ALTER TABLE page_restrictions ADD CONSTRAINT page_restrictions_pk PRIMARY KEY (pr_page,pr_type); |
| 132 | + |
| 133 | +CREATE TABLE page_props ( |
| 134 | + pp_page INTEGER NOT NULL REFERENCES page (page_id) ON DELETE CASCADE, |
| 135 | + pp_propname VARCHAR(255) NOT NULL, |
| 136 | + pp_value CLOB(64K) NOT NULL, |
| 137 | + PRIMARY KEY (pp_page,pp_propname) |
| 138 | +); |
| 139 | +--ALTER TABLE page_props ADD CONSTRAINT page_props_pk PRIMARY KEY (pp_page,pp_propname); |
| 140 | +CREATE INDEX page_props_propname ON page_props (pp_propname); |
| 141 | + |
| 142 | + |
| 143 | + |
| 144 | +CREATE TABLE archive ( |
| 145 | + ar_namespace SMALLINT NOT NULL, |
| 146 | + ar_title VARCHAR(255) NOT NULL, |
| 147 | + ar_text CLOB(16M), |
| 148 | + ar_page_id INTEGER, |
| 149 | + ar_parent_id INTEGER, |
| 150 | + ar_comment clob(1K), |
| 151 | + ar_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, |
| 152 | + ar_user_text VARCHAR(255) NOT NULL, |
| 153 | + ar_timestamp TIMESTAMP NOT NULL, |
| 154 | + ar_minor_edit SMALLINT NOT NULL DEFAULT 0, |
| 155 | + ar_flags clob(1K), |
| 156 | + ar_rev_id INTEGER, |
| 157 | + ar_text_id INTEGER, |
| 158 | + ar_deleted SMALLINT NOT NULL DEFAULT 0, |
| 159 | + ar_len INTEGER |
| 160 | +); |
| 161 | +CREATE INDEX archive_name_title_timestamp ON archive (ar_namespace,ar_title,ar_timestamp); |
| 162 | +CREATE INDEX archive_user_text ON archive (ar_user_text); |
| 163 | + |
| 164 | + |
| 165 | + |
| 166 | +CREATE TABLE redirect ( |
| 167 | + rd_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
| 168 | + rd_namespace SMALLINT NOT NULL, |
| 169 | + rd_title VARCHAR(255) NOT NULL |
| 170 | +); |
| 171 | +CREATE INDEX redirect_ns_title ON redirect (rd_namespace,rd_title,rd_from); |
| 172 | + |
| 173 | + |
| 174 | +CREATE TABLE pagelinks ( |
| 175 | + pl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
| 176 | + pl_namespace SMALLINT NOT NULL, |
| 177 | + pl_title VARCHAR(255) NOT NULL |
| 178 | +); |
| 179 | +CREATE UNIQUE INDEX pagelink_unique ON pagelinks (pl_from,pl_namespace,pl_title); |
| 180 | + |
| 181 | +CREATE TABLE templatelinks ( |
| 182 | + tl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
| 183 | + tl_namespace SMALLINT NOT NULL, |
| 184 | + tl_title VARCHAR(255) NOT NULL |
| 185 | +); |
| 186 | +CREATE UNIQUE INDEX templatelinks_unique ON templatelinks (tl_namespace,tl_title,tl_from); |
| 187 | + |
| 188 | +CREATE TABLE imagelinks ( |
| 189 | + il_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
| 190 | + il_to VARCHAR(255) NOT NULL |
| 191 | +); |
| 192 | +CREATE UNIQUE INDEX il_from ON imagelinks (il_to,il_from); |
| 193 | + |
| 194 | +CREATE TABLE categorylinks ( |
| 195 | + cl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
| 196 | + cl_to VARCHAR(255) NOT NULL, |
| 197 | + cl_sortkey VARCHAR(255), |
| 198 | + cl_timestamp TIMESTAMP NOT NULL |
| 199 | +); |
| 200 | +CREATE UNIQUE INDEX cl_from ON categorylinks (cl_from, cl_to); |
| 201 | +CREATE INDEX cl_sortkey ON categorylinks (cl_to, cl_sortkey, cl_from); |
| 202 | + |
| 203 | + |
| 204 | + |
| 205 | +CREATE TABLE externallinks ( |
| 206 | + el_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, |
| 207 | + el_to VARCHAR(255) NOT NULL, |
| 208 | + el_index VARCHAR(255) NOT NULL |
| 209 | +); |
| 210 | +CREATE INDEX externallinks_from_to ON externallinks (el_from,el_to); |
| 211 | +CREATE INDEX externallinks_index ON externallinks (el_index); |
| 212 | + |
| 213 | +CREATE TABLE langlinks ( |
| 214 | + ll_from INTEGER NOT NULL REFERENCES page (page_id) ON DELETE CASCADE, |
| 215 | + ll_lang VARCHAR(255), |
| 216 | + ll_title VARCHAR(255) |
| 217 | +); |
| 218 | +CREATE UNIQUE INDEX langlinks_unique ON langlinks (ll_from,ll_lang); |
| 219 | +CREATE INDEX langlinks_lang_title ON langlinks (ll_lang,ll_title); |
| 220 | + |
| 221 | + |
| 222 | +CREATE TABLE site_stats ( |
| 223 | + ss_row_id INTEGER NOT NULL UNIQUE, |
| 224 | + ss_total_views INTEGER DEFAULT 0, |
| 225 | + ss_total_edits INTEGER DEFAULT 0, |
| 226 | + ss_good_articles INTEGER DEFAULT 0, |
| 227 | + ss_total_pages INTEGER DEFAULT -1, |
| 228 | + ss_users INTEGER DEFAULT -1, |
| 229 | + ss_admins INTEGER DEFAULT -1, |
| 230 | + ss_images INTEGER DEFAULT 0 |
| 231 | +); |
| 232 | + |
| 233 | +CREATE TABLE hitcounter ( |
| 234 | + hc_id BIGINT NOT NULL |
| 235 | +); |
| 236 | + |
| 237 | +CREATE SEQUENCE ipblocks_ipb_id_val; |
| 238 | +CREATE TABLE ipblocks ( |
| 239 | + ipb_id INTEGER NOT NULL PRIMARY KEY, |
| 240 | + --DEFAULT nextval('ipblocks_ipb_id_val'), |
| 241 | + ipb_address VARCHAR(255), |
| 242 | + ipb_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, |
| 243 | + ipb_by INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE, |
| 244 | + ipb_by_text VARCHAR(255) NOT NULL DEFAULT '', |
| 245 | + ipb_reason VARCHAR(255) NOT NULL, |
| 246 | + ipb_timestamp TIMESTAMP NOT NULL, |
| 247 | + ipb_auto SMALLINT NOT NULL DEFAULT 0, |
| 248 | + ipb_anon_only SMALLINT NOT NULL DEFAULT 0, |
| 249 | + ipb_create_account SMALLINT NOT NULL DEFAULT 1, |
| 250 | + ipb_enable_autoblock SMALLINT NOT NULL DEFAULT 1, |
| 251 | + ipb_expiry TIMESTAMP NOT NULL, |
| 252 | + ipb_range_start VARCHAR(255), |
| 253 | + ipb_range_end VARCHAR(255), |
| 254 | + ipb_deleted SMALLINT NOT NULL DEFAULT 0, |
| 255 | + ipb_block_email SMALLINT NOT NULL DEFAULT 0 |
| 256 | + |
| 257 | +); |
| 258 | +CREATE INDEX ipb_address ON ipblocks (ipb_address); |
| 259 | +CREATE INDEX ipb_user ON ipblocks (ipb_user); |
| 260 | +CREATE INDEX ipb_range ON ipblocks (ipb_range_start,ipb_range_end); |
| 261 | + |
| 262 | + |
| 263 | + |
| 264 | +CREATE TABLE image ( |
| 265 | + img_name VARCHAR(255) NOT NULL PRIMARY KEY, |
| 266 | + img_size INTEGER NOT NULL, |
| 267 | + img_width INTEGER NOT NULL, |
| 268 | + img_height INTEGER NOT NULL, |
| 269 | + img_metadata CLOB(16M) NOT NULL DEFAULT '', |
| 270 | + img_bits SMALLINT, |
| 271 | + img_media_type VARCHAR(255), |
| 272 | + img_major_mime VARCHAR(255) DEFAULT 'unknown', |
| 273 | + img_minor_mime VARCHAR(255) DEFAULT 'unknown', |
| 274 | + img_description clob(1K) NOT NULL DEFAULT '', |
| 275 | + img_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, |
| 276 | + img_user_text VARCHAR(255) NOT NULL DEFAULT '', |
| 277 | + img_timestamp TIMESTAMP, |
| 278 | + img_sha1 VARCHAR(255) NOT NULL DEFAULT '' |
| 279 | +); |
| 280 | +CREATE INDEX img_size_idx ON image (img_size); |
| 281 | +CREATE INDEX img_timestamp_idx ON image (img_timestamp); |
| 282 | +CREATE INDEX img_sha1 ON image (img_sha1); |
| 283 | + |
| 284 | +CREATE TABLE oldimage ( |
| 285 | + oi_name VARCHAR(255) NOT NULL, |
| 286 | + oi_archive_name VARCHAR(255) NOT NULL, |
| 287 | + oi_size INTEGER NOT NULL, |
| 288 | + oi_width INTEGER NOT NULL, |
| 289 | + oi_height INTEGER NOT NULL, |
| 290 | + oi_bits SMALLINT NOT NULL, |
| 291 | + oi_description clob(1K), |
| 292 | + oi_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, |
| 293 | + oi_user_text VARCHAR(255) NOT NULL, |
| 294 | + oi_timestamp TIMESTAMP NOT NULL, |
| 295 | + oi_metadata CLOB(16M) NOT NULL DEFAULT '', |
| 296 | + oi_media_type VARCHAR(255) , |
| 297 | + oi_major_mime VARCHAR(255) NOT NULL DEFAULT 'unknown', |
| 298 | + oi_minor_mime VARCHAR(255) NOT NULL DEFAULT 'unknown', |
| 299 | + oi_deleted SMALLINT NOT NULL DEFAULT 0, |
| 300 | + oi_sha1 VARCHAR(255) NOT NULL DEFAULT '', |
| 301 | + FOREIGN KEY (oi_name) REFERENCES image(img_name) ON DELETE CASCADE |
| 302 | +); |
| 303 | +--ALTER TABLE oldimage ADD CONSTRAINT oldimage_oi_name_fkey_cascade FOREIGN KEY (oi_name) REFERENCES image(img_name) ON DELETE CASCADE; |
| 304 | +CREATE INDEX oi_name_timestamp ON oldimage (oi_name,oi_timestamp); |
| 305 | +CREATE INDEX oi_name_archive_name ON oldimage (oi_name,oi_archive_name); |
| 306 | +CREATE INDEX oi_sha1 ON oldimage (oi_sha1); |
| 307 | + |
| 308 | + |
| 309 | +CREATE SEQUENCE filearchive_fa_id_seq; |
| 310 | +CREATE TABLE filearchive ( |
| 311 | + fa_id INTEGER NOT NULL PRIMARY KEY, |
| 312 | + --PRIMARY KEY DEFAULT nextval('filearchive_fa_id_seq'), |
| 313 | + fa_name VARCHAR(255) NOT NULL, |
| 314 | + fa_archive_name VARCHAR(255), |
| 315 | + fa_storage_group VARCHAR(255), |
| 316 | + fa_storage_key VARCHAR(255), |
| 317 | + fa_deleted_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, |
| 318 | + fa_deleted_timestamp TIMESTAMP NOT NULL, |
| 319 | + fa_deleted_reason VARCHAR(255), |
| 320 | + fa_size INTEGER NOT NULL, |
| 321 | + fa_width INTEGER NOT NULL, |
| 322 | + fa_height INTEGER NOT NULL, |
| 323 | + fa_metadata CLOB(16M) NOT NULL DEFAULT '', |
| 324 | + fa_bits SMALLINT, |
| 325 | + fa_media_type VARCHAR(255), |
| 326 | + fa_major_mime VARCHAR(255) DEFAULT 'unknown', |
| 327 | + fa_minor_mime VARCHAR(255) DEFAULT 'unknown', |
| 328 | + fa_description clob(1K) NOT NULL, |
| 329 | + fa_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, |
| 330 | + fa_user_text VARCHAR(255) NOT NULL, |
| 331 | + fa_timestamp TIMESTAMP, |
| 332 | + fa_deleted SMALLINT NOT NULL DEFAULT 0 |
| 333 | +); |
| 334 | +CREATE INDEX fa_name_time ON filearchive (fa_name, fa_timestamp); |
| 335 | +CREATE INDEX fa_dupe ON filearchive (fa_storage_group, fa_storage_key); |
| 336 | +CREATE INDEX fa_notime ON filearchive (fa_deleted_timestamp); |
| 337 | +CREATE INDEX fa_nouser ON filearchive (fa_deleted_user); |
| 338 | + |
| 339 | +CREATE SEQUENCE rc_rc_id_seq; |
| 340 | +CREATE TABLE recentchanges ( |
| 341 | + rc_id INTEGER NOT NULL PRIMARY KEY, |
| 342 | + --PRIMARY KEY DEFAULT nextval('rc_rc_id_seq'), |
| 343 | + rc_timestamp TIMESTAMP NOT NULL, |
| 344 | + rc_cur_time TIMESTAMP NOT NULL, |
| 345 | + rc_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, |
| 346 | + rc_user_text VARCHAR(255) NOT NULL, |
| 347 | + rc_namespace SMALLINT NOT NULL, |
| 348 | + rc_title VARCHAR(255) NOT NULL, |
| 349 | + rc_comment VARCHAR(255), |
| 350 | + rc_minor SMALLINT NOT NULL DEFAULT 0, |
| 351 | + rc_bot SMALLINT NOT NULL DEFAULT 0, |
| 352 | + rc_new SMALLINT NOT NULL DEFAULT 0, |
| 353 | + rc_cur_id INTEGER REFERENCES page(page_id) ON DELETE SET NULL, |
| 354 | + rc_this_oldid INTEGER NOT NULL, |
| 355 | + rc_last_oldid INTEGER NOT NULL, |
| 356 | + rc_type SMALLINT NOT NULL DEFAULT 0, |
| 357 | + rc_moved_to_ns SMALLINT, |
| 358 | + rc_moved_to_title VARCHAR(255), |
| 359 | + rc_patrolled SMALLINT NOT NULL DEFAULT 0, |
| 360 | + rc_ip VARCHAR(255), -- was CIDR type |
| 361 | + rc_old_len INTEGER, |
| 362 | + rc_new_len INTEGER, |
| 363 | + rc_deleted SMALLINT NOT NULL DEFAULT 0, |
| 364 | + rc_logid INTEGER NOT NULL DEFAULT 0, |
| 365 | + rc_log_type VARCHAR(255), |
| 366 | + rc_log_action VARCHAR(255), |
| 367 | + rc_params CLOB(64K) |
| 368 | +); |
| 369 | +CREATE INDEX rc_timestamp ON recentchanges (rc_timestamp); |
| 370 | +CREATE INDEX rc_namespace_title ON recentchanges (rc_namespace, rc_title); |
| 371 | +CREATE INDEX rc_cur_id ON recentchanges (rc_cur_id); |
| 372 | +CREATE INDEX new_name_timestamp ON recentchanges (rc_new, rc_namespace, rc_timestamp); |
| 373 | +CREATE INDEX rc_ip ON recentchanges (rc_ip); |
| 374 | + |
| 375 | + |
| 376 | + |
| 377 | +CREATE TABLE watchlist ( |
| 378 | + wl_user INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE, |
| 379 | + wl_namespace SMALLINT NOT NULL DEFAULT 0, |
| 380 | + wl_title VARCHAR(255) NOT NULL, |
| 381 | + wl_notificationtimestamp TIMESTAMP |
| 382 | +); |
| 383 | +CREATE UNIQUE INDEX wl_user_namespace_title ON watchlist (wl_namespace, wl_title, wl_user); |
| 384 | + |
| 385 | + |
| 386 | +CREATE TABLE math ( |
| 387 | + math_inputhash VARGRAPHIC(255) NOT NULL UNIQUE, |
| 388 | + math_outputhash VARGRAPHIC(255) NOT NULL, |
| 389 | + math_html_conservativeness SMALLINT NOT NULL, |
| 390 | + math_html VARCHAR(255), |
| 391 | + math_mathml VARCHAR(255) |
| 392 | +); |
| 393 | + |
| 394 | + |
| 395 | +CREATE TABLE interwiki ( |
| 396 | + iw_prefix VARCHAR(255) NOT NULL UNIQUE, |
| 397 | + iw_url CLOB(64K) NOT NULL, |
| 398 | + iw_local SMALLINT NOT NULL, |
| 399 | + iw_trans SMALLINT NOT NULL DEFAULT 0 |
| 400 | +); |
| 401 | + |
| 402 | + |
| 403 | +CREATE TABLE querycache ( |
| 404 | + qc_type VARCHAR(255) NOT NULL, |
| 405 | + qc_value INTEGER NOT NULL, |
| 406 | + qc_namespace SMALLINT NOT NULL, |
| 407 | + qc_title VARCHAR(255) NOT NULL |
| 408 | +); |
| 409 | +CREATE INDEX querycache_type_value ON querycache (qc_type, qc_value); |
| 410 | + |
| 411 | + |
| 412 | + |
| 413 | +CREATE TABLE querycache_info ( |
| 414 | + qci_type VARCHAR(255) UNIQUE NOT NULL, |
| 415 | + qci_timestamp TIMESTAMP |
| 416 | +); |
| 417 | + |
| 418 | + |
| 419 | +CREATE TABLE querycachetwo ( |
| 420 | + qcc_type VARCHAR(255) NOT NULL, |
| 421 | + qcc_value INTEGER NOT NULL DEFAULT 0, |
| 422 | + qcc_namespace INTEGER NOT NULL DEFAULT 0, |
| 423 | + qcc_title VARCHAR(255) NOT NULL DEFAULT '', |
| 424 | + qcc_namespacetwo INTEGER NOT NULL DEFAULT 0, |
| 425 | + qcc_titletwo VARCHAR(255) NOT NULL DEFAULT '' |
| 426 | +); |
| 427 | +CREATE INDEX querycachetwo_type_value ON querycachetwo (qcc_type, qcc_value); |
| 428 | +CREATE INDEX querycachetwo_title ON querycachetwo (qcc_type,qcc_namespace,qcc_title); |
| 429 | +CREATE INDEX querycachetwo_titletwo ON querycachetwo (qcc_type,qcc_namespacetwo,qcc_titletwo); |
| 430 | + |
| 431 | +CREATE TABLE objectcache ( |
| 432 | + keyname VARCHAR(255) NOT NULL UNIQUE, -- was nullable |
| 433 | + value CLOB(16M) NOT NULL DEFAULT '', |
| 434 | + exptime TIMESTAMP NOT NULL |
| 435 | +); |
| 436 | +CREATE INDEX objectcacache_exptime ON objectcache (exptime); |
| 437 | + |
| 438 | + |
| 439 | + |
| 440 | +CREATE TABLE transcache ( |
| 441 | + tc_url VARCHAR(255) NOT NULL UNIQUE, |
| 442 | + tc_contents VARCHAR(255) NOT NULL, |
| 443 | + tc_time TIMESTAMP NOT NULL |
| 444 | +); |
| 445 | + |
| 446 | +CREATE SEQUENCE log_log_id_seq; |
| 447 | +CREATE TABLE logging ( |
| 448 | + log_id INTEGER NOT NULL PRIMARY KEY, |
| 449 | + --PRIMARY KEY DEFAULT nextval('log_log_id_seq'), |
| 450 | + log_type VARCHAR(255) NOT NULL, |
| 451 | + log_action VARCHAR(255) NOT NULL, |
| 452 | + log_timestamp TIMESTAMP NOT NULL, |
| 453 | + log_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, |
| 454 | + log_namespace SMALLINT NOT NULL, |
| 455 | + log_title VARCHAR(255) NOT NULL, |
| 456 | + log_comment VARCHAR(255), |
| 457 | + log_params CLOB(64K), |
| 458 | + log_deleted SMALLINT NOT NULL DEFAULT 0 |
| 459 | +); |
| 460 | +CREATE INDEX logging_type_name ON logging (log_type, log_timestamp); |
| 461 | +CREATE INDEX logging_user_time ON logging (log_timestamp, log_user); |
| 462 | +CREATE INDEX logging_page_time ON logging (log_namespace, log_title, log_timestamp); |
| 463 | + |
| 464 | +CREATE SEQUENCE trackbacks_tb_id_seq; |
| 465 | +CREATE TABLE trackbacks ( |
| 466 | + tb_id INTEGER NOT NULL PRIMARY KEY, |
| 467 | + --PRIMARY KEY DEFAULT nextval('trackbacks_tb_id_seq'), |
| 468 | + tb_page INTEGER REFERENCES page(page_id) ON DELETE CASCADE, |
| 469 | + tb_title VARCHAR(255) NOT NULL, |
| 470 | + tb_url CLOB(64K) NOT NULL, |
| 471 | + tb_ex VARCHAR(255), |
| 472 | + tb_name VARCHAR(255) |
| 473 | +); |
| 474 | +CREATE INDEX trackback_page ON trackbacks (tb_page); |
| 475 | + |
| 476 | + |
| 477 | +CREATE SEQUENCE job_job_id_seq; |
| 478 | +CREATE TABLE job ( |
| 479 | + job_id INTEGER NOT NULL PRIMARY KEY, |
| 480 | + --PRIMARY KEY DEFAULT nextval('job_job_id_seq'), |
| 481 | + job_cmd VARCHAR(255) NOT NULL, |
| 482 | + job_namespace SMALLINT NOT NULL, |
| 483 | + job_title VARCHAR(255) NOT NULL, |
| 484 | + job_params CLOB(64K) NOT NULL |
| 485 | +); |
| 486 | +CREATE INDEX job_cmd_namespace_title ON job (job_cmd, job_namespace, job_title); |
| 487 | + |
| 488 | + |
| 489 | + |
| 490 | +-- Postgres' Tsearch2 dropped |
| 491 | +--ALTER TABLE page ADD titlevector tsvector; |
| 492 | +--CREATE FUNCTION ts2_page_title() RETURNS TRIGGER LANGUAGE plpgsql AS |
| 493 | +--$mw$ |
| 494 | +--BEGIN |
| 495 | +--IF TG_OP = 'INSERT' THEN |
| 496 | +-- NEW.titlevector = to_tsvector('default',REPLACE(NEW.page_title,'/',' ')); |
| 497 | +--ELSIF NEW.page_title != OLD.page_title THEN |
| 498 | +-- NEW.titlevector := to_tsvector('default',REPLACE(NEW.page_title,'/',' ')); |
| 499 | +--END IF; |
| 500 | +--RETURN NEW; |
| 501 | +--END; |
| 502 | +--$mw$; |
| 503 | + |
| 504 | +--CREATE TRIGGER ts2_page_title BEFORE INSERT OR UPDATE ON page |
| 505 | +-- FOR EACH ROW EXECUTE PROCEDURE ts2_page_title(); |
| 506 | + |
| 507 | + |
| 508 | +--ALTER TABLE pagecontent ADD textvector tsvector; |
| 509 | +--CREATE FUNCTION ts2_page_text() RETURNS TRIGGER LANGUAGE plpgsql AS |
| 510 | +--$mw$ |
| 511 | +--BEGIN |
| 512 | +--IF TG_OP = 'INSERT' THEN |
| 513 | +-- NEW.textvector = to_tsvector('default',NEW.old_text); |
| 514 | +--ELSIF NEW.old_text != OLD.old_text THEN |
| 515 | +-- NEW.textvector := to_tsvector('default',NEW.old_text); |
| 516 | +--END IF; |
| 517 | +--RETURN NEW; |
| 518 | +--END; |
| 519 | +--$mw$; |
| 520 | + |
| 521 | +--CREATE TRIGGER ts2_page_text BEFORE INSERT OR UPDATE ON pagecontent |
| 522 | +-- FOR EACH ROW EXECUTE PROCEDURE ts2_page_text(); |
| 523 | + |
| 524 | +-- These are added by the setup script due to version compatibility issues |
| 525 | +-- If using 8.1, we switch from "gin" to "gist" |
| 526 | + |
| 527 | +--CREATE INDEX ts2_page_title ON page USING gin(titlevector); |
| 528 | +--CREATE INDEX ts2_page_text ON pagecontent USING gin(textvector); |
| 529 | + |
| 530 | +--TODO |
| 531 | +--CREATE FUNCTION add_interwiki (TEXT,INT,SMALLINT) RETURNS INT LANGUAGE SQL AS |
| 532 | +--$mw$ |
| 533 | +-- INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES ($1,$2,$3); |
| 534 | +-- SELECT 1; |
| 535 | +--$mw$; |
| 536 | + |
| 537 | +-- hack implementation |
| 538 | +-- should be replaced with OmniFind, Contains(), etc |
| 539 | +CREATE TABLE searchindex ( |
| 540 | + si_page int NOT NULL, |
| 541 | + si_title varchar(255) NOT NULL default '', |
| 542 | + si_text clob NOT NULL |
| 543 | +); |
| 544 | + |
| 545 | +-- This table is not used unless profiling is turned on |
| 546 | +CREATE TABLE profiling ( |
| 547 | + pf_count INTEGER NOT NULL DEFAULT 0, |
| 548 | + pf_time NUMERIC(18,10) NOT NULL DEFAULT 0, |
| 549 | + pf_memory NUMERIC(18,10) NOT NULL DEFAULT 0, |
| 550 | + pf_name VARCHAR(255) NOT NULL, |
| 551 | + pf_server VARCHAR(255) |
| 552 | +); |
| 553 | +CREATE UNIQUE INDEX pf_name_server ON profiling (pf_name, pf_server); |
| 554 | + |
| 555 | +CREATE TABLE protected_titles ( |
| 556 | + pt_namespace SMALLINT NOT NULL, |
| 557 | + pt_title VARCHAR(255) NOT NULL, |
| 558 | + pt_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, |
| 559 | + pt_reason clob(1K), |
| 560 | + pt_timestamp TIMESTAMP NOT NULL, |
| 561 | + pt_expiry TIMESTAMP , |
| 562 | + pt_create_perm VARCHAR(255) NOT NULL DEFAULT '' |
| 563 | +); |
| 564 | +CREATE UNIQUE INDEX protected_titles_unique ON protected_titles(pt_namespace, pt_title); |
| 565 | + |
| 566 | + |
| 567 | + |
| 568 | +CREATE TABLE updatelog ( |
| 569 | + ul_key VARCHAR(255) NOT NULL PRIMARY KEY |
| 570 | +); |
| 571 | + |
| 572 | +CREATE SEQUENCE category_id_seq; |
| 573 | +CREATE TABLE category ( |
| 574 | + cat_id INTEGER NOT NULL PRIMARY KEY, |
| 575 | + --PRIMARY KEY DEFAULT nextval('category_id_seq'), |
| 576 | + cat_title VARCHAR(255) NOT NULL, |
| 577 | + cat_pages INTEGER NOT NULL DEFAULT 0, |
| 578 | + cat_subcats INTEGER NOT NULL DEFAULT 0, |
| 579 | + cat_files INTEGER NOT NULL DEFAULT 0, |
| 580 | + cat_hidden SMALLINT NOT NULL DEFAULT 0 |
| 581 | +); |
| 582 | +CREATE UNIQUE INDEX category_title ON category(cat_title); |
| 583 | +CREATE INDEX category_pages ON category(cat_pages); |
| 584 | + |
| 585 | +CREATE TABLE mediawiki_version ( |
| 586 | + type VARCHAR(255) NOT NULL, |
| 587 | + mw_version VARCHAR(255) NOT NULL, |
| 588 | + notes VARCHAR(255) , |
| 589 | + |
| 590 | + pg_version VARCHAR(255) , |
| 591 | + pg_dbname VARCHAR(255) , |
| 592 | + pg_user VARCHAR(255) , |
| 593 | + pg_port VARCHAR(255) , |
| 594 | + mw_schema VARCHAR(255) , |
| 595 | + ts2_schema VARCHAR(255) , |
| 596 | + ctype VARCHAR(255) , |
| 597 | + |
| 598 | + sql_version VARCHAR(255) , |
| 599 | + sql_date VARCHAR(255) , |
| 600 | + cdate TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP |
| 601 | +); |
| 602 | + |
| 603 | +INSERT INTO mediawiki_version (type,mw_version,sql_version,sql_date) |
| 604 | + VALUES ('Creation','??','$LastChangedRevision: 34049 $','$LastChangedDate: 2008-04-30 10:20:36 -0400 (Wed, 30 Apr 2008) $'); |
| 605 | + |
Property changes on: trunk/phase3/maintenance/ibm_db2/tables.sql |
___________________________________________________________________ |
Name: svn:eol-style |
538 | 606 | + native |
Index: trunk/phase3/maintenance/ibm_db2/README |
— | — | @@ -1,41 +1,41 @@ |
2 | | -== Syntax differences between other databases and IBM DB2 ==
|
3 | | -{| border cellspacing=0 cellpadding=4
|
4 | | -!MySQL!!IBM DB2
|
5 | | -|-
|
6 | | -
|
7 | | -|SELECT 1 FROM $table LIMIT 1
|
8 | | -|SELECT COUNT(*) FROM SYSIBM.SYSTABLES ST
|
9 | | -WHERE ST.NAME = '$table' AND ST.CREATOR = '$schema'
|
10 | | -|-
|
11 | | -|MySQL code tries to read one row and interprets lack of error as proof of existence.
|
12 | | -|DB2 code counts the number of TABLES of that name in the database. There ought to be 1 for it to exist.
|
13 | | -|-
|
14 | | -|BEGIN
|
15 | | -|(implicit)
|
16 | | -|-
|
17 | | -|TEXT
|
18 | | -|VARCHAR(255) or CLOB
|
19 | | -|-
|
20 | | -|TIMESTAMPTZ
|
21 | | -|TIMESTAMP
|
22 | | -|-
|
23 | | -|BYTEA
|
24 | | -|VARGRAPHIC(255)
|
25 | | -|-
|
26 | | -|DEFAULT nextval('some_kind_of_sequence'),
|
27 | | -|GENERATED ALWAYS AS IDENTITY (START WITH 0, INCREMENT BY 1),
|
28 | | -|-
|
29 | | -|CIDR
|
30 | | -|VARCHAR(255)
|
31 | | -|-
|
32 | | -|LIMIT 10
|
33 | | -|FETCH FIRST 10 ROWS ONLY
|
34 | | -|-
|
35 | | -|ROLLBACK TO
|
36 | | -|ROLLBACK TO SAVEPOINT
|
37 | | -|-
|
38 | | -|RELEASE
|
39 | | -|RELEASE SAVEPOINT
|
40 | | -|}
|
41 | | -== See also ==
|
| 2 | +== Syntax differences between other databases and IBM DB2 == |
| 3 | +{| border cellspacing=0 cellpadding=4 |
| 4 | +!MySQL!!IBM DB2 |
| 5 | +|- |
| 6 | + |
| 7 | +|SELECT 1 FROM $table LIMIT 1 |
| 8 | +|SELECT COUNT(*) FROM SYSIBM.SYSTABLES ST |
| 9 | +WHERE ST.NAME = '$table' AND ST.CREATOR = '$schema' |
| 10 | +|- |
| 11 | +|MySQL code tries to read one row and interprets lack of error as proof of existence. |
| 12 | +|DB2 code counts the number of TABLES of that name in the database. There ought to be 1 for it to exist. |
| 13 | +|- |
| 14 | +|BEGIN |
| 15 | +|(implicit) |
| 16 | +|- |
| 17 | +|TEXT |
| 18 | +|VARCHAR(255) or CLOB |
| 19 | +|- |
| 20 | +|TIMESTAMPTZ |
| 21 | +|TIMESTAMP |
| 22 | +|- |
| 23 | +|BYTEA |
| 24 | +|VARGRAPHIC(255) |
| 25 | +|- |
| 26 | +|DEFAULT nextval('some_kind_of_sequence'), |
| 27 | +|GENERATED ALWAYS AS IDENTITY (START WITH 0, INCREMENT BY 1), |
| 28 | +|- |
| 29 | +|CIDR |
| 30 | +|VARCHAR(255) |
| 31 | +|- |
| 32 | +|LIMIT 10 |
| 33 | +|FETCH FIRST 10 ROWS ONLY |
| 34 | +|- |
| 35 | +|ROLLBACK TO |
| 36 | +|ROLLBACK TO SAVEPOINT |
| 37 | +|- |
| 38 | +|RELEASE |
| 39 | +|RELEASE SAVEPOINT |
| 40 | +|} |
| 41 | +== See also == |
42 | 42 | *[http://ca.php.net/manual/en/function.db2-connect.php PHP Manual for DB2 functions] |
\ No newline at end of file |
Property changes on: trunk/phase3/maintenance/ibm_db2/README |
___________________________________________________________________ |
Name: svn:eol-style |
43 | 43 | + native |
Index: trunk/phase3/includes/db/DatabaseIbm_db2.php |
— | — | @@ -684,16 +684,16 @@ |
685 | 685 | throw new DBUnexpectedError( $this, 'Error in fetchRow(): ' . htmlspecialchars( $this->lastError() ) ); |
686 | 686 | } |
687 | 687 | return $row; |
688 | | - }
|
689 | | -
|
690 | | - /**
|
691 | | - * Override if introduced to base Database class
|
692 | | - */
|
693 | | - public function initial_setup() {
|
694 | | - // do nothing
|
695 | 688 | } |
696 | 689 | |
697 | 690 | /** |
| 691 | + * Override if introduced to base Database class |
| 692 | + */ |
| 693 | + public function initial_setup() { |
| 694 | + // do nothing |
| 695 | + } |
| 696 | + |
| 697 | + /** |
698 | 698 | * Create tables, stored procedures, and so on |
699 | 699 | */ |
700 | 700 | public function setup_database() { |
— | — | @@ -721,12 +721,12 @@ |
722 | 722 | print "<br><pre>$mwe</pre><br>"; |
723 | 723 | } |
724 | 724 | } |
725 | | -
|
726 | | - /**
|
| 725 | + |
| 726 | + /** |
727 | 727 | * Escapes strings |
728 | | - * Doesn't escape numbers
|
729 | | - * @param string s string to escape
|
730 | | - * @return escaped string
|
| 728 | + * Doesn't escape numbers |
| 729 | + * @param string s string to escape |
| 730 | + * @return escaped string |
731 | 731 | */ |
732 | 732 | public function addQuotes( $s ) { |
733 | 733 | //wfDebug("DB2::addQuotes($s)\n"); |
— | — | @@ -814,48 +814,48 @@ |
815 | 815 | $s = str_replace($from, $to, $s); // DB2 expects '', not \' escaping |
816 | 816 | return $s; |
817 | 817 | } |
818 | | -
|
819 | | - /**
|
820 | | - * Switch into the database schema
|
| 818 | + |
| 819 | + /** |
| 820 | + * Switch into the database schema |
821 | 821 | */ |
822 | 822 | protected function applySchema() { |
823 | | - if ( !($this->mSchemaSet) ) {
|
| 823 | + if ( !($this->mSchemaSet) ) { |
824 | 824 | $this->mSchemaSet = true; |
825 | 825 | $this->begin(); |
826 | | - $this->doQuery("SET SCHEMA = $this->mSchema");
|
| 826 | + $this->doQuery("SET SCHEMA = $this->mSchema"); |
827 | 827 | $this->commit(); |
828 | 828 | } |
829 | | - }
|
830 | | -
|
831 | | - /**
|
832 | | - * Start a transaction (mandatory)
|
833 | | - */
|
834 | | - public function begin() {
|
| 829 | + } |
| 830 | + |
| 831 | + /** |
| 832 | + * Start a transaction (mandatory) |
| 833 | + */ |
| 834 | + public function begin() { |
835 | 835 | // turn off auto-commit |
836 | 836 | db2_autocommit($this->mConn, DB2_AUTOCOMMIT_OFF); |
837 | | - $this->mTrxLevel = 1;
|
838 | | - }
|
839 | | -
|
840 | | - /**
|
| 837 | + $this->mTrxLevel = 1; |
| 838 | + } |
| 839 | + |
| 840 | + /** |
841 | 841 | * End a transaction |
842 | | - * Must have a preceding begin()
|
843 | | - */
|
844 | | - public function commit() {
|
| 842 | + * Must have a preceding begin() |
| 843 | + */ |
| 844 | + public function commit() { |
845 | 845 | db2_commit($this->mConn); |
846 | 846 | // turn auto-commit back on |
847 | 847 | db2_autocommit($this->mConn, DB2_AUTOCOMMIT_ON); |
848 | | - $this->mTrxLevel = 0;
|
849 | | - }
|
850 | | -
|
851 | | - /**
|
852 | | - * Cancel a transaction
|
853 | | - */
|
854 | | - public function rollback() {
|
| 848 | + $this->mTrxLevel = 0; |
| 849 | + } |
| 850 | + |
| 851 | + /** |
| 852 | + * Cancel a transaction |
| 853 | + */ |
| 854 | + public function rollback() { |
855 | 855 | db2_rollback($this->mConn); |
856 | 856 | // turn auto-commit back on |
857 | 857 | // not sure if this is appropriate |
858 | 858 | db2_autocommit($this->mConn, DB2_AUTOCOMMIT_ON); |
859 | | - $this->mTrxLevel = 0;
|
| 859 | + $this->mTrxLevel = 0; |
860 | 860 | } |
861 | 861 | |
862 | 862 | /** |
Property changes on: trunk/phase3/includes/db/DatabaseIbm_db2.php |
___________________________________________________________________ |
Name: svn:eol-style |
863 | 863 | + native |
Index: trunk/phase3/includes/api/ApiFormatJson_json.php |
— | — | @@ -45,14 +45,14 @@ |
46 | 46 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
47 | 47 | * DAMAGE. |
48 | 48 | * |
49 | | -* @ingroup API |
50 | | -* @author Michal Migurski <mike-json@teczno.com> |
51 | | -* @author Matt Knapp <mdknapp[at]gmail[dot]com> |
52 | | -* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com> |
53 | | -* @copyright 2005 Michal Migurski |
54 | | -* @version CVS: $Id$ |
55 | | -* @license http://www.opensource.org/licenses/bsd-license.php |
56 | | -* @see http://pear.php.net/pepr/pepr-proposal-show.php?id=198 |
| 49 | +* @ingroup API |
| 50 | +* @author Michal Migurski <mike-json@teczno.com> |
| 51 | +* @author Matt Knapp <mdknapp[at]gmail[dot]com> |
| 52 | +* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com> |
| 53 | +* @copyright 2005 Michal Migurski |
| 54 | +* @version CVS: $Id$ |
| 55 | +* @license http://www.opensource.org/licenses/bsd-license.php |
| 56 | +* @see http://pear.php.net/pepr/pepr-proposal-show.php?id=198 |
57 | 57 | */ |
58 | 58 | |
59 | 59 | /** |
— | — | @@ -115,715 +115,715 @@ |
116 | 116 | */ |
117 | 117 | class Services_JSON |
118 | 118 | { |
119 | | - /** |
120 | | - * constructs a new JSON instance |
121 | | - * |
122 | | - * @param int $use object behavior flags; combine with boolean-OR |
123 | | - * |
124 | | - * possible values: |
125 | | - * - SERVICES_JSON_LOOSE_TYPE: loose typing. |
126 | | - * "{...}" syntax creates associative arrays |
127 | | - * instead of objects in decode(). |
128 | | - * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. |
129 | | - * Values which can't be encoded (e.g. resources) |
130 | | - * appear as NULL instead of throwing errors. |
131 | | - * By default, a deeply-nested resource will |
132 | | - * bubble up with an error, so all return values |
133 | | - * from encode() should be checked with isError() |
134 | | - */ |
135 | | - function Services_JSON($use = 0) |
136 | | - { |
137 | | - $this->use = $use; |
138 | | - } |
| 119 | + /** |
| 120 | + * constructs a new JSON instance |
| 121 | + * |
| 122 | + * @param int $use object behavior flags; combine with boolean-OR |
| 123 | + * |
| 124 | + * possible values: |
| 125 | + * - SERVICES_JSON_LOOSE_TYPE: loose typing. |
| 126 | + * "{...}" syntax creates associative arrays |
| 127 | + * instead of objects in decode(). |
| 128 | + * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. |
| 129 | + * Values which can't be encoded (e.g. resources) |
| 130 | + * appear as NULL instead of throwing errors. |
| 131 | + * By default, a deeply-nested resource will |
| 132 | + * bubble up with an error, so all return values |
| 133 | + * from encode() should be checked with isError() |
| 134 | + */ |
| 135 | + function Services_JSON($use = 0) |
| 136 | + { |
| 137 | + $this->use = $use; |
| 138 | + } |
139 | 139 | |
140 | | - /** |
141 | | - * convert a string from one UTF-16 char to one UTF-8 char |
142 | | - * |
143 | | - * Normally should be handled by mb_convert_encoding, but |
144 | | - * provides a slower PHP-only method for installations |
145 | | - * that lack the multibye string extension. |
146 | | - * |
147 | | - * @param string $utf16 UTF-16 character |
148 | | - * @return string UTF-8 character |
149 | | - * @access private |
150 | | - */ |
151 | | - function utf162utf8($utf16) |
152 | | - { |
153 | | - // oh please oh please oh please oh please oh please |
154 | | - if(function_exists('mb_convert_encoding')) { |
155 | | - return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); |
156 | | - } |
| 140 | + /** |
| 141 | + * convert a string from one UTF-16 char to one UTF-8 char |
| 142 | + * |
| 143 | + * Normally should be handled by mb_convert_encoding, but |
| 144 | + * provides a slower PHP-only method for installations |
| 145 | + * that lack the multibye string extension. |
| 146 | + * |
| 147 | + * @param string $utf16 UTF-16 character |
| 148 | + * @return string UTF-8 character |
| 149 | + * @access private |
| 150 | + */ |
| 151 | + function utf162utf8($utf16) |
| 152 | + { |
| 153 | + // oh please oh please oh please oh please oh please |
| 154 | + if(function_exists('mb_convert_encoding')) { |
| 155 | + return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); |
| 156 | + } |
157 | 157 | |
158 | | - $bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); |
| 158 | + $bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); |
159 | 159 | |
160 | | - switch(true) { |
161 | | - case ((0x7F & $bytes) == $bytes): |
162 | | - // this case should never be reached, because we are in ASCII range |
163 | | - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
164 | | - return chr(0x7F & $bytes); |
| 160 | + switch(true) { |
| 161 | + case ((0x7F & $bytes) == $bytes): |
| 162 | + // this case should never be reached, because we are in ASCII range |
| 163 | + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 164 | + return chr(0x7F & $bytes); |
165 | 165 | |
166 | | - case (0x07FF & $bytes) == $bytes: |
167 | | - // return a 2-byte UTF-8 character |
168 | | - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
169 | | - return chr(0xC0 | (($bytes >> 6) & 0x1F)) |
170 | | - . chr(0x80 | ($bytes & 0x3F)); |
| 166 | + case (0x07FF & $bytes) == $bytes: |
| 167 | + // return a 2-byte UTF-8 character |
| 168 | + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 169 | + return chr(0xC0 | (($bytes >> 6) & 0x1F)) |
| 170 | + . chr(0x80 | ($bytes & 0x3F)); |
171 | 171 | |
172 | | - case (0xFC00 & $bytes) == 0xD800 && strlen($utf16) >= 4 && (0xFC & ord($utf16{2})) == 0xDC: |
173 | | - // return a 4-byte UTF-8 character |
174 | | - $char = ((($bytes & 0x03FF) << 10) |
175 | | - | ((ord($utf16{2}) & 0x03) << 8) |
176 | | - | ord($utf16{3})); |
177 | | - $char += 0x10000; |
178 | | - return chr(0xF0 | (($char >> 18) & 0x07)) |
179 | | - . chr(0x80 | (($char >> 12) & 0x3F)) |
180 | | - . chr(0x80 | (($char >> 6) & 0x3F)) |
181 | | - . chr(0x80 | ($char & 0x3F)); |
| 172 | + case (0xFC00 & $bytes) == 0xD800 && strlen($utf16) >= 4 && (0xFC & ord($utf16{2})) == 0xDC: |
| 173 | + // return a 4-byte UTF-8 character |
| 174 | + $char = ((($bytes & 0x03FF) << 10) |
| 175 | + | ((ord($utf16{2}) & 0x03) << 8) |
| 176 | + | ord($utf16{3})); |
| 177 | + $char += 0x10000; |
| 178 | + return chr(0xF0 | (($char >> 18) & 0x07)) |
| 179 | + . chr(0x80 | (($char >> 12) & 0x3F)) |
| 180 | + . chr(0x80 | (($char >> 6) & 0x3F)) |
| 181 | + . chr(0x80 | ($char & 0x3F)); |
182 | 182 | |
183 | | - case (0xFFFF & $bytes) == $bytes: |
184 | | - // return a 3-byte UTF-8 character |
185 | | - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
186 | | - return chr(0xE0 | (($bytes >> 12) & 0x0F)) |
187 | | - . chr(0x80 | (($bytes >> 6) & 0x3F)) |
188 | | - . chr(0x80 | ($bytes & 0x3F)); |
189 | | - } |
| 183 | + case (0xFFFF & $bytes) == $bytes: |
| 184 | + // return a 3-byte UTF-8 character |
| 185 | + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 186 | + return chr(0xE0 | (($bytes >> 12) & 0x0F)) |
| 187 | + . chr(0x80 | (($bytes >> 6) & 0x3F)) |
| 188 | + . chr(0x80 | ($bytes & 0x3F)); |
| 189 | + } |
190 | 190 | |
191 | | - // ignoring UTF-32 for now, sorry |
192 | | - return ''; |
193 | | - } |
| 191 | + // ignoring UTF-32 for now, sorry |
| 192 | + return ''; |
| 193 | + } |
194 | 194 | |
195 | | - /** |
196 | | - * convert a string from one UTF-8 char to one UTF-16 char |
197 | | - * |
198 | | - * Normally should be handled by mb_convert_encoding, but |
199 | | - * provides a slower PHP-only method for installations |
200 | | - * that lack the multibye string extension. |
201 | | - * |
202 | | - * @param string $utf8 UTF-8 character |
203 | | - * @return string UTF-16 character |
204 | | - * @access private |
205 | | - */ |
206 | | - function utf82utf16($utf8) |
207 | | - { |
208 | | - // oh please oh please oh please oh please oh please |
209 | | - if(function_exists('mb_convert_encoding')) { |
210 | | - return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); |
211 | | - } |
| 195 | + /** |
| 196 | + * convert a string from one UTF-8 char to one UTF-16 char |
| 197 | + * |
| 198 | + * Normally should be handled by mb_convert_encoding, but |
| 199 | + * provides a slower PHP-only method for installations |
| 200 | + * that lack the multibye string extension. |
| 201 | + * |
| 202 | + * @param string $utf8 UTF-8 character |
| 203 | + * @return string UTF-16 character |
| 204 | + * @access private |
| 205 | + */ |
| 206 | + function utf82utf16($utf8) |
| 207 | + { |
| 208 | + // oh please oh please oh please oh please oh please |
| 209 | + if(function_exists('mb_convert_encoding')) { |
| 210 | + return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); |
| 211 | + } |
212 | 212 | |
213 | | - switch(strlen($utf8)) { |
214 | | - case 1: |
215 | | - // this case should never be reached, because we are in ASCII range |
216 | | - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
217 | | - return $utf8; |
| 213 | + switch(strlen($utf8)) { |
| 214 | + case 1: |
| 215 | + // this case should never be reached, because we are in ASCII range |
| 216 | + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 217 | + return $utf8; |
218 | 218 | |
219 | | - case 2: |
220 | | - // return a UTF-16 character from a 2-byte UTF-8 char |
221 | | - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
222 | | - return chr(0x07 & (ord($utf8{0}) >> 2)) |
223 | | - . chr((0xC0 & (ord($utf8{0}) << 6)) |
224 | | - | (0x3F & ord($utf8{1}))); |
| 219 | + case 2: |
| 220 | + // return a UTF-16 character from a 2-byte UTF-8 char |
| 221 | + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 222 | + return chr(0x07 & (ord($utf8{0}) >> 2)) |
| 223 | + . chr((0xC0 & (ord($utf8{0}) << 6)) |
| 224 | + | (0x3F & ord($utf8{1}))); |
225 | 225 | |
226 | | - case 3: |
227 | | - // return a UTF-16 character from a 3-byte UTF-8 char |
228 | | - // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
229 | | - return chr((0xF0 & (ord($utf8{0}) << 4)) |
230 | | - | (0x0F & (ord($utf8{1}) >> 2))) |
231 | | - . chr((0xC0 & (ord($utf8{1}) << 6)) |
232 | | - | (0x7F & ord($utf8{2}))); |
| 226 | + case 3: |
| 227 | + // return a UTF-16 character from a 3-byte UTF-8 char |
| 228 | + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 229 | + return chr((0xF0 & (ord($utf8{0}) << 4)) |
| 230 | + | (0x0F & (ord($utf8{1}) >> 2))) |
| 231 | + . chr((0xC0 & (ord($utf8{1}) << 6)) |
| 232 | + | (0x7F & ord($utf8{2}))); |
233 | 233 | |
234 | | - case 4: |
235 | | - // return a UTF-16 surrogate pair from a 4-byte UTF-8 char |
236 | | - if(ord($utf8{0}) > 0xF4) return ''; # invalid |
237 | | - $char = ((0x1C0000 & (ord($utf8{0}) << 18)) |
238 | | - | (0x03F000 & (ord($utf8{1}) << 12)) |
239 | | - | (0x000FC0 & (ord($utf8{2}) << 6)) |
240 | | - | (0x00003F & ord($utf8{3}))); |
241 | | - if($char > 0x10FFFF) return ''; # invalid |
242 | | - $char -= 0x10000; |
243 | | - return chr(0xD8 | (($char >> 18) & 0x03)) |
244 | | - . chr(($char >> 10) & 0xFF) |
245 | | - . chr(0xDC | (($char >> 8) & 0x03)) |
246 | | - . chr($char & 0xFF); |
247 | | - } |
| 234 | + case 4: |
| 235 | + // return a UTF-16 surrogate pair from a 4-byte UTF-8 char |
| 236 | + if(ord($utf8{0}) > 0xF4) return ''; # invalid |
| 237 | + $char = ((0x1C0000 & (ord($utf8{0}) << 18)) |
| 238 | + | (0x03F000 & (ord($utf8{1}) << 12)) |
| 239 | + | (0x000FC0 & (ord($utf8{2}) << 6)) |
| 240 | + | (0x00003F & ord($utf8{3}))); |
| 241 | + if($char > 0x10FFFF) return ''; # invalid |
| 242 | + $char -= 0x10000; |
| 243 | + return chr(0xD8 | (($char >> 18) & 0x03)) |
| 244 | + . chr(($char >> 10) & 0xFF) |
| 245 | + . chr(0xDC | (($char >> 8) & 0x03)) |
| 246 | + . chr($char & 0xFF); |
| 247 | + } |
248 | 248 | |
249 | | - // ignoring UTF-32 for now, sorry |
250 | | - return ''; |
251 | | - } |
| 249 | + // ignoring UTF-32 for now, sorry |
| 250 | + return ''; |
| 251 | + } |
252 | 252 | |
253 | | - /** |
254 | | - * encodes an arbitrary variable into JSON format |
255 | | - * |
256 | | - * @param mixed $var any number, boolean, string, array, or object to be encoded. |
257 | | - * see argument 1 to Services_JSON() above for array-parsing behavior. |
258 | | - * if var is a strng, note that encode() always expects it |
259 | | - * to be in ASCII or UTF-8 format! |
260 | | - * @param bool $pretty pretty-print output with indents and newlines |
261 | | - * |
262 | | - * @return mixed JSON string representation of input var or an error if a problem occurs |
263 | | - * @access public |
264 | | - */ |
265 | | - function encode($var, $pretty=false) |
266 | | - { |
267 | | - $this->indent = 0; |
268 | | - $this->pretty = $pretty; |
269 | | - $this->nameValSeparator = $pretty ? ': ' : ':'; |
270 | | - return $this->encode2($var); |
271 | | - } |
| 253 | + /** |
| 254 | + * encodes an arbitrary variable into JSON format |
| 255 | + * |
| 256 | + * @param mixed $var any number, boolean, string, array, or object to be encoded. |
| 257 | + * see argument 1 to Services_JSON() above for array-parsing behavior. |
| 258 | + * if var is a strng, note that encode() always expects it |
| 259 | + * to be in ASCII or UTF-8 format! |
| 260 | + * @param bool $pretty pretty-print output with indents and newlines |
| 261 | + * |
| 262 | + * @return mixed JSON string representation of input var or an error if a problem occurs |
| 263 | + * @access public |
| 264 | + */ |
| 265 | + function encode($var, $pretty=false) |
| 266 | + { |
| 267 | + $this->indent = 0; |
| 268 | + $this->pretty = $pretty; |
| 269 | + $this->nameValSeparator = $pretty ? ': ' : ':'; |
| 270 | + return $this->encode2($var); |
| 271 | + } |
272 | 272 | |
273 | | - /** |
274 | | - * encodes an arbitrary variable into JSON format |
275 | | - * |
276 | | - * @param mixed $var any number, boolean, string, array, or object to be encoded. |
277 | | - * see argument 1 to Services_JSON() above for array-parsing behavior. |
278 | | - * if var is a strng, note that encode() always expects it |
279 | | - * to be in ASCII or UTF-8 format! |
280 | | - * |
281 | | - * @return mixed JSON string representation of input var or an error if a problem occurs |
282 | | - * @access private |
283 | | - */ |
284 | | - function encode2($var) |
285 | | - { |
286 | | - if ($this->pretty) { |
287 | | - $close = "\n" . str_repeat("\t", $this->indent); |
288 | | - $open = $close . "\t"; |
289 | | - $mid = ',' . $open; |
290 | | - } |
291 | | - else { |
292 | | - $open = $close = ''; |
293 | | - $mid = ','; |
294 | | - } |
| 273 | + /** |
| 274 | + * encodes an arbitrary variable into JSON format |
| 275 | + * |
| 276 | + * @param mixed $var any number, boolean, string, array, or object to be encoded. |
| 277 | + * see argument 1 to Services_JSON() above for array-parsing behavior. |
| 278 | + * if var is a strng, note that encode() always expects it |
| 279 | + * to be in ASCII or UTF-8 format! |
| 280 | + * |
| 281 | + * @return mixed JSON string representation of input var or an error if a problem occurs |
| 282 | + * @access private |
| 283 | + */ |
| 284 | + function encode2($var) |
| 285 | + { |
| 286 | + if ($this->pretty) { |
| 287 | + $close = "\n" . str_repeat("\t", $this->indent); |
| 288 | + $open = $close . "\t"; |
| 289 | + $mid = ',' . $open; |
| 290 | + } |
| 291 | + else { |
| 292 | + $open = $close = ''; |
| 293 | + $mid = ','; |
| 294 | + } |
295 | 295 | |
296 | | - switch (gettype($var)) { |
297 | | - case 'boolean': |
298 | | - return $var ? 'true' : 'false'; |
| 296 | + switch (gettype($var)) { |
| 297 | + case 'boolean': |
| 298 | + return $var ? 'true' : 'false'; |
299 | 299 | |
300 | | - case 'NULL': |
301 | | - return 'null'; |
| 300 | + case 'NULL': |
| 301 | + return 'null'; |
302 | 302 | |
303 | | - case 'integer': |
304 | | - return (int) $var; |
| 303 | + case 'integer': |
| 304 | + return (int) $var; |
305 | 305 | |
306 | | - case 'double': |
307 | | - case 'float': |
308 | | - return (float) $var; |
| 306 | + case 'double': |
| 307 | + case 'float': |
| 308 | + return (float) $var; |
309 | 309 | |
310 | | - case 'string': |
311 | | - // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT |
312 | | - $ascii = ''; |
313 | | - $strlen_var = strlen($var); |
| 310 | + case 'string': |
| 311 | + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT |
| 312 | + $ascii = ''; |
| 313 | + $strlen_var = strlen($var); |
314 | 314 | |
315 | | - /* |
316 | | - * Iterate over every character in the string, |
317 | | - * escaping with a slash or encoding to UTF-8 where necessary |
318 | | - */ |
319 | | - for ($c = 0; $c < $strlen_var; ++$c) { |
| 315 | + /* |
| 316 | + * Iterate over every character in the string, |
| 317 | + * escaping with a slash or encoding to UTF-8 where necessary |
| 318 | + */ |
| 319 | + for ($c = 0; $c < $strlen_var; ++$c) { |
320 | 320 | |
321 | | - $ord_var_c = ord($var{$c}); |
| 321 | + $ord_var_c = ord($var{$c}); |
322 | 322 | |
323 | | - switch (true) { |
324 | | - case $ord_var_c == 0x08: |
325 | | - $ascii .= '\b'; |
326 | | - break; |
327 | | - case $ord_var_c == 0x09: |
328 | | - $ascii .= '\t'; |
329 | | - break; |
330 | | - case $ord_var_c == 0x0A: |
331 | | - $ascii .= '\n'; |
332 | | - break; |
333 | | - case $ord_var_c == 0x0C: |
334 | | - $ascii .= '\f'; |
335 | | - break; |
336 | | - case $ord_var_c == 0x0D: |
337 | | - $ascii .= '\r'; |
338 | | - break; |
| 323 | + switch (true) { |
| 324 | + case $ord_var_c == 0x08: |
| 325 | + $ascii .= '\b'; |
| 326 | + break; |
| 327 | + case $ord_var_c == 0x09: |
| 328 | + $ascii .= '\t'; |
| 329 | + break; |
| 330 | + case $ord_var_c == 0x0A: |
| 331 | + $ascii .= '\n'; |
| 332 | + break; |
| 333 | + case $ord_var_c == 0x0C: |
| 334 | + $ascii .= '\f'; |
| 335 | + break; |
| 336 | + case $ord_var_c == 0x0D: |
| 337 | + $ascii .= '\r'; |
| 338 | + break; |
339 | 339 | |
340 | | - case $ord_var_c == 0x22: |
341 | | - case $ord_var_c == 0x2F: |
342 | | - case $ord_var_c == 0x5C: |
343 | | - // double quote, slash, slosh |
344 | | - $ascii .= '\\'.$var{$c}; |
345 | | - break; |
| 340 | + case $ord_var_c == 0x22: |
| 341 | + case $ord_var_c == 0x2F: |
| 342 | + case $ord_var_c == 0x5C: |
| 343 | + // double quote, slash, slosh |
| 344 | + $ascii .= '\\'.$var{$c}; |
| 345 | + break; |
346 | 346 | |
347 | | - case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): |
348 | | - // characters U-00000000 - U-0000007F (same as ASCII) |
349 | | - $ascii .= $var{$c}; |
350 | | - break; |
| 347 | + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): |
| 348 | + // characters U-00000000 - U-0000007F (same as ASCII) |
| 349 | + $ascii .= $var{$c}; |
| 350 | + break; |
351 | 351 | |
352 | | - case (($ord_var_c & 0xE0) == 0xC0): |
353 | | - // characters U-00000080 - U-000007FF, mask 110XXXXX |
354 | | - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
355 | | - $char = pack('C*', $ord_var_c, ord($var{$c + 1})); |
356 | | - $c += 1; |
357 | | - $utf16 = $this->utf82utf16($char); |
358 | | - $ascii .= sprintf('\u%04s', bin2hex($utf16)); |
359 | | - break; |
| 352 | + case (($ord_var_c & 0xE0) == 0xC0): |
| 353 | + // characters U-00000080 - U-000007FF, mask 110XXXXX |
| 354 | + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 355 | + $char = pack('C*', $ord_var_c, ord($var{$c + 1})); |
| 356 | + $c += 1; |
| 357 | + $utf16 = $this->utf82utf16($char); |
| 358 | + $ascii .= sprintf('\u%04s', bin2hex($utf16)); |
| 359 | + break; |
360 | 360 | |
361 | | - case (($ord_var_c & 0xF0) == 0xE0): |
362 | | - // characters U-00000800 - U-0000FFFF, mask 1110XXXX |
363 | | - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
364 | | - $char = pack('C*', $ord_var_c, |
365 | | - ord($var{$c + 1}), |
366 | | - ord($var{$c + 2})); |
367 | | - $c += 2; |
368 | | - $utf16 = $this->utf82utf16($char); |
369 | | - $ascii .= sprintf('\u%04s', bin2hex($utf16)); |
370 | | - break; |
| 361 | + case (($ord_var_c & 0xF0) == 0xE0): |
| 362 | + // characters U-00000800 - U-0000FFFF, mask 1110XXXX |
| 363 | + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 364 | + $char = pack('C*', $ord_var_c, |
| 365 | + ord($var{$c + 1}), |
| 366 | + ord($var{$c + 2})); |
| 367 | + $c += 2; |
| 368 | + $utf16 = $this->utf82utf16($char); |
| 369 | + $ascii .= sprintf('\u%04s', bin2hex($utf16)); |
| 370 | + break; |
371 | 371 | |
372 | | - case (($ord_var_c & 0xF8) == 0xF0): |
373 | | - // characters U-00010000 - U-001FFFFF, mask 11110XXX |
374 | | - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
375 | | - // These will always return a surrogate pair |
376 | | - $char = pack('C*', $ord_var_c, |
377 | | - ord($var{$c + 1}), |
378 | | - ord($var{$c + 2}), |
379 | | - ord($var{$c + 3})); |
380 | | - $c += 3; |
381 | | - $utf16 = $this->utf82utf16($char); |
382 | | - if($utf16 == '') { |
383 | | - $ascii .= '\ufffd'; |
384 | | - } else { |
385 | | - $utf16 = str_split($utf16, 2); |
386 | | - $ascii .= sprintf('\u%04s\u%04s', bin2hex($utf16[0]), bin2hex($utf16[1])); |
387 | | - } |
388 | | - break; |
389 | | - } |
390 | | - } |
| 372 | + case (($ord_var_c & 0xF8) == 0xF0): |
| 373 | + // characters U-00010000 - U-001FFFFF, mask 11110XXX |
| 374 | + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 375 | + // These will always return a surrogate pair |
| 376 | + $char = pack('C*', $ord_var_c, |
| 377 | + ord($var{$c + 1}), |
| 378 | + ord($var{$c + 2}), |
| 379 | + ord($var{$c + 3})); |
| 380 | + $c += 3; |
| 381 | + $utf16 = $this->utf82utf16($char); |
| 382 | + if($utf16 == '') { |
| 383 | + $ascii .= '\ufffd'; |
| 384 | + } else { |
| 385 | + $utf16 = str_split($utf16, 2); |
| 386 | + $ascii .= sprintf('\u%04s\u%04s', bin2hex($utf16[0]), bin2hex($utf16[1])); |
| 387 | + } |
| 388 | + break; |
| 389 | + } |
| 390 | + } |
391 | 391 | |
392 | | - return '"'.$ascii.'"'; |
| 392 | + return '"'.$ascii.'"'; |
393 | 393 | |
394 | | - case 'array': |
395 | | - /* |
396 | | - * As per JSON spec if any array key is not an integer |
397 | | - * we must treat the the whole array as an object. We |
398 | | - * also try to catch a sparsely populated associative |
399 | | - * array with numeric keys here because some JS engines |
400 | | - * will create an array with empty indexes up to |
401 | | - * max_index which can cause memory issues and because |
402 | | - * the keys, which may be relevant, will be remapped |
403 | | - * otherwise. |
404 | | - * |
405 | | - * As per the ECMA and JSON specification an object may |
406 | | - * have any string as a property. Unfortunately due to |
407 | | - * a hole in the ECMA specification if the key is a |
408 | | - * ECMA reserved word or starts with a digit the |
409 | | - * parameter is only accessible using ECMAScript's |
410 | | - * bracket notation. |
411 | | - */ |
| 394 | + case 'array': |
| 395 | + /* |
| 396 | + * As per JSON spec if any array key is not an integer |
| 397 | + * we must treat the the whole array as an object. We |
| 398 | + * also try to catch a sparsely populated associative |
| 399 | + * array with numeric keys here because some JS engines |
| 400 | + * will create an array with empty indexes up to |
| 401 | + * max_index which can cause memory issues and because |
| 402 | + * the keys, which may be relevant, will be remapped |
| 403 | + * otherwise. |
| 404 | + * |
| 405 | + * As per the ECMA and JSON specification an object may |
| 406 | + * have any string as a property. Unfortunately due to |
| 407 | + * a hole in the ECMA specification if the key is a |
| 408 | + * ECMA reserved word or starts with a digit the |
| 409 | + * parameter is only accessible using ECMAScript's |
| 410 | + * bracket notation. |
| 411 | + */ |
412 | 412 | |
413 | | - // treat as a JSON object |
414 | | - if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { |
415 | | - $this->indent++; |
416 | | - $properties = array_map(array($this, 'name_value'), |
417 | | - array_keys($var), |
418 | | - array_values($var)); |
419 | | - $this->indent--; |
| 413 | + // treat as a JSON object |
| 414 | + if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { |
| 415 | + $this->indent++; |
| 416 | + $properties = array_map(array($this, 'name_value'), |
| 417 | + array_keys($var), |
| 418 | + array_values($var)); |
| 419 | + $this->indent--; |
420 | 420 | |
421 | | - foreach($properties as $property) { |
422 | | - if(Services_JSON::isError($property)) { |
423 | | - return $property; |
424 | | - } |
425 | | - } |
| 421 | + foreach($properties as $property) { |
| 422 | + if(Services_JSON::isError($property)) { |
| 423 | + return $property; |
| 424 | + } |
| 425 | + } |
426 | 426 | |
427 | | - return '{' . $open . join($mid, $properties) . $close . '}'; |
428 | | - } |
| 427 | + return '{' . $open . join($mid, $properties) . $close . '}'; |
| 428 | + } |
429 | 429 | |
430 | | - // treat it like a regular array |
431 | | - $this->indent++; |
432 | | - $elements = array_map(array($this, 'encode2'), $var); |
433 | | - $this->indent--; |
| 430 | + // treat it like a regular array |
| 431 | + $this->indent++; |
| 432 | + $elements = array_map(array($this, 'encode2'), $var); |
| 433 | + $this->indent--; |
434 | 434 | |
435 | | - foreach($elements as $element) { |
436 | | - if(Services_JSON::isError($element)) { |
437 | | - return $element; |
438 | | - } |
439 | | - } |
| 435 | + foreach($elements as $element) { |
| 436 | + if(Services_JSON::isError($element)) { |
| 437 | + return $element; |
| 438 | + } |
| 439 | + } |
440 | 440 | |
441 | | - return '[' . $open . join($mid, $elements) . $close . ']'; |
| 441 | + return '[' . $open . join($mid, $elements) . $close . ']'; |
442 | 442 | |
443 | | - case 'object': |
444 | | - $vars = get_object_vars($var); |
| 443 | + case 'object': |
| 444 | + $vars = get_object_vars($var); |
445 | 445 | |
446 | | - $this->indent++; |
447 | | - $properties = array_map(array($this, 'name_value'), |
448 | | - array_keys($vars), |
449 | | - array_values($vars)); |
450 | | - $this->indent--; |
| 446 | + $this->indent++; |
| 447 | + $properties = array_map(array($this, 'name_value'), |
| 448 | + array_keys($vars), |
| 449 | + array_values($vars)); |
| 450 | + $this->indent--; |
451 | 451 | |
452 | | - foreach($properties as $property) { |
453 | | - if(Services_JSON::isError($property)) { |
454 | | - return $property; |
455 | | - } |
456 | | - } |
| 452 | + foreach($properties as $property) { |
| 453 | + if(Services_JSON::isError($property)) { |
| 454 | + return $property; |
| 455 | + } |
| 456 | + } |
457 | 457 | |
458 | | - return '{' . $open . join($mid, $properties) . $close . '}'; |
| 458 | + return '{' . $open . join($mid, $properties) . $close . '}'; |
459 | 459 | |
460 | | - default: |
461 | | - return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) |
462 | | - ? 'null' |
463 | | - : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); |
464 | | - } |
465 | | - } |
| 460 | + default: |
| 461 | + return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) |
| 462 | + ? 'null' |
| 463 | + : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); |
| 464 | + } |
| 465 | + } |
466 | 466 | |
467 | | - /** |
468 | | - * array-walking function for use in generating JSON-formatted name-value pairs |
469 | | - * |
470 | | - * @param string $name name of key to use |
471 | | - * @param mixed $value reference to an array element to be encoded |
472 | | - * |
473 | | - * @return string JSON-formatted name-value pair, like '"name":value' |
474 | | - * @access private |
475 | | - */ |
476 | | - function name_value($name, $value) |
477 | | - { |
478 | | - $encoded_value = $this->encode2($value); |
| 467 | + /** |
| 468 | + * array-walking function for use in generating JSON-formatted name-value pairs |
| 469 | + * |
| 470 | + * @param string $name name of key to use |
| 471 | + * @param mixed $value reference to an array element to be encoded |
| 472 | + * |
| 473 | + * @return string JSON-formatted name-value pair, like '"name":value' |
| 474 | + * @access private |
| 475 | + */ |
| 476 | + function name_value($name, $value) |
| 477 | + { |
| 478 | + $encoded_value = $this->encode2($value); |
479 | 479 | |
480 | | - if(Services_JSON::isError($encoded_value)) { |
481 | | - return $encoded_value; |
482 | | - } |
| 480 | + if(Services_JSON::isError($encoded_value)) { |
| 481 | + return $encoded_value; |
| 482 | + } |
483 | 483 | |
484 | | - return $this->encode2(strval($name)) . $this->nameValSeparator . $encoded_value; |
485 | | - } |
| 484 | + return $this->encode2(strval($name)) . $this->nameValSeparator . $encoded_value; |
| 485 | + } |
486 | 486 | |
487 | | - /** |
488 | | - * reduce a string by removing leading and trailing comments and whitespace |
489 | | - * |
490 | | - * @param $str string string value to strip of comments and whitespace |
491 | | - * |
492 | | - * @return string string value stripped of comments and whitespace |
493 | | - * @access private |
494 | | - */ |
495 | | - function reduce_string($str) |
496 | | - { |
497 | | - $str = preg_replace(array( |
| 487 | + /** |
| 488 | + * reduce a string by removing leading and trailing comments and whitespace |
| 489 | + * |
| 490 | + * @param $str string string value to strip of comments and whitespace |
| 491 | + * |
| 492 | + * @return string string value stripped of comments and whitespace |
| 493 | + * @access private |
| 494 | + */ |
| 495 | + function reduce_string($str) |
| 496 | + { |
| 497 | + $str = preg_replace(array( |
498 | 498 | |
499 | | - // eliminate single line comments in '// ...' form |
500 | | - '#^\s*//(.+)$#m', |
| 499 | + // eliminate single line comments in '// ...' form |
| 500 | + '#^\s*//(.+)$#m', |
501 | 501 | |
502 | | - // eliminate multi-line comments in '/* ... */' form, at start of string |
503 | | - '#^\s*/\*(.+)\*/#Us', |
| 502 | + // eliminate multi-line comments in '/* ... */' form, at start of string |
| 503 | + '#^\s*/\*(.+)\*/#Us', |
504 | 504 | |
505 | | - // eliminate multi-line comments in '/* ... */' form, at end of string |
506 | | - '#/\*(.+)\*/\s*$#Us' |
| 505 | + // eliminate multi-line comments in '/* ... */' form, at end of string |
| 506 | + '#/\*(.+)\*/\s*$#Us' |
507 | 507 | |
508 | | - ), '', $str); |
| 508 | + ), '', $str); |
509 | 509 | |
510 | | - // eliminate extraneous space |
511 | | - return trim($str); |
512 | | - } |
| 510 | + // eliminate extraneous space |
| 511 | + return trim($str); |
| 512 | + } |
513 | 513 | |
514 | | - /** |
515 | | - * decodes a JSON string into appropriate variable |
516 | | - * |
517 | | - * @param string $str JSON-formatted string |
518 | | - * |
519 | | - * @return mixed number, boolean, string, array, or object |
520 | | - * corresponding to given JSON input string. |
521 | | - * See argument 1 to Services_JSON() above for object-output behavior. |
522 | | - * Note that decode() always returns strings |
523 | | - * in ASCII or UTF-8 format! |
524 | | - * @access public |
525 | | - */ |
526 | | - function decode($str) |
527 | | - { |
528 | | - $str = $this->reduce_string($str); |
| 514 | + /** |
| 515 | + * decodes a JSON string into appropriate variable |
| 516 | + * |
| 517 | + * @param string $str JSON-formatted string |
| 518 | + * |
| 519 | + * @return mixed number, boolean, string, array, or object |
| 520 | + * corresponding to given JSON input string. |
| 521 | + * See argument 1 to Services_JSON() above for object-output behavior. |
| 522 | + * Note that decode() always returns strings |
| 523 | + * in ASCII or UTF-8 format! |
| 524 | + * @access public |
| 525 | + */ |
| 526 | + function decode($str) |
| 527 | + { |
| 528 | + $str = $this->reduce_string($str); |
529 | 529 | |
530 | | - switch (strtolower($str)) { |
531 | | - case 'true': |
532 | | - return true; |
| 530 | + switch (strtolower($str)) { |
| 531 | + case 'true': |
| 532 | + return true; |
533 | 533 | |
534 | | - case 'false': |
535 | | - return false; |
| 534 | + case 'false': |
| 535 | + return false; |
536 | 536 | |
537 | | - case 'null': |
538 | | - return null; |
| 537 | + case 'null': |
| 538 | + return null; |
539 | 539 | |
540 | | - default: |
541 | | - $m = array(); |
| 540 | + default: |
| 541 | + $m = array(); |
542 | 542 | |
543 | | - if (is_numeric($str)) { |
544 | | - // Lookie-loo, it's a number |
| 543 | + if (is_numeric($str)) { |
| 544 | + // Lookie-loo, it's a number |
545 | 545 | |
546 | | - // This would work on its own, but I'm trying to be |
547 | | - // good about returning integers where appropriate: |
548 | | - // return (float)$str; |
| 546 | + // This would work on its own, but I'm trying to be |
| 547 | + // good about returning integers where appropriate: |
| 548 | + // return (float)$str; |
549 | 549 | |
550 | | - // Return float or int, as appropriate |
551 | | - return ((float)$str == (integer)$str) |
552 | | - ? (integer)$str |
553 | | - : (float)$str; |
| 550 | + // Return float or int, as appropriate |
| 551 | + return ((float)$str == (integer)$str) |
| 552 | + ? (integer)$str |
| 553 | + : (float)$str; |
554 | 554 | |
555 | | - } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { |
556 | | - // STRINGS RETURNED IN UTF-8 FORMAT |
557 | | - $delim = substr($str, 0, 1); |
558 | | - $chrs = substr($str, 1, -1); |
559 | | - $utf8 = ''; |
560 | | - $strlen_chrs = strlen($chrs); |
| 555 | + } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { |
| 556 | + // STRINGS RETURNED IN UTF-8 FORMAT |
| 557 | + $delim = substr($str, 0, 1); |
| 558 | + $chrs = substr($str, 1, -1); |
| 559 | + $utf8 = ''; |
| 560 | + $strlen_chrs = strlen($chrs); |
561 | 561 | |
562 | | - for ($c = 0; $c < $strlen_chrs; ++$c) { |
| 562 | + for ($c = 0; $c < $strlen_chrs; ++$c) { |
563 | 563 | |
564 | | - $substr_chrs_c_2 = substr($chrs, $c, 2); |
565 | | - $ord_chrs_c = ord($chrs{$c}); |
| 564 | + $substr_chrs_c_2 = substr($chrs, $c, 2); |
| 565 | + $ord_chrs_c = ord($chrs{$c}); |
566 | 566 | |
567 | | - switch (true) { |
568 | | - case $substr_chrs_c_2 == '\b': |
569 | | - $utf8 .= chr(0x08); |
570 | | - ++$c; |
571 | | - break; |
572 | | - case $substr_chrs_c_2 == '\t': |
573 | | - $utf8 .= chr(0x09); |
574 | | - ++$c; |
575 | | - break; |
576 | | - case $substr_chrs_c_2 == '\n': |
577 | | - $utf8 .= chr(0x0A); |
578 | | - ++$c; |
579 | | - break; |
580 | | - case $substr_chrs_c_2 == '\f': |
581 | | - $utf8 .= chr(0x0C); |
582 | | - ++$c; |
583 | | - break; |
584 | | - case $substr_chrs_c_2 == '\r': |
585 | | - $utf8 .= chr(0x0D); |
586 | | - ++$c; |
587 | | - break; |
| 567 | + switch (true) { |
| 568 | + case $substr_chrs_c_2 == '\b': |
| 569 | + $utf8 .= chr(0x08); |
| 570 | + ++$c; |
| 571 | + break; |
| 572 | + case $substr_chrs_c_2 == '\t': |
| 573 | + $utf8 .= chr(0x09); |
| 574 | + ++$c; |
| 575 | + break; |
| 576 | + case $substr_chrs_c_2 == '\n': |
| 577 | + $utf8 .= chr(0x0A); |
| 578 | + ++$c; |
| 579 | + break; |
| 580 | + case $substr_chrs_c_2 == '\f': |
| 581 | + $utf8 .= chr(0x0C); |
| 582 | + ++$c; |
| 583 | + break; |
| 584 | + case $substr_chrs_c_2 == '\r': |
| 585 | + $utf8 .= chr(0x0D); |
| 586 | + ++$c; |
| 587 | + break; |
588 | 588 | |
589 | | - case $substr_chrs_c_2 == '\\"': |
590 | | - case $substr_chrs_c_2 == '\\\'': |
591 | | - case $substr_chrs_c_2 == '\\\\': |
592 | | - case $substr_chrs_c_2 == '\\/': |
593 | | - if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || |
594 | | - ($delim == "'" && $substr_chrs_c_2 != '\\"')) { |
595 | | - $utf8 .= $chrs{++$c}; |
596 | | - } |
597 | | - break; |
| 589 | + case $substr_chrs_c_2 == '\\"': |
| 590 | + case $substr_chrs_c_2 == '\\\'': |
| 591 | + case $substr_chrs_c_2 == '\\\\': |
| 592 | + case $substr_chrs_c_2 == '\\/': |
| 593 | + if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || |
| 594 | + ($delim == "'" && $substr_chrs_c_2 != '\\"')) { |
| 595 | + $utf8 .= $chrs{++$c}; |
| 596 | + } |
| 597 | + break; |
598 | 598 | |
599 | | - case preg_match('/\\\uD[89AB][0-9A-F]{2}\\\uD[C-F][0-9A-F]{2}/i', substr($chrs, $c, 12)): |
600 | | - // escaped unicode surrogate pair |
601 | | - $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) |
602 | | - . chr(hexdec(substr($chrs, ($c + 4), 2))) |
603 | | - . chr(hexdec(substr($chrs, ($c + 8), 2))) |
604 | | - . chr(hexdec(substr($chrs, ($c + 10), 2))); |
605 | | - $utf8 .= $this->utf162utf8($utf16); |
606 | | - $c += 11; |
607 | | - break; |
| 599 | + case preg_match('/\\\uD[89AB][0-9A-F]{2}\\\uD[C-F][0-9A-F]{2}/i', substr($chrs, $c, 12)): |
| 600 | + // escaped unicode surrogate pair |
| 601 | + $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) |
| 602 | + . chr(hexdec(substr($chrs, ($c + 4), 2))) |
| 603 | + . chr(hexdec(substr($chrs, ($c + 8), 2))) |
| 604 | + . chr(hexdec(substr($chrs, ($c + 10), 2))); |
| 605 | + $utf8 .= $this->utf162utf8($utf16); |
| 606 | + $c += 11; |
| 607 | + break; |
608 | 608 | |
609 | | - case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): |
610 | | - // single, escaped unicode character |
611 | | - $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) |
612 | | - . chr(hexdec(substr($chrs, ($c + 4), 2))); |
613 | | - $utf8 .= $this->utf162utf8($utf16); |
614 | | - $c += 5; |
615 | | - break; |
| 609 | + case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): |
| 610 | + // single, escaped unicode character |
| 611 | + $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) |
| 612 | + . chr(hexdec(substr($chrs, ($c + 4), 2))); |
| 613 | + $utf8 .= $this->utf162utf8($utf16); |
| 614 | + $c += 5; |
| 615 | + break; |
616 | 616 | |
617 | | - case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): |
618 | | - $utf8 .= $chrs{$c}; |
619 | | - break; |
| 617 | + case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): |
| 618 | + $utf8 .= $chrs{$c}; |
| 619 | + break; |
620 | 620 | |
621 | | - case ($ord_chrs_c & 0xE0) == 0xC0: |
622 | | - // characters U-00000080 - U-000007FF, mask 110XXXXX |
623 | | - //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
624 | | - $utf8 .= substr($chrs, $c, 2); |
625 | | - ++$c; |
626 | | - break; |
| 621 | + case ($ord_chrs_c & 0xE0) == 0xC0: |
| 622 | + // characters U-00000080 - U-000007FF, mask 110XXXXX |
| 623 | + //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 624 | + $utf8 .= substr($chrs, $c, 2); |
| 625 | + ++$c; |
| 626 | + break; |
627 | 627 | |
628 | | - case ($ord_chrs_c & 0xF0) == 0xE0: |
629 | | - // characters U-00000800 - U-0000FFFF, mask 1110XXXX |
630 | | - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
631 | | - $utf8 .= substr($chrs, $c, 3); |
632 | | - $c += 2; |
633 | | - break; |
| 628 | + case ($ord_chrs_c & 0xF0) == 0xE0: |
| 629 | + // characters U-00000800 - U-0000FFFF, mask 1110XXXX |
| 630 | + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 631 | + $utf8 .= substr($chrs, $c, 3); |
| 632 | + $c += 2; |
| 633 | + break; |
634 | 634 | |
635 | | - case ($ord_chrs_c & 0xF8) == 0xF0: |
636 | | - // characters U-00010000 - U-001FFFFF, mask 11110XXX |
637 | | - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
638 | | - $utf8 .= substr($chrs, $c, 4); |
639 | | - $c += 3; |
640 | | - break; |
| 635 | + case ($ord_chrs_c & 0xF8) == 0xF0: |
| 636 | + // characters U-00010000 - U-001FFFFF, mask 11110XXX |
| 637 | + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 638 | + $utf8 .= substr($chrs, $c, 4); |
| 639 | + $c += 3; |
| 640 | + break; |
641 | 641 | |
642 | | - case ($ord_chrs_c & 0xFC) == 0xF8: |
643 | | - // characters U-00200000 - U-03FFFFFF, mask 111110XX |
644 | | - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
645 | | - $utf8 .= substr($chrs, $c, 5); |
646 | | - $c += 4; |
647 | | - break; |
| 642 | + case ($ord_chrs_c & 0xFC) == 0xF8: |
| 643 | + // characters U-00200000 - U-03FFFFFF, mask 111110XX |
| 644 | + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 645 | + $utf8 .= substr($chrs, $c, 5); |
| 646 | + $c += 4; |
| 647 | + break; |
648 | 648 | |
649 | | - case ($ord_chrs_c & 0xFE) == 0xFC: |
650 | | - // characters U-04000000 - U-7FFFFFFF, mask 1111110X |
651 | | - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
652 | | - $utf8 .= substr($chrs, $c, 6); |
653 | | - $c += 5; |
654 | | - break; |
| 649 | + case ($ord_chrs_c & 0xFE) == 0xFC: |
| 650 | + // characters U-04000000 - U-7FFFFFFF, mask 1111110X |
| 651 | + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
| 652 | + $utf8 .= substr($chrs, $c, 6); |
| 653 | + $c += 5; |
| 654 | + break; |
655 | 655 | |
656 | | - } |
| 656 | + } |
657 | 657 | |
658 | | - } |
| 658 | + } |
659 | 659 | |
660 | | - return $utf8; |
| 660 | + return $utf8; |
661 | 661 | |
662 | | - } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { |
663 | | - // array, or object notation |
| 662 | + } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { |
| 663 | + // array, or object notation |
664 | 664 | |
665 | | - if ($str{0} == '[') { |
666 | | - $stk = array(SERVICES_JSON_IN_ARR); |
667 | | - $arr = array(); |
668 | | - } else { |
669 | | - if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
670 | | - $stk = array(SERVICES_JSON_IN_OBJ); |
671 | | - $obj = array(); |
672 | | - } else { |
673 | | - $stk = array(SERVICES_JSON_IN_OBJ); |
674 | | - $obj = new stdClass(); |
675 | | - } |
676 | | - } |
| 665 | + if ($str{0} == '[') { |
| 666 | + $stk = array(SERVICES_JSON_IN_ARR); |
| 667 | + $arr = array(); |
| 668 | + } else { |
| 669 | + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
| 670 | + $stk = array(SERVICES_JSON_IN_OBJ); |
| 671 | + $obj = array(); |
| 672 | + } else { |
| 673 | + $stk = array(SERVICES_JSON_IN_OBJ); |
| 674 | + $obj = new stdClass(); |
| 675 | + } |
| 676 | + } |
677 | 677 | |
678 | | - array_push($stk, array('what' => SERVICES_JSON_SLICE, |
679 | | - 'where' => 0, |
680 | | - 'delim' => false)); |
| 678 | + array_push($stk, array( 'what' => SERVICES_JSON_SLICE, |
| 679 | + 'where' => 0, |
| 680 | + 'delim' => false)); |
681 | 681 | |
682 | | - $chrs = substr($str, 1, -1); |
683 | | - $chrs = $this->reduce_string($chrs); |
| 682 | + $chrs = substr($str, 1, -1); |
| 683 | + $chrs = $this->reduce_string($chrs); |
684 | 684 | |
685 | | - if ($chrs == '') { |
686 | | - if (reset($stk) == SERVICES_JSON_IN_ARR) { |
687 | | - return $arr; |
| 685 | + if ($chrs == '') { |
| 686 | + if (reset($stk) == SERVICES_JSON_IN_ARR) { |
| 687 | + return $arr; |
688 | 688 | |
689 | | - } else { |
690 | | - return $obj; |
| 689 | + } else { |
| 690 | + return $obj; |
691 | 691 | |
692 | | - } |
693 | | - } |
| 692 | + } |
| 693 | + } |
694 | 694 | |
695 | | - //print("\nparsing {$chrs}\n"); |
| 695 | + //print("\nparsing {$chrs}\n"); |
696 | 696 | |
697 | | - $strlen_chrs = strlen($chrs); |
| 697 | + $strlen_chrs = strlen($chrs); |
698 | 698 | |
699 | | - for ($c = 0; $c <= $strlen_chrs; ++$c) { |
| 699 | + for ($c = 0; $c <= $strlen_chrs; ++$c) { |
700 | 700 | |
701 | | - $top = end($stk); |
702 | | - $substr_chrs_c_2 = substr($chrs, $c, 2); |
| 701 | + $top = end($stk); |
| 702 | + $substr_chrs_c_2 = substr($chrs, $c, 2); |
703 | 703 | |
704 | | - if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { |
705 | | - // found a comma that is not inside a string, array, etc., |
706 | | - // OR we've reached the end of the character list |
707 | | - $slice = substr($chrs, $top['where'], ($c - $top['where'])); |
708 | | - array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); |
709 | | - //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
| 704 | + if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { |
| 705 | + // found a comma that is not inside a string, array, etc., |
| 706 | + // OR we've reached the end of the character list |
| 707 | + $slice = substr($chrs, $top['where'], ($c - $top['where'])); |
| 708 | + array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); |
| 709 | + //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
710 | 710 | |
711 | | - if (reset($stk) == SERVICES_JSON_IN_ARR) { |
712 | | - // we are in an array, so just push an element onto the stack |
713 | | - array_push($arr, $this->decode($slice)); |
| 711 | + if (reset($stk) == SERVICES_JSON_IN_ARR) { |
| 712 | + // we are in an array, so just push an element onto the stack |
| 713 | + array_push($arr, $this->decode($slice)); |
714 | 714 | |
715 | | - } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |
716 | | - // we are in an object, so figure |
717 | | - // out the property name and set an |
718 | | - // element in an associative array, |
719 | | - // for now |
720 | | - $parts = array(); |
| 715 | + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |
| 716 | + // we are in an object, so figure |
| 717 | + // out the property name and set an |
| 718 | + // element in an associative array, |
| 719 | + // for now |
| 720 | + $parts = array(); |
721 | 721 | |
722 | | - if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |
723 | | - // "name":value pair |
724 | | - $key = $this->decode($parts[1]); |
725 | | - $val = $this->decode($parts[2]); |
| 722 | + if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |
| 723 | + // "name":value pair |
| 724 | + $key = $this->decode($parts[1]); |
| 725 | + $val = $this->decode($parts[2]); |
726 | 726 | |
727 | | - if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
728 | | - $obj[$key] = $val; |
729 | | - } else { |
730 | | - $obj->$key = $val; |
731 | | - } |
732 | | - } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |
733 | | - // name:value pair, where name is unquoted |
734 | | - $key = $parts[1]; |
735 | | - $val = $this->decode($parts[2]); |
| 727 | + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
| 728 | + $obj[$key] = $val; |
| 729 | + } else { |
| 730 | + $obj->$key = $val; |
| 731 | + } |
| 732 | + } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |
| 733 | + // name:value pair, where name is unquoted |
| 734 | + $key = $parts[1]; |
| 735 | + $val = $this->decode($parts[2]); |
736 | 736 | |
737 | | - if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
738 | | - $obj[$key] = $val; |
739 | | - } else { |
740 | | - $obj->$key = $val; |
741 | | - } |
742 | | - } |
| 737 | + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
| 738 | + $obj[$key] = $val; |
| 739 | + } else { |
| 740 | + $obj->$key = $val; |
| 741 | + } |
| 742 | + } |
743 | 743 | |
744 | | - } |
| 744 | + } |
745 | 745 | |
746 | | - } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { |
747 | | - // found a quote, and we are not inside a string |
748 | | - array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); |
749 | | - //print("Found start of string at {$c}\n"); |
| 746 | + } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { |
| 747 | + // found a quote, and we are not inside a string |
| 748 | + array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); |
| 749 | + //print("Found start of string at {$c}\n"); |
750 | 750 | |
751 | | - } elseif (($chrs{$c} == $top['delim']) && |
752 | | - ($top['what'] == SERVICES_JSON_IN_STR) && |
753 | | - (($chrs{$c - 1} != '\\') || |
754 | | - ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) { |
755 | | - // found a quote, we're in a string, and it's not escaped |
756 | | - array_pop($stk); |
757 | | - //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); |
| 751 | + } elseif (($chrs{$c} == $top['delim']) && |
| 752 | + ($top['what'] == SERVICES_JSON_IN_STR) && |
| 753 | + (($chrs{$c - 1} != '\\') || |
| 754 | + ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) { |
| 755 | + // found a quote, we're in a string, and it's not escaped |
| 756 | + array_pop($stk); |
| 757 | + //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); |
758 | 758 | |
759 | | - } elseif (($chrs{$c} == '[') && |
760 | | - in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
761 | | - // found a left-bracket, and we are in an array, object, or slice |
762 | | - array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); |
763 | | - //print("Found start of array at {$c}\n"); |
| 759 | + } elseif (($chrs{$c} == '[') && |
| 760 | + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
| 761 | + // found a left-bracket, and we are in an array, object, or slice |
| 762 | + array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); |
| 763 | + //print("Found start of array at {$c}\n"); |
764 | 764 | |
765 | | - } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { |
766 | | - // found a right-bracket, and we're in an array |
767 | | - array_pop($stk); |
768 | | - //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
| 765 | + } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { |
| 766 | + // found a right-bracket, and we're in an array |
| 767 | + array_pop($stk); |
| 768 | + //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
769 | 769 | |
770 | | - } elseif (($chrs{$c} == '{') && |
771 | | - in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
772 | | - // found a left-brace, and we are in an array, object, or slice |
773 | | - array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); |
774 | | - //print("Found start of object at {$c}\n"); |
| 770 | + } elseif (($chrs{$c} == '{') && |
| 771 | + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
| 772 | + // found a left-brace, and we are in an array, object, or slice |
| 773 | + array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); |
| 774 | + //print("Found start of object at {$c}\n"); |
775 | 775 | |
776 | | - } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { |
777 | | - // found a right-brace, and we're in an object |
778 | | - array_pop($stk); |
779 | | - //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
| 776 | + } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { |
| 777 | + // found a right-brace, and we're in an object |
| 778 | + array_pop($stk); |
| 779 | + //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
780 | 780 | |
781 | | - } elseif (($substr_chrs_c_2 == '/*') && |
782 | | - in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
783 | | - // found a comment start, and we are in an array, object, or slice |
784 | | - array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); |
785 | | - $c++; |
786 | | - //print("Found start of comment at {$c}\n"); |
| 781 | + } elseif (($substr_chrs_c_2 == '/*') && |
| 782 | + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
| 783 | + // found a comment start, and we are in an array, object, or slice |
| 784 | + array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); |
| 785 | + $c++; |
| 786 | + //print("Found start of comment at {$c}\n"); |
787 | 787 | |
788 | | - } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { |
789 | | - // found a comment end, and we're in one now |
790 | | - array_pop($stk); |
791 | | - $c++; |
| 788 | + } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { |
| 789 | + // found a comment end, and we're in one now |
| 790 | + array_pop($stk); |
| 791 | + $c++; |
792 | 792 | |
793 | | - for ($i = $top['where']; $i <= $c; ++$i) |
794 | | - $chrs = substr_replace($chrs, ' ', $i, 1); |
| 793 | + for ($i = $top['where']; $i <= $c; ++$i) |
| 794 | + $chrs = substr_replace($chrs, ' ', $i, 1); |
795 | 795 | |
796 | | - //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
| 796 | + //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
797 | 797 | |
798 | | - } |
| 798 | + } |
799 | 799 | |
800 | | - } |
| 800 | + } |
801 | 801 | |
802 | | - if (reset($stk) == SERVICES_JSON_IN_ARR) { |
803 | | - return $arr; |
| 802 | + if (reset($stk) == SERVICES_JSON_IN_ARR) { |
| 803 | + return $arr; |
804 | 804 | |
805 | | - } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |
806 | | - return $obj; |
| 805 | + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |
| 806 | + return $obj; |
807 | 807 | |
808 | | - } |
| 808 | + } |
809 | 809 | |
810 | | - } |
811 | | - } |
812 | | - } |
| 810 | + } |
| 811 | + } |
| 812 | + } |
813 | 813 | |
814 | | - /** |
815 | | - * @todo Ultimately, this should just call PEAR::isError() |
816 | | - */ |
817 | | - function isError($data, $code = null) |
818 | | - { |
819 | | - if (class_exists('pear')) { |
820 | | - return PEAR::isError($data, $code); |
821 | | - } elseif (is_object($data) && (get_class($data) == 'services_json_error' || |
822 | | - is_subclass_of($data, 'services_json_error'))) { |
823 | | - return true; |
824 | | - } |
| 814 | + /** |
| 815 | + * @todo Ultimately, this should just call PEAR::isError() |
| 816 | + */ |
| 817 | + function isError($data, $code = null) |
| 818 | + { |
| 819 | + if (class_exists('pear')) { |
| 820 | + return PEAR::isError($data, $code); |
| 821 | + } elseif (is_object($data) && (get_class($data) == 'services_json_error' || |
| 822 | + is_subclass_of($data, 'services_json_error'))) { |
| 823 | + return true; |
| 824 | + } |
825 | 825 | |
826 | | - return false; |
827 | | - } |
| 826 | + return false; |
| 827 | + } |
828 | 828 | } |
829 | 829 | |
830 | 830 | |
— | — | @@ -831,31 +831,31 @@ |
832 | 832 | /// @cond |
833 | 833 | if (class_exists('PEAR_Error')) { |
834 | 834 | |
835 | | - /** |
836 | | - * @ingroup API |
837 | | - */ |
838 | | - class Services_JSON_Error extends PEAR_Error |
839 | | - { |
840 | | - function Services_JSON_Error($message = 'unknown error', $code = null, |
841 | | - $mode = null, $options = null, $userinfo = null) |
842 | | - { |
843 | | - parent::PEAR_Error($message, $code, $mode, $options, $userinfo); |
844 | | - } |
845 | | - } |
| 835 | + /** |
| 836 | + * @ingroup API |
| 837 | + */ |
| 838 | + class Services_JSON_Error extends PEAR_Error |
| 839 | + { |
| 840 | + function Services_JSON_Error($message = 'unknown error', $code = null, |
| 841 | + $mode = null, $options = null, $userinfo = null) |
| 842 | + { |
| 843 | + parent::PEAR_Error($message, $code, $mode, $options, $userinfo); |
| 844 | + } |
| 845 | + } |
846 | 846 | |
847 | 847 | } else { |
848 | 848 | /// @endcond |
849 | 849 | |
850 | | - /** |
851 | | - * @todo Ultimately, this class shall be descended from PEAR_Error |
852 | | - * @ingroup API |
853 | | - */ |
854 | | - class Services_JSON_Error |
855 | | - { |
856 | | - function Services_JSON_Error($message = 'unknown error', $code = null, |
857 | | - $mode = null, $options = null, $userinfo = null) |
858 | | - { |
| 850 | + /** |
| 851 | + * @todo Ultimately, this class shall be descended from PEAR_Error |
| 852 | + * @ingroup API |
| 853 | + */ |
| 854 | + class Services_JSON_Error |
| 855 | + { |
| 856 | + function Services_JSON_Error($message = 'unknown error', $code = null, |
| 857 | + $mode = null, $options = null, $userinfo = null) |
| 858 | + { |
859 | 859 | |
860 | | - } |
861 | | - } |
| 860 | + } |
| 861 | + } |
862 | 862 | } |
Index: trunk/phase3/includes/SearchIBM_DB2.php |
— | — | @@ -1,247 +1,247 @@ |
2 | | -<?php
|
3 | | -# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
|
4 | | -# http://www.mediawiki.org/
|
5 | | -#
|
6 | | -# This program is free software; you can redistribute it and/or modify
|
7 | | -# it under the terms of the GNU General Public License as published by
|
8 | | -# the Free Software Foundation; either version 2 of the License, or
|
9 | | -# (at your option) any later version.
|
10 | | -#
|
11 | | -# This program is distributed in the hope that it will be useful,
|
12 | | -# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14 | | -# GNU General Public License for more details.
|
15 | | -#
|
16 | | -# You should have received a copy of the GNU General Public License along
|
17 | | -# with this program; if not, write to the Free Software Foundation, Inc.,
|
18 | | -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
19 | | -# http://www.gnu.org/copyleft/gpl.html
|
20 | | -
|
21 | | -/**
|
22 | | - * @file
|
23 | | - * @ingroup Search
|
24 | | - */
|
25 | | -
|
26 | | -/**
|
27 | | - * Search engine hook base class for IBM DB2
|
28 | | - * @ingroup Search
|
29 | | - */
|
30 | | -class SearchIBM_DB2 extends SearchEngine {
|
31 | | - function __construct($db) {
|
32 | | - $this->db = $db;
|
33 | | - }
|
34 | | -
|
35 | | - /**
|
36 | | - * Perform a full text search query and return a result set.
|
37 | | - *
|
38 | | - * @param string $term - Raw search term
|
39 | | - * @return IBM_DB2SearchResultSet
|
40 | | - * @access public
|
41 | | - */
|
42 | | - function searchText( $term ) {
|
43 | | - $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), true)));
|
44 | | - return new IBM_DB2SearchResultSet($resultSet, $this->searchTerms);
|
45 | | - }
|
46 | | -
|
47 | | - /**
|
48 | | - * Perform a title-only search query and return a result set.
|
49 | | - *
|
50 | | - * @param string $term - Raw search term
|
51 | | - * @return IBM_DB2SearchResultSet
|
52 | | - * @access public
|
53 | | - */
|
54 | | - function searchTitle($term) {
|
55 | | - $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), false)));
|
56 | | - return new MySQLSearchResultSet($resultSet, $this->searchTerms);
|
57 | | - }
|
58 | | -
|
59 | | -
|
60 | | - /**
|
61 | | - * Return a partial WHERE clause to exclude redirects, if so set
|
62 | | - * @return string
|
63 | | - * @private
|
64 | | - */
|
65 | | - function queryRedirect() {
|
66 | | - if ($this->showRedirects) {
|
67 | | - return '';
|
68 | | - } else {
|
69 | | - return 'AND page_is_redirect=0';
|
70 | | - }
|
71 | | - }
|
72 | | -
|
73 | | - /**
|
74 | | - * Return a partial WHERE clause to limit the search to the given namespaces
|
75 | | - * @return string
|
76 | | - * @private
|
77 | | - */
|
78 | | - function queryNamespaces() {
|
79 | | - if( is_null($this->namespaces) )
|
80 | | - return '';
|
81 | | - $namespaces = implode(',', $this->namespaces);
|
82 | | - if ($namespaces == '') {
|
83 | | - $namespaces = '0';
|
84 | | - }
|
85 | | - return 'AND page_namespace IN (' . $namespaces . ')';
|
86 | | - }
|
87 | | -
|
88 | | - /**
|
89 | | - * Return a LIMIT clause to limit results on the query.
|
90 | | - * @return string
|
91 | | - * @private
|
92 | | - */
|
93 | | - function queryLimit($sql) {
|
94 | | - return $this->db->limitResult($sql, $this->limit, $this->offset);
|
95 | | - }
|
96 | | -
|
97 | | - /**
|
98 | | - * Does not do anything for generic search engine
|
99 | | - * subclasses may define this though
|
100 | | - * @return string
|
101 | | - * @private
|
102 | | - */
|
103 | | - function queryRanking($filteredTerm, $fulltext) {
|
104 | | - // requires Net Search Extender or equivalent
|
105 | | - // return ' ORDER BY score(1)';
|
106 | | - return '';
|
107 | | - }
|
108 | | -
|
109 | | - /**
|
110 | | - * Construct the full SQL query to do the search.
|
111 | | - * The guts shoulds be constructed in queryMain()
|
112 | | - * @param string $filteredTerm
|
113 | | - * @param bool $fulltext
|
114 | | - * @private
|
115 | | - */
|
116 | | - function getQuery( $filteredTerm, $fulltext ) {
|
117 | | - return $this->queryLimit($this->queryMain($filteredTerm, $fulltext) . ' ' .
|
118 | | - $this->queryRedirect() . ' ' .
|
119 | | - $this->queryNamespaces() . ' ' .
|
120 | | - $this->queryRanking( $filteredTerm, $fulltext ) . ' ');
|
121 | | - }
|
122 | | -
|
123 | | -
|
124 | | - /**
|
125 | | - * Picks which field to index on, depending on what type of query.
|
126 | | - * @param bool $fulltext
|
127 | | - * @return string
|
128 | | - */
|
129 | | - function getIndexField($fulltext) {
|
130 | | - return $fulltext ? 'si_text' : 'si_title';
|
131 | | - }
|
132 | | -
|
133 | | - /**
|
134 | | - * Get the base part of the search query.
|
135 | | - *
|
136 | | - * @param string $filteredTerm
|
137 | | - * @param bool $fulltext
|
138 | | - * @return string
|
139 | | - * @private
|
140 | | - */
|
141 | | - function queryMain( $filteredTerm, $fulltext ) {
|
142 | | - $match = $this->parseQuery($filteredTerm, $fulltext);
|
143 | | - $page = $this->db->tableName('page');
|
144 | | - $searchindex = $this->db->tableName('searchindex');
|
145 | | - return 'SELECT page_id, page_namespace, page_title ' .
|
146 | | - "FROM $page,$searchindex " .
|
147 | | - 'WHERE page_id=si_page AND ' . $match;
|
148 | | - }
|
149 | | -
|
150 | | - /** @todo document */
|
151 | | - function parseQuery($filteredText, $fulltext) {
|
152 | | - global $wgContLang;
|
153 | | - $lc = SearchEngine::legalSearchChars();
|
154 | | - $this->searchTerms = array();
|
155 | | -
|
156 | | - # FIXME: This doesn't handle parenthetical expressions.
|
157 | | - $m = array();
|
158 | | - $q = array();
|
159 | | -
|
160 | | - if (preg_match_all('/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
|
161 | | - $filteredText, $m, PREG_SET_ORDER)) {
|
162 | | - foreach($m as $terms) {
|
163 | | - $q[] = $terms[1] . $wgContLang->stripForSearch($terms[2]);
|
164 | | -
|
165 | | - if (!empty($terms[3])) {
|
166 | | - $regexp = preg_quote( $terms[3], '/' );
|
167 | | - if ($terms[4])
|
168 | | - $regexp .= "[0-9A-Za-z_]+";
|
169 | | - } else {
|
170 | | - $regexp = preg_quote(str_replace('"', '', $terms[2]), '/');
|
171 | | - }
|
172 | | - $this->searchTerms[] = $regexp;
|
173 | | - }
|
174 | | - }
|
175 | | -
|
176 | | - $searchon = $this->db->strencode(join(',', $q));
|
177 | | - $field = $this->getIndexField($fulltext);
|
178 | | -
|
179 | | - // requires Net Search Extender or equivalent
|
180 | | - //return " CONTAINS($field, '$searchon') > 0 ";
|
181 | | -
|
182 | | - return " lcase($field) LIKE lcase('%$searchon%')";
|
183 | | - }
|
184 | | -
|
185 | | - /**
|
186 | | - * Create or update the search index record for the given page.
|
187 | | - * Title and text should be pre-processed.
|
188 | | - *
|
189 | | - * @param int $id
|
190 | | - * @param string $title
|
191 | | - * @param string $text
|
192 | | - */
|
193 | | - function update($id, $title, $text) {
|
194 | | - $dbw = wfGetDB(DB_MASTER);
|
195 | | - $dbw->replace('searchindex',
|
196 | | - array('si_page'),
|
197 | | - array(
|
198 | | - 'si_page' => $id,
|
199 | | - 'si_title' => $title,
|
200 | | - 'si_text' => $text
|
201 | | - ), 'SearchIBM_DB2::update' );
|
202 | | - // ?
|
203 | | - //$dbw->query("CALL ctx_ddl.sync_index('si_text_idx')");
|
204 | | - //$dbw->query("CALL ctx_ddl.sync_index('si_title_idx')");
|
205 | | - }
|
206 | | -
|
207 | | - /**
|
208 | | - * Update a search index record's title only.
|
209 | | - * Title should be pre-processed.
|
210 | | - *
|
211 | | - * @param int $id
|
212 | | - * @param string $title
|
213 | | - */
|
214 | | - function updateTitle($id, $title) {
|
215 | | - $dbw = wfGetDB(DB_MASTER);
|
216 | | -
|
217 | | - $dbw->update('searchindex',
|
218 | | - array('si_title' => $title),
|
219 | | - array('si_page' => $id),
|
220 | | - 'SearchIBM_DB2::updateTitle',
|
221 | | - array());
|
222 | | - }
|
223 | | -}
|
224 | | -
|
225 | | -/**
|
226 | | - * @ingroup Search
|
227 | | - */
|
228 | | -class IBM_DB2SearchResultSet extends SearchResultSet {
|
229 | | - function __construct($resultSet, $terms) {
|
230 | | - $this->mResultSet = $resultSet;
|
231 | | - $this->mTerms = $terms;
|
232 | | - }
|
233 | | -
|
234 | | - function termMatches() {
|
235 | | - return $this->mTerms;
|
236 | | - }
|
237 | | -
|
238 | | - function numRows() {
|
239 | | - return $this->mResultSet->numRows();
|
240 | | - }
|
241 | | -
|
242 | | - function next() {
|
243 | | - $row = $this->mResultSet->fetchObject();
|
244 | | - if ($row === false)
|
245 | | - return false;
|
246 | | - return new SearchResult($row);
|
247 | | - }
|
248 | | -}
|
| 2 | +<?php |
| 3 | +# Copyright (C) 2004 Brion Vibber <brion@pobox.com> |
| 4 | +# http://www.mediawiki.org/ |
| 5 | +# |
| 6 | +# This program is free software; you can redistribute it and/or modify |
| 7 | +# it under the terms of the GNU General Public License as published by |
| 8 | +# the Free Software Foundation; either version 2 of the License, or |
| 9 | +# (at your option) any later version. |
| 10 | +# |
| 11 | +# This program is distributed in the hope that it will be useful, |
| 12 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | +# GNU General Public License for more details. |
| 15 | +# |
| 16 | +# You should have received a copy of the GNU General Public License along |
| 17 | +# with this program; if not, write to the Free Software Foundation, Inc., |
| 18 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 19 | +# http://www.gnu.org/copyleft/gpl.html |
| 20 | + |
| 21 | +/** |
| 22 | + * @file |
| 23 | + * @ingroup Search |
| 24 | + */ |
| 25 | + |
| 26 | +/** |
| 27 | + * Search engine hook base class for IBM DB2 |
| 28 | + * @ingroup Search |
| 29 | + */ |
| 30 | +class SearchIBM_DB2 extends SearchEngine { |
| 31 | + function __construct($db) { |
| 32 | + $this->db = $db; |
| 33 | + } |
| 34 | + |
| 35 | + /** |
| 36 | + * Perform a full text search query and return a result set. |
| 37 | + * |
| 38 | + * @param string $term - Raw search term |
| 39 | + * @return IBM_DB2SearchResultSet |
| 40 | + * @access public |
| 41 | + */ |
| 42 | + function searchText( $term ) { |
| 43 | + $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), true))); |
| 44 | + return new IBM_DB2SearchResultSet($resultSet, $this->searchTerms); |
| 45 | + } |
| 46 | + |
| 47 | + /** |
| 48 | + * Perform a title-only search query and return a result set. |
| 49 | + * |
| 50 | + * @param string $term - Raw search term |
| 51 | + * @return IBM_DB2SearchResultSet |
| 52 | + * @access public |
| 53 | + */ |
| 54 | + function searchTitle($term) { |
| 55 | + $resultSet = $this->db->resultObject($this->db->query($this->getQuery($this->filter($term), false))); |
| 56 | + return new MySQLSearchResultSet($resultSet, $this->searchTerms); |
| 57 | + } |
| 58 | + |
| 59 | + |
| 60 | + /** |
| 61 | + * Return a partial WHERE clause to exclude redirects, if so set |
| 62 | + * @return string |
| 63 | + * @private |
| 64 | + */ |
| 65 | + function queryRedirect() { |
| 66 | + if ($this->showRedirects) { |
| 67 | + return ''; |
| 68 | + } else { |
| 69 | + return 'AND page_is_redirect=0'; |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | + /** |
| 74 | + * Return a partial WHERE clause to limit the search to the given namespaces |
| 75 | + * @return string |
| 76 | + * @private |
| 77 | + */ |
| 78 | + function queryNamespaces() { |
| 79 | + if( is_null($this->namespaces) ) |
| 80 | + return ''; |
| 81 | + $namespaces = implode(',', $this->namespaces); |
| 82 | + if ($namespaces == '') { |
| 83 | + $namespaces = '0'; |
| 84 | + } |
| 85 | + return 'AND page_namespace IN (' . $namespaces . ')'; |
| 86 | + } |
| 87 | + |
| 88 | + /** |
| 89 | + * Return a LIMIT clause to limit results on the query. |
| 90 | + * @return string |
| 91 | + * @private |
| 92 | + */ |
| 93 | + function queryLimit($sql) { |
| 94 | + return $this->db->limitResult($sql, $this->limit, $this->offset); |
| 95 | + } |
| 96 | + |
| 97 | + /** |
| 98 | + * Does not do anything for generic search engine |
| 99 | + * subclasses may define this though |
| 100 | + * @return string |
| 101 | + * @private |
| 102 | + */ |
| 103 | + function queryRanking($filteredTerm, $fulltext) { |
| 104 | + // requires Net Search Extender or equivalent |
| 105 | + // return ' ORDER BY score(1)'; |
| 106 | + return ''; |
| 107 | + } |
| 108 | + |
| 109 | + /** |
| 110 | + * Construct the full SQL query to do the search. |
| 111 | + * The guts shoulds be constructed in queryMain() |
| 112 | + * @param string $filteredTerm |
| 113 | + * @param bool $fulltext |
| 114 | + * @private |
| 115 | + */ |
| 116 | + function getQuery( $filteredTerm, $fulltext ) { |
| 117 | + return $this->queryLimit($this->queryMain($filteredTerm, $fulltext) . ' ' . |
| 118 | + $this->queryRedirect() . ' ' . |
| 119 | + $this->queryNamespaces() . ' ' . |
| 120 | + $this->queryRanking( $filteredTerm, $fulltext ) . ' '); |
| 121 | + } |
| 122 | + |
| 123 | + |
| 124 | + /** |
| 125 | + * Picks which field to index on, depending on what type of query. |
| 126 | + * @param bool $fulltext |
| 127 | + * @return string |
| 128 | + */ |
| 129 | + function getIndexField($fulltext) { |
| 130 | + return $fulltext ? 'si_text' : 'si_title'; |
| 131 | + } |
| 132 | + |
| 133 | + /** |
| 134 | + * Get the base part of the search query. |
| 135 | + * |
| 136 | + * @param string $filteredTerm |
| 137 | + * @param bool $fulltext |
| 138 | + * @return string |
| 139 | + * @private |
| 140 | + */ |
| 141 | + function queryMain( $filteredTerm, $fulltext ) { |
| 142 | + $match = $this->parseQuery($filteredTerm, $fulltext); |
| 143 | + $page = $this->db->tableName('page'); |
| 144 | + $searchindex = $this->db->tableName('searchindex'); |
| 145 | + return 'SELECT page_id, page_namespace, page_title ' . |
| 146 | + "FROM $page,$searchindex " . |
| 147 | + 'WHERE page_id=si_page AND ' . $match; |
| 148 | + } |
| 149 | + |
| 150 | + /** @todo document */ |
| 151 | + function parseQuery($filteredText, $fulltext) { |
| 152 | + global $wgContLang; |
| 153 | + $lc = SearchEngine::legalSearchChars(); |
| 154 | + $this->searchTerms = array(); |
| 155 | + |
| 156 | + # FIXME: This doesn't handle parenthetical expressions. |
| 157 | + $m = array(); |
| 158 | + $q = array(); |
| 159 | + |
| 160 | + if (preg_match_all('/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/', |
| 161 | + $filteredText, $m, PREG_SET_ORDER)) { |
| 162 | + foreach($m as $terms) { |
| 163 | + $q[] = $terms[1] . $wgContLang->stripForSearch($terms[2]); |
| 164 | + |
| 165 | + if (!empty($terms[3])) { |
| 166 | + $regexp = preg_quote( $terms[3], '/' ); |
| 167 | + if ($terms[4]) |
| 168 | + $regexp .= "[0-9A-Za-z_]+"; |
| 169 | + } else { |
| 170 | + $regexp = preg_quote(str_replace('"', '', $terms[2]), '/'); |
| 171 | + } |
| 172 | + $this->searchTerms[] = $regexp; |
| 173 | + } |
| 174 | + } |
| 175 | + |
| 176 | + $searchon = $this->db->strencode(join(',', $q)); |
| 177 | + $field = $this->getIndexField($fulltext); |
| 178 | + |
| 179 | + // requires Net Search Extender or equivalent |
| 180 | + //return " CONTAINS($field, '$searchon') > 0 "; |
| 181 | + |
| 182 | + return " lcase($field) LIKE lcase('%$searchon%')"; |
| 183 | + } |
| 184 | + |
| 185 | + /** |
| 186 | + * Create or update the search index record for the given page. |
| 187 | + * Title and text should be pre-processed. |
| 188 | + * |
| 189 | + * @param int $id |
| 190 | + * @param string $title |
| 191 | + * @param string $text |
| 192 | + */ |
| 193 | + function update($id, $title, $text) { |
| 194 | + $dbw = wfGetDB(DB_MASTER); |
| 195 | + $dbw->replace('searchindex', |
| 196 | + array('si_page'), |
| 197 | + array( |
| 198 | + 'si_page' => $id, |
| 199 | + 'si_title' => $title, |
| 200 | + 'si_text' => $text |
| 201 | + ), 'SearchIBM_DB2::update' ); |
| 202 | + // ? |
| 203 | + //$dbw->query("CALL ctx_ddl.sync_index('si_text_idx')"); |
| 204 | + //$dbw->query("CALL ctx_ddl.sync_index('si_title_idx')"); |
| 205 | + } |
| 206 | + |
| 207 | + /** |
| 208 | + * Update a search index record's title only. |
| 209 | + * Title should be pre-processed. |
| 210 | + * |
| 211 | + * @param int $id |
| 212 | + * @param string $title |
| 213 | + */ |
| 214 | + function updateTitle($id, $title) { |
| 215 | + $dbw = wfGetDB(DB_MASTER); |
| 216 | + |
| 217 | + $dbw->update('searchindex', |
| 218 | + array('si_title' => $title), |
| 219 | + array('si_page' => $id), |
| 220 | + 'SearchIBM_DB2::updateTitle', |
| 221 | + array()); |
| 222 | + } |
| 223 | +} |
| 224 | + |
| 225 | +/** |
| 226 | + * @ingroup Search |
| 227 | + */ |
| 228 | +class IBM_DB2SearchResultSet extends SearchResultSet { |
| 229 | + function __construct($resultSet, $terms) { |
| 230 | + $this->mResultSet = $resultSet; |
| 231 | + $this->mTerms = $terms; |
| 232 | + } |
| 233 | + |
| 234 | + function termMatches() { |
| 235 | + return $this->mTerms; |
| 236 | + } |
| 237 | + |
| 238 | + function numRows() { |
| 239 | + return $this->mResultSet->numRows(); |
| 240 | + } |
| 241 | + |
| 242 | + function next() { |
| 243 | + $row = $this->mResultSet->fetchObject(); |
| 244 | + if ($row === false) |
| 245 | + return false; |
| 246 | + return new SearchResult($row); |
| 247 | + } |
| 248 | +} |
Property changes on: trunk/phase3/includes/SearchIBM_DB2.php |
___________________________________________________________________ |
Name: svn:eol-style |
249 | 249 | + native |