'mysql' => array(
'name' => 'MySQL',
'check_module' => 'mysqli',
- 'installer' => 'mysql_db_installer',
+ 'scheme' => 'mysqli', // DSN prefix for PEAR::DB
),
'pgsql' => array(
'name' => 'PostgreSQL',
'check_module' => 'pgsql',
- 'installer' => 'pgsql_db_installer',
+ 'scheme' => 'pgsql', // DSN prefix for PEAR::DB
),
);
* Set up the database with the appropriate function for the selected type...
* Saves database info into $this->db.
*
+ * @fixme escape things in the connection string in case we have a funny pass etc
* @return mixed array of database connection params on success, false on failure
*/
function setupDatabase()
if ($this->db) {
throw new Exception("Bad order of operations: DB already set up.");
}
- $method = self::$dbModules[$this->dbtype]['installer'];
- $db = call_user_func(array($this, $method),
- $this->host,
- $this->database,
- $this->username,
- $this->password);
- $this->db = $db;
- return $this->db;
- }
-
- /**
- * Set up a database on PostgreSQL.
- * Will output status updates during the operation.
- *
- * @param string $host
- * @param string $database
- * @param string $username
- * @param string $password
- * @return mixed array of database connection params on success, false on failure
- *
- * @fixme escape things in the connection string in case we have a funny pass etc
- */
- function Pgsql_Db_installer($host, $database, $username, $password)
- {
- $connstring = "dbname=$database host=$host user=$username";
-
- //No password would mean trust authentication used.
- if (!empty($password)) {
- $connstring .= " password=$password";
- }
$this->updateStatus("Starting installation...");
- $this->updateStatus("Checking database...");
- $conn = pg_connect($connstring);
- if ($conn ===false) {
- $this->updateStatus("Failed to connect to database: $connstring");
- return false;
+ if (empty($password)) {
+ $auth = '';
+ } else {
+ $auth = ":$this->password";
}
+ $scheme = self::$dbModules[$this->dbtype]['scheme'];
- //ensure database encoding is UTF8
- $record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
- if ($record->server_encoding != 'UTF8') {
- $this->updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
+ $this->updateStatus("Checking database...");
+ $conn = $this->connectDatabase($dsn);
+ if (DB::isError($conn)) {
+ $this->updateStatus("Database connection error: " . $conn->getMessage(), true);
return false;
}
- $this->updateStatus("Running database script...");
- //wrap in transaction;
- pg_query($conn, 'BEGIN');
- $res = $this->runDbScript('statusnet_pg.sql', $conn, 'pgsql');
+ // ensure database encoding is UTF8
+ if ($this->dbtype == 'mysql') {
+ // @fixme utf8m4 support for mysql 5.5?
+ // Force the comms charset to utf8 for sanity
+ $conn->execute('SET names utf8');
+ } else if ($this->dbtype == 'pgsql') {
+ $record = $conn->getRow('SHOW server_encoding');
+ if ($record->server_encoding != 'UTF8') {
+ $this->updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
+ return false;
+ }
+ }
- if ($res === false) {
- $this->updateStatus("Can't run database script.", true);
+ $res = $this->updateStatus("Creating database tables...");
+ if (!$this->createCoreTables($conn)) {
+ $this->updateStatus("Error creating tables.", true);
return false;
}
+
foreach (array('sms_carrier' => 'SMS carrier',
'notice_source' => 'notice source',
'foreign_services' => 'foreign service')
as $scr => $name) {
$this->updateStatus(sprintf("Adding %s data to database...", $name));
- $res = $this->runDbScript($scr.'.sql', $conn, 'pgsql');
+ $res = $this->runDbScript($scr.'.sql', $conn);
if ($res === false) {
- $this->updateStatus(sprintf("Can't run %s script.", $name), true);
+ $this->updateStatus(sprintf("Can't run %d script.", $name), true);
return false;
}
}
- pg_query($conn, 'COMMIT');
-
- if (empty($password)) {
- $sqlUrl = "pgsql://$username@$host/$database";
- } else {
- $sqlUrl = "pgsql://$username:$password@$host/$database";
- }
-
- $db = array('type' => 'pgsql', 'database' => $sqlUrl);
+ $db = array('type' => $this->dbtype, 'database' => $dsn);
return $db;
}
/**
- * Set up a database on MySQL.
- * Will output status updates during the operation.
- *
- * @param string $host
- * @param string $database
- * @param string $username
- * @param string $password
- * @return mixed array of database connection params on success, false on failure
- *
- * @fixme escape things in the connection string in case we have a funny pass etc
+ * Open a connection to the database.
+ *
+ * @param <type> $dsn
+ * @return <type>
*/
- function Mysql_Db_installer($host, $database, $username, $password)
+ function connectDatabase($dsn)
{
- $this->updateStatus("Starting installation...");
- $this->updateStatus("Checking database...");
-
- $conn = mysqli_init();
- if (!$conn->real_connect($host, $username, $password)) {
- $this->updateStatus("Can't connect to server '$host' as '$username'.", true);
- return false;
- }
- $this->updateStatus("Changing to database...");
- if (!$conn->select_db($database)) {
- $this->updateStatus("Can't change to database.", true);
- return false;
- }
+ require_once 'DB.php';
+ return DB::connect($dsn);
+ }
- $this->updateStatus("Running database script...");
- $res = $this->runDbScript('statusnet.sql', $conn);
- if ($res === false) {
- $this->updateStatus("Can't run database script.", true);
- return false;
- }
- foreach (array('sms_carrier' => 'SMS carrier',
- 'notice_source' => 'notice source',
- 'foreign_services' => 'foreign service')
- as $scr => $name) {
- $this->updateStatus(sprintf("Adding %s data to database...", $name));
- $res = $this->runDbScript($scr.'.sql', $conn);
- if ($res === false) {
- $this->updateStatus(sprintf("Can't run %d script.", $name), true);
- return false;
- }
+ /**
+ * Create core tables on the given database connection.
+ *
+ * @param DB_common $conn
+ */
+ function createCoreTables(DB_common $conn)
+ {
+ $schema = Schema::get($conn);
+ $tableDefs = $this->getCoreSchema();
+ foreach ($tableDefs as $name => $def) {
+ $schema->ensureTable($name, $def);
}
+ }
- $sqlUrl = "mysqli://$username:$password@$host/$database";
- $db = array('type' => 'mysql', 'database' => $sqlUrl);
- return $db;
+ /**
+ * Fetch the core table schema definitions.
+ *
+ * @return array of table names => table def arrays
+ */
+ function getCoreSchema()
+ {
+ $schema = array();
+ include INSTALLDIR . '/db/core.php';
+ return $schema;
}
/**
/**
* Install schema into the database
*
- * @param string $filename location of database schema file
- * @param dbconn $conn connection to database
- * @param string $type type of database, currently mysql or pgsql
+ * @param string $filename location of database schema file
+ * @param DB_common $conn connection to database
*
* @return boolean - indicating success or failure
*/
- function runDbScript($filename, $conn, $type = 'mysqli')
+ function runDbScript($filename, DB_common $conn)
{
$sql = trim(file_get_contents(INSTALLDIR . '/db/' . $filename));
$stmts = explode(';', $sql);
if (!mb_strlen($stmt)) {
continue;
}
- // FIXME: use PEAR::DB or PDO instead of our own switch
- switch ($type) {
- case 'mysqli':
- $res = $conn->query($stmt);
- if ($res === false) {
- $error = $conn->error;
- }
- break;
- case 'pgsql':
- $res = pg_query($conn, $stmt);
- if ($res === false) {
- $error = pg_last_error();
- }
- break;
- default:
- $this->updateStatus("runDbScript() error: unknown database type ". $type ." provided.");
- }
- if ($res === false) {
+ $res = $conn->execute($stmt);
+ if (DB::isError($res)) {
+ $error = $result->getMessage();
$this->updateStatus("ERROR ($error) for SQL '$stmt'");
return $res;
}