Index: trunk/phase3/includes/DatabasePostgres.php |
— | — | @@ -146,7 +146,7 @@ |
147 | 147 | |
148 | 148 | $this->close(); |
149 | 149 | $this->mServer = $server; |
150 | | - $port = $wgDBport; |
| 150 | + $this->mPort = $port = $wgDBport; |
151 | 151 | $this->mUser = $user; |
152 | 152 | $this->mPassword = $password; |
153 | 153 | $this->mDBname = $dbName; |
— | — | @@ -159,7 +159,6 @@ |
160 | 160 | $hstring .= "port=$port "; |
161 | 161 | } |
162 | 162 | |
163 | | - |
164 | 163 | error_reporting( E_ALL ); |
165 | 164 | @$this->mConn = pg_connect("$hstring dbname=$dbName user=$user password=$password"); |
166 | 165 | |
— | — | @@ -171,328 +170,7 @@ |
172 | 171 | } |
173 | 172 | |
174 | 173 | $this->mOpened = true; |
175 | | - ## If this is the initial connection, setup the schema stuff and possibly create the user |
176 | | - ## TODO: Move this out of open() |
177 | | - if (defined('MEDIAWIKI_INSTALL')) { |
178 | | - global $wgDBname, $wgDBuser, $wgDBpassword, $wgDBsuperuser, $wgDBmwschema, |
179 | | - $wgDBts2schema; |
180 | 174 | |
181 | | - print "<li>Checking the version of Postgres..."; |
182 | | - $version = $this->getServerVersion(); |
183 | | - $PGMINVER = "8.1"; |
184 | | - if ($this->numeric_version < $PGMINVER) { |
185 | | - print "<b>FAILED</b>. Required version is $PGMINVER. You have $this->numeric_version ($version)</li>\n"; |
186 | | - dieout("</ul>"); |
187 | | - } |
188 | | - print "version $this->numeric_version is OK.</li>\n"; |
189 | | - |
190 | | - $safeuser = $this->quote_ident($wgDBuser); |
191 | | - ## Are we connecting as a superuser for the first time? |
192 | | - if ($wgDBsuperuser) { |
193 | | - ## Are we really a superuser? Check out our rights |
194 | | - $SQL = "SELECT |
195 | | - CASE WHEN usesuper IS TRUE THEN |
196 | | - CASE WHEN usecreatedb IS TRUE THEN 3 ELSE 1 END |
197 | | - ELSE CASE WHEN usecreatedb IS TRUE THEN 2 ELSE 0 END |
198 | | - END AS rights |
199 | | - FROM pg_catalog.pg_user WHERE usename = " . $this->addQuotes($wgDBsuperuser); |
200 | | - $rows = $this->numRows($res = $this->doQuery($SQL)); |
201 | | - if (!$rows) { |
202 | | - print "<li>ERROR: Could not read permissions for user \"$wgDBsuperuser\"</li>\n"; |
203 | | - dieout('</ul>'); |
204 | | - } |
205 | | - $perms = pg_fetch_result($res, 0, 0); |
206 | | - |
207 | | - $SQL = "SELECT 1 FROM pg_catalog.pg_user WHERE usename = " . $this->addQuotes($wgDBuser); |
208 | | - $rows = $this->numRows($this->doQuery($SQL)); |
209 | | - if ($rows) { |
210 | | - print "<li>User \"$wgDBuser\" already exists, skipping account creation.</li>"; |
211 | | - } |
212 | | - else { |
213 | | - if ($perms != 1 and $perms != 3) { |
214 | | - print "<li>ERROR: the user \"$wgDBsuperuser\" cannot create other users. "; |
215 | | - print 'Please use a different Postgres user.</li>'; |
216 | | - dieout('</ul>'); |
217 | | - } |
218 | | - print "<li>Creating user <b>$wgDBuser</b>..."; |
219 | | - $safepass = $this->addQuotes($wgDBpassword); |
220 | | - $SQL = "CREATE USER $safeuser NOCREATEDB PASSWORD $safepass"; |
221 | | - $this->doQuery($SQL); |
222 | | - print "OK</li>\n"; |
223 | | - } |
224 | | - ## User now exists, check out the database |
225 | | - if ($dbName != $wgDBname) { |
226 | | - $SQL = "SELECT 1 FROM pg_catalog.pg_database WHERE datname = " . $this->addQuotes($wgDBname); |
227 | | - $rows = $this->numRows($this->doQuery($SQL)); |
228 | | - if ($rows) { |
229 | | - print "<li>Database \"$wgDBname\" already exists, skipping database creation.</li>"; |
230 | | - } |
231 | | - else { |
232 | | - if ($perms < 2) { |
233 | | - print "<li>ERROR: the user \"$wgDBsuperuser\" cannot create databases. "; |
234 | | - print 'Please use a different Postgres user.</li>'; |
235 | | - dieout('</ul>'); |
236 | | - } |
237 | | - print "<li>Creating database <b>$wgDBname</b>..."; |
238 | | - $safename = $this->quote_ident($wgDBname); |
239 | | - $SQL = "CREATE DATABASE $safename OWNER $safeuser "; |
240 | | - $this->doQuery($SQL); |
241 | | - print "OK</li>\n"; |
242 | | - ## Hopefully tsearch2 and plpgsql are in template1... |
243 | | - } |
244 | | - |
245 | | - ## Reconnect to check out tsearch2 rights for this user |
246 | | - print "<li>Connecting to \"$wgDBname\" as superuser \"$wgDBsuperuser\" to check rights..."; |
247 | | - @$this->mConn = pg_connect("$hstring dbname=$wgDBname user=$user password=$password"); |
248 | | - if ( $this->mConn == false ) { |
249 | | - print "<b>FAILED TO CONNECT!</b></li>"; |
250 | | - dieout("</ul>"); |
251 | | - } |
252 | | - print "OK</li>\n"; |
253 | | - } |
254 | | - |
255 | | - ## Tsearch2 checks |
256 | | - print "<li>Checking that tsearch2 is installed in the database \"$wgDBname\"..."; |
257 | | - if (! $this->tableExists("pg_ts_cfg", $wgDBts2schema)) { |
258 | | - print "<b>FAILED</b>. tsearch2 must be installed in the database \"$wgDBname\"."; |
259 | | - print "Please see <a href='http://www.devx.com/opensource/Article/21674/0/page/2'>this article</a>"; |
260 | | - print " for instructions or ask on #postgresql on irc.freenode.net</li>\n"; |
261 | | - dieout("</ul>"); |
262 | | - } |
263 | | - print "OK</li>\n"; |
264 | | - print "<li>Ensuring that user \"$wgDBuser\" has select rights on the tsearch2 tables..."; |
265 | | - foreach (array('cfg','cfgmap','dict','parser') as $table) { |
266 | | - $SQL = "GRANT SELECT ON pg_ts_$table TO $safeuser"; |
267 | | - $this->doQuery($SQL); |
268 | | - } |
269 | | - print "OK</li>\n"; |
270 | | - |
271 | | - |
272 | | - ## Setup the schema for this user if needed |
273 | | - $result = $this->schemaExists($wgDBmwschema); |
274 | | - $safeschema = $this->quote_ident($wgDBmwschema); |
275 | | - if (!$result) { |
276 | | - print "<li>Creating schema <b>$wgDBmwschema</b> ..."; |
277 | | - $result = $this->doQuery("CREATE SCHEMA $safeschema AUTHORIZATION $safeuser"); |
278 | | - if (!$result) { |
279 | | - print "<b>FAILED</b>.</li>\n"; |
280 | | - dieout("</ul>"); |
281 | | - } |
282 | | - print "OK</li>\n"; |
283 | | - } |
284 | | - else { |
285 | | - print "<li>Schema already exists, explicitly granting rights...\n"; |
286 | | - $safeschema2 = $this->addQuotes($wgDBmwschema); |
287 | | - $SQL = "SELECT 'GRANT ALL ON '||pg_catalog.quote_ident(relname)||' TO $safeuser;'\n". |
288 | | - "FROM pg_catalog.pg_class p, pg_catalog.pg_namespace n\n". |
289 | | - "WHERE relnamespace = n.oid AND n.nspname = $safeschema2\n". |
290 | | - "AND p.relkind IN ('r','S','v')\n"; |
291 | | - $SQL .= "UNION\n"; |
292 | | - $SQL .= "SELECT 'GRANT ALL ON FUNCTION '||pg_catalog.quote_ident(proname)||'('||\n". |
293 | | - "pg_catalog.oidvectortypes(p.proargtypes)||') TO $safeuser;'\n". |
294 | | - "FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n\n". |
295 | | - "WHERE p.pronamespace = n.oid AND n.nspname = $safeschema2"; |
296 | | - $res = $this->doQuery($SQL); |
297 | | - if (!$res) { |
298 | | - print "<b>FAILED</b>. Could not set rights for the user.</li>\n"; |
299 | | - dieout("</ul>"); |
300 | | - } |
301 | | - $this->doQuery("SET search_path = $safeschema"); |
302 | | - $rows = $this->numRows($res); |
303 | | - while ($rows) { |
304 | | - $rows--; |
305 | | - $this->doQuery(pg_fetch_result($res, $rows, 0)); |
306 | | - } |
307 | | - print "OK</li>"; |
308 | | - } |
309 | | - |
310 | | - $wgDBsuperuser = ''; |
311 | | - return true; ## Reconnect as regular user |
312 | | - |
313 | | - } ## end superuser |
314 | | - |
315 | | - if (!defined('POSTGRES_SEARCHPATH')) { |
316 | | - |
317 | | - ## Do we have the basic tsearch2 table? |
318 | | - print "<li>Checking for tsearch2 in the schema \"$wgDBts2schema\"..."; |
319 | | - if (! $this->tableExists("pg_ts_dict", $wgDBts2schema)) { |
320 | | - print "<b>FAILED</b>. Make sure tsearch2 is installed. See <a href="; |
321 | | - print "'http://www.devx.com/opensource/Article/21674/0/page/2'>this article</a>"; |
322 | | - print " for instructions.</li>\n"; |
323 | | - dieout("</ul>"); |
324 | | - } |
325 | | - print "OK</li>\n"; |
326 | | - |
327 | | - ## Does this user have the rights to the tsearch2 tables? |
328 | | - $ctype = pg_fetch_result($this->doQuery("SHOW lc_ctype"),0,0); |
329 | | - print "<li>Checking tsearch2 permissions..."; |
330 | | - ## Let's check all four, just to be safe |
331 | | - error_reporting( 0 ); |
332 | | - $ts2tables = array('cfg','cfgmap','dict','parser'); |
333 | | - $safetsschema = $this->quote_ident($wgDBts2schema); |
334 | | - foreach ( $ts2tables AS $tname ) { |
335 | | - $SQL = "SELECT count(*) FROM $safetsschema.pg_ts_$tname"; |
336 | | - $res = $this->doQuery($SQL); |
337 | | - if (!$res) { |
338 | | - print "<b>FAILED</b> to access pg_ts_$tname. Make sure that the user ". |
339 | | - "\"$wgDBuser\" has SELECT access to all four tsearch2 tables</li>\n"; |
340 | | - dieout("</ul>"); |
341 | | - } |
342 | | - } |
343 | | - $SQL = "SELECT ts_name FROM $safetsschema.pg_ts_cfg WHERE locale = '$ctype'"; |
344 | | - $SQL .= " ORDER BY CASE WHEN ts_name <> 'default' THEN 1 ELSE 0 END"; |
345 | | - $res = $this->doQuery($SQL); |
346 | | - error_reporting( E_ALL ); |
347 | | - if (!$res) { |
348 | | - print "<b>FAILED</b>. Could not determine the tsearch2 locale information</li>\n"; |
349 | | - dieout("</ul>"); |
350 | | - } |
351 | | - print "OK</li>"; |
352 | | - |
353 | | - ## Will the current locale work? Can we force it to? |
354 | | - print "<li>Verifying tsearch2 locale with $ctype..."; |
355 | | - $rows = $this->numRows($res); |
356 | | - $resetlocale = 0; |
357 | | - if (!$rows) { |
358 | | - print "<b>not found</b></li>\n"; |
359 | | - print "<li>Attempting to set default tsearch2 locale to \"$ctype\"..."; |
360 | | - $resetlocale = 1; |
361 | | - } |
362 | | - else { |
363 | | - $tsname = pg_fetch_result($res, 0, 0); |
364 | | - if ($tsname != 'default') { |
365 | | - print "<b>not set to default ($tsname)</b>"; |
366 | | - print "<li>Attempting to change tsearch2 default locale to \"$ctype\"..."; |
367 | | - $resetlocale = 1; |
368 | | - } |
369 | | - } |
370 | | - if ($resetlocale) { |
371 | | - $SQL = "UPDATE $safetsschema.pg_ts_cfg SET locale = '$ctype' WHERE ts_name = 'default'"; |
372 | | - $res = $this->doQuery($SQL); |
373 | | - if (!$res) { |
374 | | - print "<b>FAILED</b>. "; |
375 | | - print "Please make sure that the locale in pg_ts_cfg for \"default\" is set to \"$ctype\"</li>\n"; |
376 | | - dieout("</ul>"); |
377 | | - } |
378 | | - print "OK</li>"; |
379 | | - } |
380 | | - |
381 | | - ## Final test: try out a simple tsearch2 query |
382 | | - $SQL = "SELECT $safetsschema.to_tsvector('default','MediaWiki tsearch2 testing')"; |
383 | | - $res = $this->doQuery($SQL); |
384 | | - if (!$res) { |
385 | | - print "<b>FAILED</b>. Specifically, \"$SQL\" did not work.</li>"; |
386 | | - dieout("</ul>"); |
387 | | - } |
388 | | - print "OK</li>"; |
389 | | - |
390 | | - ## Do we have plpgsql installed? |
391 | | - print "<li>Checking for Pl/Pgsql ..."; |
392 | | - $SQL = "SELECT 1 FROM pg_catalog.pg_language WHERE lanname = 'plpgsql'"; |
393 | | - $rows = $this->numRows($this->doQuery($SQL)); |
394 | | - if ($rows < 1) { |
395 | | - // plpgsql is not installed, but if we have a pg_pltemplate table, we should be able to create it |
396 | | - print "not installed. Attempting to install Pl/Pgsql ..."; |
397 | | - $SQL = "SELECT 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON (n.oid = c.relnamespace) ". |
398 | | - "WHERE relname = 'pg_pltemplate' AND nspname='pg_catalog'"; |
399 | | - $rows = $this->numRows($this->doQuery($SQL)); |
400 | | - if ($rows >= 1) { |
401 | | - $olde = error_reporting(0); |
402 | | - error_reporting($olde - E_WARNING); |
403 | | - $result = $this->doQuery("CREATE LANGUAGE plpgsql"); |
404 | | - error_reporting($olde); |
405 | | - if (!$result) { |
406 | | - print "<b>FAILED</b>. You need to install the language plpgsql in the database <tt>$wgDBname</tt></li>"; |
407 | | - dieout("</ul>"); |
408 | | - } |
409 | | - } |
410 | | - else { |
411 | | - print "<b>FAILED</b>. You need to install the language plpgsql in the database <tt>$wgDBname</tt></li>"; |
412 | | - dieout("</ul>"); |
413 | | - } |
414 | | - } |
415 | | - print "OK</li>\n"; |
416 | | - |
417 | | - ## Does the schema already exist? Who owns it? |
418 | | - $result = $this->schemaExists($wgDBmwschema); |
419 | | - if (!$result) { |
420 | | - print "<li>Creating schema <b>$wgDBmwschema</b> ..."; |
421 | | - error_reporting( 0 ); |
422 | | - $safeschema = $this->quote_ident($wgDBmwschema); |
423 | | - $result = $this->doQuery("CREATE SCHEMA $safeschema"); |
424 | | - error_reporting( E_ALL ); |
425 | | - if (!$result) { |
426 | | - print "<b>FAILED</b>. The user \"$wgDBuser\" must be able to access the schema. ". |
427 | | - "You can try making them the owner of the database, or try creating the schema with a ". |
428 | | - "different user, and then grant access to the \"$wgDBuser\" user.</li>\n"; |
429 | | - dieout("</ul>"); |
430 | | - } |
431 | | - print "OK</li>\n"; |
432 | | - } |
433 | | - else if ($result != $user) { |
434 | | - print "<li>Schema \"$wgDBmwschema\" exists but is not owned by \"$user\". Not ideal.</li>\n"; |
435 | | - } |
436 | | - else { |
437 | | - print "<li>Schema \"$wgDBmwschema\" exists and is owned by \"$user\". Excellent.</li>\n"; |
438 | | - } |
439 | | - |
440 | | - ## Always return GMT time to accomodate the existing integer-based timestamp assumption |
441 | | - print "<li>Setting the timezone to GMT for user \"$user\" ..."; |
442 | | - $SQL = "ALTER USER $safeuser SET timezone = 'GMT'"; |
443 | | - $result = pg_query($this->mConn, $SQL); |
444 | | - if (!$result) { |
445 | | - print "<b>FAILED</b>.</li>\n"; |
446 | | - dieout("</ul>"); |
447 | | - } |
448 | | - print "OK</li>\n"; |
449 | | - ## Set for the rest of this session |
450 | | - $SQL = "SET timezone = 'GMT'"; |
451 | | - $result = pg_query($this->mConn, $SQL); |
452 | | - if (!$result) { |
453 | | - print "<li>Failed to set timezone</li>\n"; |
454 | | - dieout("</ul>"); |
455 | | - } |
456 | | - |
457 | | - print "<li>Setting the datestyle to ISO, YMD for user \"$user\" ..."; |
458 | | - $SQL = "ALTER USER $safeuser SET datestyle = 'ISO, YMD'"; |
459 | | - $result = pg_query($this->mConn, $SQL); |
460 | | - if (!$result) { |
461 | | - print "<b>FAILED</b>.</li>\n"; |
462 | | - dieout("</ul>"); |
463 | | - } |
464 | | - print "OK</li>\n"; |
465 | | - ## Set for the rest of this session |
466 | | - $SQL = "SET datestyle = 'ISO, YMD'"; |
467 | | - $result = pg_query($this->mConn, $SQL); |
468 | | - if (!$result) { |
469 | | - print "<li>Failed to set datestyle</li>\n"; |
470 | | - dieout("</ul>"); |
471 | | - } |
472 | | - |
473 | | - ## Fix up the search paths if needed |
474 | | - print "<li>Setting the search path for user \"$user\" ..."; |
475 | | - $path = $this->quote_ident($wgDBmwschema); |
476 | | - if ($wgDBts2schema !== $wgDBmwschema) |
477 | | - $path .= ", ". $this->quote_ident($wgDBts2schema); |
478 | | - if ($wgDBmwschema !== 'public' and $wgDBts2schema !== 'public') |
479 | | - $path .= ", public"; |
480 | | - $SQL = "ALTER USER $safeuser SET search_path = $path"; |
481 | | - $result = pg_query($this->mConn, $SQL); |
482 | | - if (!$result) { |
483 | | - print "<b>FAILED</b>.</li>\n"; |
484 | | - dieout("</ul>"); |
485 | | - } |
486 | | - print "OK</li>\n"; |
487 | | - ## Set for the rest of this session |
488 | | - $SQL = "SET search_path = $path"; |
489 | | - $result = pg_query($this->mConn, $SQL); |
490 | | - if (!$result) { |
491 | | - print "<li>Failed to set search_path</li>\n"; |
492 | | - dieout("</ul>"); |
493 | | - } |
494 | | - define( "POSTGRES_SEARCHPATH", $path ); |
495 | | - }} |
496 | | - |
497 | 175 | global $wgCommandLineMode; |
498 | 176 | ## If called from the command-line (e.g. importDump), only show errors |
499 | 177 | if ($wgCommandLineMode) { |
— | — | @@ -513,6 +191,339 @@ |
514 | 192 | return $this->mConn; |
515 | 193 | } |
516 | 194 | |
| 195 | + |
| 196 | + function initial_setup($password, $dbName) { |
| 197 | + ## If this is the initial connection, setup the schema stuff and possibly create the user |
| 198 | + global $wgDBname, $wgDBuser, $wgDBpassword, $wgDBsuperuser, $wgDBmwschema, |
| 199 | + $wgDBts2schema; |
| 200 | + |
| 201 | + print "<li>Checking the version of Postgres..."; |
| 202 | + $version = $this->getServerVersion(); |
| 203 | + $PGMINVER = "8.1"; |
| 204 | + if ($this->numeric_version < $PGMINVER) { |
| 205 | + print "<b>FAILED</b>. Required version is $PGMINVER. You have $this->numeric_version ($version)</li>\n"; |
| 206 | + dieout("</ul>"); |
| 207 | + } |
| 208 | + print "version $this->numeric_version is OK.</li>\n"; |
| 209 | + |
| 210 | + $safeuser = $this->quote_ident($wgDBuser); |
| 211 | + ## Are we connecting as a superuser for the first time? |
| 212 | + if ($wgDBsuperuser) { |
| 213 | + ## Are we really a superuser? Check out our rights |
| 214 | + $SQL = "SELECT |
| 215 | + CASE WHEN usesuper IS TRUE THEN |
| 216 | + CASE WHEN usecreatedb IS TRUE THEN 3 ELSE 1 END |
| 217 | + ELSE CASE WHEN usecreatedb IS TRUE THEN 2 ELSE 0 END |
| 218 | + END AS rights |
| 219 | + FROM pg_catalog.pg_user WHERE usename = " . $this->addQuotes($wgDBsuperuser); |
| 220 | + $rows = $this->numRows($res = $this->doQuery($SQL)); |
| 221 | + if (!$rows) { |
| 222 | + print "<li>ERROR: Could not read permissions for user \"$wgDBsuperuser\"</li>\n"; |
| 223 | + dieout('</ul>'); |
| 224 | + } |
| 225 | + $perms = pg_fetch_result($res, 0, 0); |
| 226 | + |
| 227 | + $SQL = "SELECT 1 FROM pg_catalog.pg_user WHERE usename = " . $this->addQuotes($wgDBuser); |
| 228 | + $rows = $this->numRows($this->doQuery($SQL)); |
| 229 | + if ($rows) { |
| 230 | + print "<li>User \"$wgDBuser\" already exists, skipping account creation.</li>"; |
| 231 | + } |
| 232 | + else { |
| 233 | + if ($perms != 1 and $perms != 3) { |
| 234 | + print "<li>ERROR: the user \"$wgDBsuperuser\" cannot create other users. "; |
| 235 | + print 'Please use a different Postgres user.</li>'; |
| 236 | + dieout('</ul>'); |
| 237 | + } |
| 238 | + print "<li>Creating user <b>$wgDBuser</b>..."; |
| 239 | + $safepass = $this->addQuotes($wgDBpassword); |
| 240 | + $SQL = "CREATE USER $safeuser NOCREATEDB PASSWORD $safepass"; |
| 241 | + $this->doQuery($SQL); |
| 242 | + print "OK</li>\n"; |
| 243 | + } |
| 244 | + ## User now exists, check out the database |
| 245 | + if ($dbName != $wgDBname) { |
| 246 | + $SQL = "SELECT 1 FROM pg_catalog.pg_database WHERE datname = " . $this->addQuotes($wgDBname); |
| 247 | + $rows = $this->numRows($this->doQuery($SQL)); |
| 248 | + if ($rows) { |
| 249 | + print "<li>Database \"$wgDBname\" already exists, skipping database creation.</li>"; |
| 250 | + } |
| 251 | + else { |
| 252 | + if ($perms < 2) { |
| 253 | + print "<li>ERROR: the user \"$wgDBsuperuser\" cannot create databases. "; |
| 254 | + print 'Please use a different Postgres user.</li>'; |
| 255 | + dieout('</ul>'); |
| 256 | + } |
| 257 | + print "<li>Creating database <b>$wgDBname</b>..."; |
| 258 | + $safename = $this->quote_ident($wgDBname); |
| 259 | + $SQL = "CREATE DATABASE $safename OWNER $safeuser "; |
| 260 | + $this->doQuery($SQL); |
| 261 | + print "OK</li>\n"; |
| 262 | + ## Hopefully tsearch2 and plpgsql are in template1... |
| 263 | + } |
| 264 | + |
| 265 | + ## Reconnect to check out tsearch2 rights for this user |
| 266 | + print "<li>Connecting to \"$wgDBname\" as superuser \"$wgDBsuperuser\" to check rights..."; |
| 267 | + |
| 268 | + $hstring=""; |
| 269 | + if ($this->mServer!=false && $this->mServer!="") { |
| 270 | + $hstring="host=$this->mServer "; |
| 271 | + } |
| 272 | + if ($this->mPort!=false && $this->mPort!="") { |
| 273 | + $hstring .= "port=$this->mPort "; |
| 274 | + } |
| 275 | + |
| 276 | + @$this->mConn = pg_connect("$hstring dbname=$wgDBname user=$wgDBsuperuser password=$password"); |
| 277 | + if ( $this->mConn == false ) { |
| 278 | + print "<b>FAILED TO CONNECT!</b></li>"; |
| 279 | + dieout("</ul>"); |
| 280 | + } |
| 281 | + print "OK</li>\n"; |
| 282 | + } |
| 283 | + |
| 284 | + ## Tsearch2 checks |
| 285 | + print "<li>Checking that tsearch2 is installed in the database \"$wgDBname\"..."; |
| 286 | + if (! $this->tableExists("pg_ts_cfg", $wgDBts2schema)) { |
| 287 | + print "<b>FAILED</b>. tsearch2 must be installed in the database \"$wgDBname\"."; |
| 288 | + print "Please see <a href='http://www.devx.com/opensource/Article/21674/0/page/2'>this article</a>"; |
| 289 | + print " for instructions or ask on #postgresql on irc.freenode.net</li>\n"; |
| 290 | + dieout("</ul>"); |
| 291 | + } |
| 292 | + print "OK</li>\n"; |
| 293 | + print "<li>Ensuring that user \"$wgDBuser\" has select rights on the tsearch2 tables..."; |
| 294 | + foreach (array('cfg','cfgmap','dict','parser') as $table) { |
| 295 | + $SQL = "GRANT SELECT ON pg_ts_$table TO $safeuser"; |
| 296 | + $this->doQuery($SQL); |
| 297 | + } |
| 298 | + print "OK</li>\n"; |
| 299 | + |
| 300 | + |
| 301 | + ## Setup the schema for this user if needed |
| 302 | + $result = $this->schemaExists($wgDBmwschema); |
| 303 | + $safeschema = $this->quote_ident($wgDBmwschema); |
| 304 | + if (!$result) { |
| 305 | + print "<li>Creating schema <b>$wgDBmwschema</b> ..."; |
| 306 | + $result = $this->doQuery("CREATE SCHEMA $safeschema AUTHORIZATION $safeuser"); |
| 307 | + if (!$result) { |
| 308 | + print "<b>FAILED</b>.</li>\n"; |
| 309 | + dieout("</ul>"); |
| 310 | + } |
| 311 | + print "OK</li>\n"; |
| 312 | + } |
| 313 | + else { |
| 314 | + print "<li>Schema already exists, explicitly granting rights...\n"; |
| 315 | + $safeschema2 = $this->addQuotes($wgDBmwschema); |
| 316 | + $SQL = "SELECT 'GRANT ALL ON '||pg_catalog.quote_ident(relname)||' TO $safeuser;'\n". |
| 317 | + "FROM pg_catalog.pg_class p, pg_catalog.pg_namespace n\n". |
| 318 | + "WHERE relnamespace = n.oid AND n.nspname = $safeschema2\n". |
| 319 | + "AND p.relkind IN ('r','S','v')\n"; |
| 320 | + $SQL .= "UNION\n"; |
| 321 | + $SQL .= "SELECT 'GRANT ALL ON FUNCTION '||pg_catalog.quote_ident(proname)||'('||\n". |
| 322 | + "pg_catalog.oidvectortypes(p.proargtypes)||') TO $safeuser;'\n". |
| 323 | + "FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n\n". |
| 324 | + "WHERE p.pronamespace = n.oid AND n.nspname = $safeschema2"; |
| 325 | + $res = $this->doQuery($SQL); |
| 326 | + if (!$res) { |
| 327 | + print "<b>FAILED</b>. Could not set rights for the user.</li>\n"; |
| 328 | + dieout("</ul>"); |
| 329 | + } |
| 330 | + $this->doQuery("SET search_path = $safeschema"); |
| 331 | + $rows = $this->numRows($res); |
| 332 | + while ($rows) { |
| 333 | + $rows--; |
| 334 | + $this->doQuery(pg_fetch_result($res, $rows, 0)); |
| 335 | + } |
| 336 | + print "OK</li>"; |
| 337 | + } |
| 338 | + |
| 339 | + $wgDBsuperuser = ''; |
| 340 | + return true; // Reconnect as regular user |
| 341 | + |
| 342 | + } // end superuser |
| 343 | + |
| 344 | + if (!defined('POSTGRES_SEARCHPATH')) { |
| 345 | + |
| 346 | + ## Do we have the basic tsearch2 table? |
| 347 | + print "<li>Checking for tsearch2 in the schema \"$wgDBts2schema\"..."; |
| 348 | + if (! $this->tableExists("pg_ts_dict", $wgDBts2schema)) { |
| 349 | + print "<b>FAILED</b>. Make sure tsearch2 is installed. See <a href="; |
| 350 | + print "'http://www.devx.com/opensource/Article/21674/0/page/2'>this article</a>"; |
| 351 | + print " for instructions.</li>\n"; |
| 352 | + dieout("</ul>"); |
| 353 | + } |
| 354 | + print "OK</li>\n"; |
| 355 | + |
| 356 | + ## Does this user have the rights to the tsearch2 tables? |
| 357 | + $ctype = pg_fetch_result($this->doQuery("SHOW lc_ctype"),0,0); |
| 358 | + print "<li>Checking tsearch2 permissions..."; |
| 359 | + ## Let's check all four, just to be safe |
| 360 | + error_reporting( 0 ); |
| 361 | + $ts2tables = array('cfg','cfgmap','dict','parser'); |
| 362 | + $safetsschema = $this->quote_ident($wgDBts2schema); |
| 363 | + foreach ( $ts2tables AS $tname ) { |
| 364 | + $SQL = "SELECT count(*) FROM $safetsschema.pg_ts_$tname"; |
| 365 | + $res = $this->doQuery($SQL); |
| 366 | + if (!$res) { |
| 367 | + print "<b>FAILED</b> to access pg_ts_$tname. Make sure that the user ". |
| 368 | + "\"$wgDBuser\" has SELECT access to all four tsearch2 tables</li>\n"; |
| 369 | + dieout("</ul>"); |
| 370 | + } |
| 371 | + } |
| 372 | + $SQL = "SELECT ts_name FROM $safetsschema.pg_ts_cfg WHERE locale = '$ctype'"; |
| 373 | + $SQL .= " ORDER BY CASE WHEN ts_name <> 'default' THEN 1 ELSE 0 END"; |
| 374 | + $res = $this->doQuery($SQL); |
| 375 | + error_reporting( E_ALL ); |
| 376 | + if (!$res) { |
| 377 | + print "<b>FAILED</b>. Could not determine the tsearch2 locale information</li>\n"; |
| 378 | + dieout("</ul>"); |
| 379 | + } |
| 380 | + print "OK</li>"; |
| 381 | + |
| 382 | + ## Will the current locale work? Can we force it to? |
| 383 | + print "<li>Verifying tsearch2 locale with $ctype..."; |
| 384 | + $rows = $this->numRows($res); |
| 385 | + $resetlocale = 0; |
| 386 | + if (!$rows) { |
| 387 | + print "<b>not found</b></li>\n"; |
| 388 | + print "<li>Attempting to set default tsearch2 locale to \"$ctype\"..."; |
| 389 | + $resetlocale = 1; |
| 390 | + } |
| 391 | + else { |
| 392 | + $tsname = pg_fetch_result($res, 0, 0); |
| 393 | + if ($tsname != 'default') { |
| 394 | + print "<b>not set to default ($tsname)</b>"; |
| 395 | + print "<li>Attempting to change tsearch2 default locale to \"$ctype\"..."; |
| 396 | + $resetlocale = 1; |
| 397 | + } |
| 398 | + } |
| 399 | + if ($resetlocale) { |
| 400 | + $SQL = "UPDATE $safetsschema.pg_ts_cfg SET locale = '$ctype' WHERE ts_name = 'default'"; |
| 401 | + $res = $this->doQuery($SQL); |
| 402 | + if (!$res) { |
| 403 | + print "<b>FAILED</b>. "; |
| 404 | + print "Please make sure that the locale in pg_ts_cfg for \"default\" is set to \"$ctype\"</li>\n"; |
| 405 | + dieout("</ul>"); |
| 406 | + } |
| 407 | + print "OK</li>"; |
| 408 | + } |
| 409 | + |
| 410 | + ## Final test: try out a simple tsearch2 query |
| 411 | + $SQL = "SELECT $safetsschema.to_tsvector('default','MediaWiki tsearch2 testing')"; |
| 412 | + $res = $this->doQuery($SQL); |
| 413 | + if (!$res) { |
| 414 | + print "<b>FAILED</b>. Specifically, \"$SQL\" did not work.</li>"; |
| 415 | + dieout("</ul>"); |
| 416 | + } |
| 417 | + print "OK</li>"; |
| 418 | + |
| 419 | + ## Do we have plpgsql installed? |
| 420 | + print "<li>Checking for Pl/Pgsql ..."; |
| 421 | + $SQL = "SELECT 1 FROM pg_catalog.pg_language WHERE lanname = 'plpgsql'"; |
| 422 | + $rows = $this->numRows($this->doQuery($SQL)); |
| 423 | + if ($rows < 1) { |
| 424 | + // plpgsql is not installed, but if we have a pg_pltemplate table, we should be able to create it |
| 425 | + print "not installed. Attempting to install Pl/Pgsql ..."; |
| 426 | + $SQL = "SELECT 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON (n.oid = c.relnamespace) ". |
| 427 | + "WHERE relname = 'pg_pltemplate' AND nspname='pg_catalog'"; |
| 428 | + $rows = $this->numRows($this->doQuery($SQL)); |
| 429 | + if ($rows >= 1) { |
| 430 | + $olde = error_reporting(0); |
| 431 | + error_reporting($olde - E_WARNING); |
| 432 | + $result = $this->doQuery("CREATE LANGUAGE plpgsql"); |
| 433 | + error_reporting($olde); |
| 434 | + if (!$result) { |
| 435 | + print "<b>FAILED</b>. You need to install the language plpgsql in the database <tt>$wgDBname</tt></li>"; |
| 436 | + dieout("</ul>"); |
| 437 | + } |
| 438 | + } |
| 439 | + else { |
| 440 | + print "<b>FAILED</b>. You need to install the language plpgsql in the database <tt>$wgDBname</tt></li>"; |
| 441 | + dieout("</ul>"); |
| 442 | + } |
| 443 | + } |
| 444 | + print "OK</li>\n"; |
| 445 | + |
| 446 | + ## Does the schema already exist? Who owns it? |
| 447 | + $result = $this->schemaExists($wgDBmwschema); |
| 448 | + if (!$result) { |
| 449 | + print "<li>Creating schema <b>$wgDBmwschema</b> ..."; |
| 450 | + error_reporting( 0 ); |
| 451 | + $safeschema = $this->quote_ident($wgDBmwschema); |
| 452 | + $result = $this->doQuery("CREATE SCHEMA $safeschema"); |
| 453 | + error_reporting( E_ALL ); |
| 454 | + if (!$result) { |
| 455 | + print "<b>FAILED</b>. The user \"$wgDBuser\" must be able to access the schema. ". |
| 456 | + "You can try making them the owner of the database, or try creating the schema with a ". |
| 457 | + "different user, and then grant access to the \"$wgDBuser\" user.</li>\n"; |
| 458 | + dieout("</ul>"); |
| 459 | + } |
| 460 | + print "OK</li>\n"; |
| 461 | + } |
| 462 | + else if ($result != $wgDBuser) { |
| 463 | + print "<li>Schema \"$wgDBmwschema\" exists but is not owned by \"$wgDBuser\". Not ideal.</li>\n"; |
| 464 | + } |
| 465 | + else { |
| 466 | + print "<li>Schema \"$wgDBmwschema\" exists and is owned by \"$wgDBuser\". Excellent.</li>\n"; |
| 467 | + } |
| 468 | + |
| 469 | + ## Always return GMT time to accomodate the existing integer-based timestamp assumption |
| 470 | + print "<li>Setting the timezone to GMT for user \"$wgDBuser\" ..."; |
| 471 | + $SQL = "ALTER USER $safeuser SET timezone = 'GMT'"; |
| 472 | + $result = pg_query($this->mConn, $SQL); |
| 473 | + if (!$result) { |
| 474 | + print "<b>FAILED</b>.</li>\n"; |
| 475 | + dieout("</ul>"); |
| 476 | + } |
| 477 | + print "OK</li>\n"; |
| 478 | + ## Set for the rest of this session |
| 479 | + $SQL = "SET timezone = 'GMT'"; |
| 480 | + $result = pg_query($this->mConn, $SQL); |
| 481 | + if (!$result) { |
| 482 | + print "<li>Failed to set timezone</li>\n"; |
| 483 | + dieout("</ul>"); |
| 484 | + } |
| 485 | + |
| 486 | + print "<li>Setting the datestyle to ISO, YMD for user \"$wgDBuser\" ..."; |
| 487 | + $SQL = "ALTER USER $safeuser SET datestyle = 'ISO, YMD'"; |
| 488 | + $result = pg_query($this->mConn, $SQL); |
| 489 | + if (!$result) { |
| 490 | + print "<b>FAILED</b>.</li>\n"; |
| 491 | + dieout("</ul>"); |
| 492 | + } |
| 493 | + print "OK</li>\n"; |
| 494 | + ## Set for the rest of this session |
| 495 | + $SQL = "SET datestyle = 'ISO, YMD'"; |
| 496 | + $result = pg_query($this->mConn, $SQL); |
| 497 | + if (!$result) { |
| 498 | + print "<li>Failed to set datestyle</li>\n"; |
| 499 | + dieout("</ul>"); |
| 500 | + } |
| 501 | + |
| 502 | + ## Fix up the search paths if needed |
| 503 | + print "<li>Setting the search path for user \"$wgDBuser\" ..."; |
| 504 | + $path = $this->quote_ident($wgDBmwschema); |
| 505 | + if ($wgDBts2schema !== $wgDBmwschema) |
| 506 | + $path .= ", ". $this->quote_ident($wgDBts2schema); |
| 507 | + if ($wgDBmwschema !== 'public' and $wgDBts2schema !== 'public') |
| 508 | + $path .= ", public"; |
| 509 | + $SQL = "ALTER USER $safeuser SET search_path = $path"; |
| 510 | + $result = pg_query($this->mConn, $SQL); |
| 511 | + if (!$result) { |
| 512 | + print "<b>FAILED</b>.</li>\n"; |
| 513 | + dieout("</ul>"); |
| 514 | + } |
| 515 | + print "OK</li>\n"; |
| 516 | + ## Set for the rest of this session |
| 517 | + $SQL = "SET search_path = $path"; |
| 518 | + $result = pg_query($this->mConn, $SQL); |
| 519 | + if (!$result) { |
| 520 | + print "<li>Failed to set search_path</li>\n"; |
| 521 | + dieout("</ul>"); |
| 522 | + } |
| 523 | + define( "POSTGRES_SEARCHPATH", $path ); |
| 524 | + } |
| 525 | + } |
| 526 | + |
| 527 | + |
517 | 528 | /** |
518 | 529 | * Closes a database connection, if it is open |
519 | 530 | * Returns success, true if already closed |
Index: trunk/phase3/config/index.php |
— | — | @@ -839,6 +839,7 @@ |
840 | 840 | $errs["RootPW"] = "and password"; |
841 | 841 | continue; |
842 | 842 | } |
| 843 | + $wgDatabase->initial_setup($conf->RootPW, 'postgres'); |
843 | 844 | } |
844 | 845 | echo( "<li>Attempting to connect to database \"$wgDBname\" as \"$wgDBuser\"..." ); |
845 | 846 | $wgDatabase = $dbc->newFromParams($wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, 1); |
— | — | @@ -847,6 +848,7 @@ |
848 | 849 | } else { |
849 | 850 | $myver = $wgDatabase->getServerVersion(); |
850 | 851 | } |
| 852 | + $wgDatabase->initial_setup('', $wgDBname); |
851 | 853 | } |
852 | 854 | |
853 | 855 | if ( !$wgDatabase->isOpen() ) { |