Index: install.php
===================================================================
RCS file: /cvs/drupal/drupal/install.php,v
retrieving revision 1.86
diff -u -p -r1.86 install.php
--- install.php 6 Nov 2007 09:00:30 -0000 1.86
+++ install.php 8 Nov 2007 19:13:53 -0000
@@ -271,75 +271,85 @@ function install_settings_form(&$form_st
}
}
- // Database name
- $form['basic_options']['db_path'] = array(
- '#type' => 'textfield',
- '#title' => st('Database name'),
- '#default_value' => $db_path,
- '#size' => 45,
- '#maxlength' => 45,
- '#required' => TRUE,
- '#description' => $db_path_description
- );
-
- // Database username
- $form['basic_options']['db_user'] = array(
- '#type' => 'textfield',
- '#title' => st('Database username'),
- '#default_value' => $db_user,
- '#size' => 45,
- '#maxlength' => 45,
- '#required' => TRUE,
- );
-
- // Database username
- $form['basic_options']['db_pass'] = array(
- '#type' => 'password',
- '#title' => st('Database password'),
- '#default_value' => $db_pass,
- '#size' => 45,
- '#maxlength' => 45,
- );
-
- $form['advanced_options'] = array(
- '#type' => 'fieldset',
- '#title' => st('Advanced options'),
- '#collapsible' => TRUE,
- '#collapsed' => TRUE,
- '#description' => st("These options are only necessary for some sites. If you're not sure what you should enter here, leave the default settings or check with your hosting provider.")
- );
-
- // Database host
- $form['advanced_options']['db_host'] = array(
- '#type' => 'textfield',
- '#title' => st('Database host'),
- '#default_value' => $db_host,
- '#size' => 45,
- '#maxlength' => 45,
- '#required' => TRUE,
- '#description' => st('If your database is located on a different server, change this.'),
- );
-
- // Database port
- $form['advanced_options']['db_port'] = array(
- '#type' => 'textfield',
- '#title' => st('Database port'),
- '#default_value' => $db_port,
- '#size' => 45,
- '#maxlength' => 45,
- '#description' => st('If your database server is listening to a non-standard port, enter its number.'),
- );
-
- // Table prefix
+ if (count($db_types) > 1 || $db_types[0] != 'sqlite') {
+ // Database name
+ $form['basic_options']['db_path'] = array(
+ '#type' => 'textfield',
+ '#title' => st('Database name'),
+ '#default_value' => $db_path,
+ '#size' => 45,
+ '#maxlength' => 45,
+ '#description' => $db_path_description,
+ '#prefix' => '
',
+ '#suffix' => '
',
+ );
+
+ // Database username
+ $form['basic_options']['db_user'] = array(
+ '#type' => 'textfield',
+ '#title' => st('Database username'),
+ '#default_value' => $db_user,
+ '#size' => 45,
+ '#maxlength' => 45,
+ '#prefix' => '',
+ '#suffix' => '
',
+ );
+
+ // Database username
+ $form['basic_options']['db_pass'] = array(
+ '#type' => 'password',
+ '#title' => st('Database password'),
+ '#default_value' => $db_pass,
+ '#size' => 45,
+ '#maxlength' => 45,
+ '#prefix' => '',
+ '#suffix' => '
',
+ );
+
+ $form['advanced_options'] = array(
+ '#type' => 'fieldset',
+ '#title' => st('Advanced options'),
+ '#collapsible' => TRUE,
+ '#collapsed' => TRUE,
+ '#prefix' => '',
+ '#suffix' => '
',
+ '#description' => st("These options are only necessary for some sites. If you're not sure what you should enter here, leave the default settings or check with your hosting provider.")
+ );
+
+ // Database host
+ $form['advanced_options']['db_host'] = array(
+ '#type' => 'textfield',
+ '#title' => st('Database host'),
+ '#default_value' => $db_host,
+ '#size' => 45,
+ '#maxlength' => 45,
+ '#required' => TRUE,
+ '#description' => st('If your database is located on a different server, change this.'),
+ );
+
+ // Database port
+ $form['advanced_options']['db_port'] = array(
+ '#type' => 'textfield',
+ '#title' => st('Database port'),
+ '#default_value' => $db_port,
+ '#size' => 45,
+ '#maxlength' => 45,
+ '#description' => st('If your database server is listening to a non-standard port, enter its number.'),
+ );
+
+ // Table prefix
$prefix = ($profile == 'default') ? 'drupal_' : $profile .'_';
- $form['advanced_options']['db_prefix'] = array(
- '#type' => 'textfield',
- '#title' => st('Table prefix'),
- '#default_value' => $db_prefix,
- '#size' => 45,
- '#maxlength' => 45,
+ $form['advanced_options']['db_prefix'] = array(
+ '#type' => 'textfield',
+ '#title' => st('Table prefix'),
+ '#default_value' => $db_prefix,
+ '#size' => 45,
+ '#maxlength' => 45,
'#description' => st('If more than one application will be sharing this database, enter a table prefix such as %prefix for your @drupal site here.', array('@drupal' => drupal_install_profile_name(), '%prefix' => $prefix)),
- );
+ );
+
+ drupal_add_js('misc/install.js');
+ }
$form['save'] = array(
'#type' => 'submit',
@@ -368,21 +378,45 @@ function install_settings_form_validate(
*/
function _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, &$form_state, $form = NULL) {
global $db_url;
-
- // Verify the table prefix
- if (!empty($db_prefix) && is_string($db_prefix) && !preg_match('/^[A-Za-z0-9_.]+$/', $db_prefix)) {
- form_set_error('db_prefix', st('The database table prefix you have entered, %db_prefix, is invalid. The table prefix can only contain alphanumeric characters, underscores or dots.', array('%db_prefix' => $db_prefix)), 'error');
- }
-
- if (!empty($db_port) && !is_numeric($db_port)) {
- form_set_error('db_port', st('Database port must be a number.'));
- }
-
// Check database type
if (!isset($form)) {
$_db_url = is_array($db_url) ? $db_url['default'] : $db_url;
$db_type = substr($_db_url, 0, strpos($_db_url, '://'));
}
+
+ if ($db_type != 'sqlite') {
+ // Check for default username/password
+ if ($db_user == 'username' && $db_pass == 'password') {
+ form_set_error('db_user', st('You have configured @drupal to use the default username and password. This is not allowed for security reasons.', array('@drupal' => drupal_install_profile_name())));
+ }
+
+ // Verify the table prefix
+ if (!empty($db_prefix) && is_string($db_prefix) && !preg_match('/^[A-Za-z0-9_.]+$/', $db_prefix)) {
+ form_set_error('db_prefix', st('The database table prefix you have entered, %db_prefix, is invalid. The table prefix can only contain alphanumeric characters, underscores or dots.', array('%db_prefix' => $db_prefix)), 'error');
+ }
+
+ if (!empty($db_port) && !is_numeric($db_port)) {
+ form_set_error('db_port', st('Database port must be a number.'));
+ }
+
+ if (empty($db_path)) {
+ form_set_error('db_path', st('Path is a requred field for MySQL and Postgres databases.'));
+ }
+
+ if (empty($db_user)) {
+ form_set_error('db_user', st('User is a requred field for MySQL and Postgres databases.'));
+ }
+ }
+ else {
+ if ($db_user != 'dummy') {
+ $db_user = 'dummy';
+ // get current site path
+ $db_host = conf_path();
+ // Take a random starting point in the randomly
+ // generated string, not going any higher then 24
+ $db_path = $i . 'database-'.substr(md5(time()), rand(0, 24), 8).'.php';
+ }
+ }
+
$databases = drupal_detect_database_types();
if (!in_array($db_type, $databases)) {
form_set_error('db_type', st("In your %settings_file file you have configured @drupal to use a %db_type server, however your PHP installation currently does not support this database type.", array('%settings_file' => $settings_file, '@drupal' => drupal_install_profile_name(), '%db_type' => $db_type)));
Index: update.php
===================================================================
RCS file: /cvs/drupal/drupal/update.php,v
retrieving revision 1.236
diff -u -p -r1.236 update.php
--- update.php 20 Oct 2007 21:57:49 -0000 1.236
+++ update.php 8 Nov 2007 19:11:30 -0000
@@ -189,6 +189,10 @@ function update_fix_schema_version() {
case 'mysqli':
db_query('ALTER TABLE {system} ADD schema_version smallint(3) not null default -1');
break;
+
+ case 'sqlite':
+ db_query("ALTER TABLE {system} ADD schema_version INTEGER NOT NULL default '-1'");
+ break;
}
// Set all enabled (contrib) modules to schema version 0 (installed)
db_query('UPDATE {system} SET schema_version = 0 WHERE status = 1');
@@ -214,6 +218,9 @@ function update_fix_sessions() {
if ($GLOBALS['db_type'] == 'mysql') {
db_query("ALTER TABLE {sessions} ADD cache int(11) NOT NULL default '0' AFTER timestamp");
}
+ else if ($GLOBALS['db_type'] == 'sqlite') {
+ db_query("ALTER TABLE {sessions} ADD cache INTEGER NOT NULL default '0'");
+ }
elseif ($GLOBALS['db_type'] == 'pgsql') {
db_add_column($ret, 'sessions', 'cache', 'int', array('default' => 0, 'not null' => TRUE));
}
@@ -234,6 +241,9 @@ function update_fix_watchdog_115() {
if ($GLOBALS['db_type'] == 'mysql') {
$ret[] = update_sql("ALTER TABLE {watchdog} ADD severity tinyint(3) unsigned NOT NULL default '0'");
}
+ else if ($GLOBALS['db_type'] == 'sqlite') {
+ $ret[] = update_sql("ALTER TABLE {watchdog} ADD severity INTEGER NOT NULL default '0'");
+ }
else if ($GLOBALS['db_type'] == 'pgsql') {
$ret[] = update_sql('ALTER TABLE {watchdog} ADD severity smallint');
$ret[] = update_sql('UPDATE {watchdog} SET severity = 0');
@@ -263,6 +273,9 @@ function update_fix_watchdog() {
case 'mysqli':
db_query("ALTER TABLE {watchdog} ADD COLUMN referer varchar(128) NOT NULL");
break;
+ case 'sqlite':
+ db_query("ALTER TABLE {watchdog} ADD referer varchar(128) NOT NULL DEFAULT ''");
+ break;
}
variable_set('update_watchdog_fixed', TRUE);
@@ -515,6 +528,10 @@ function update_fix_system_table() {
db_add_column($ret, 'system', 'weight', 'smallint', array('not null' => TRUE, 'default' => 0));
$ret[] = update_sql('CREATE INDEX {system}_weight_idx ON {system} (weight)');
break;
+ case 'sqlite':
+ $ret[] = update_sql("ALTER TABLE {system} ADD weight INTEGER default '0' NOT NULL)");
+ $ret[] = update_sql('CREATE INDEX {system}_weight_idx ON {system} (weight)');
+ break;
case 'mysql':
case 'mysqli':
$ret[] = update_sql("ALTER TABLE {system} ADD weight tinyint(2) default '0' NOT NULL, ADD KEY (weight)");
@@ -539,6 +556,7 @@ function update_fix_access_table() {
}
break;
case 'pgsql':
+ case 'sqlite':
return;
}
@@ -651,27 +669,56 @@ function update_create_cache_tables() {
created int NOT NULL default '0',
headers text,
PRIMARY KEY (cid)
- )");
- $ret[] = update_sql("CREATE TABLE {cache_menu} (
- cid varchar(255) NOT NULL default '',
- data bytea,
- expire int NOT NULL default '0',
- created int NOT NULL default '0',
- headers text,
- PRIMARY KEY (cid)
- )");
- $ret[] = update_sql("CREATE TABLE {cache_page} (
- cid varchar(255) NOT NULL default '',
- data bytea,
- expire int NOT NULL default '0',
- created int NOT NULL default '0',
- headers text,
- PRIMARY KEY (cid)
- )");
- $ret[] = update_sql("CREATE INDEX {cache_filter}_expire_idx ON {cache_filter} (expire)");
- $ret[] = update_sql("CREATE INDEX {cache_menu}_expire_idx ON {cache_menu} (expire)");
- $ret[] = update_sql("CREATE INDEX {cache_page}_expire_idx ON {cache_page} (expire)");
- break;
+ )");
+ $ret[] = update_sql("CREATE TABLE {cache_menu} (
+ cid varchar(255) NOT NULL default '',
+ data bytea,
+ expire int NOT NULL default '0',
+ created int NOT NULL default '0',
+ headers text,
+ PRIMARY KEY (cid)
+ )");
+ $ret[] = update_sql("CREATE TABLE {cache_page} (
+ cid varchar(255) NOT NULL default '',
+ data bytea,
+ expire int NOT NULL default '0',
+ created int NOT NULL default '0',
+ headers text,
+ PRIMARY KEY (cid)
+ )");
+ $ret[] = update_sql("CREATE INDEX {cache_filter}_expire_idx ON {cache_filter} (expire)");
+ $ret[] = update_sql("CREATE INDEX {cache_menu}_expire_idx ON {cache_menu} (expire)");
+ $ret[] = update_sql("CREATE INDEX {cache_page}_expire_idx ON {cache_page} (expire)");
+ break;
+ case 'sqlite':
+ $ret[] = update_sql("CREATE TABLE {cache_filter} (
+ cid varchar(255) NOT NULL default '',
+ data blob,
+ expire int NOT NULL default '0',
+ created int NOT NULL default '0',
+ headers text,
+ PRIMARY KEY (cid)
+ )");
+ $ret[] = update_sql("CREATE TABLE {cache_menu} (
+ cid varchar(255) NOT NULL default '',
+ data blob,
+ expire int NOT NULL default '0',
+ created int NOT NULL default '0',
+ headers text,
+ PRIMARY KEY (cid)
+ )");
+ $ret[] = update_sql("CREATE TABLE {cache_page} (
+ cid varchar(255) NOT NULL default '',
+ data blob,
+ expire int NOT NULL default '0',
+ created int NOT NULL default '0',
+ headers text,
+ PRIMARY KEY (cid)
+ )");
+ $ret[] = update_sql("CREATE INDEX {cache_filter}_expire_idx ON {cache_filter} (expire)");
+ $ret[] = update_sql("CREATE INDEX {cache_menu}_expire_idx ON {cache_menu} (expire)");
+ $ret[] = update_sql("CREATE INDEX {cache_page}_expire_idx ON {cache_page} (expire)");
+ break;
}
return $ret;
}
Index: includes/database.sqlite-altertable.inc
===================================================================
RCS file: includes/database.sqlite-altertable.inc
diff -N includes/database.sqlite-altertable.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ includes/database.sqlite-altertable.inc 8 Nov 2007 17:57:24 -0000
@@ -0,0 +1,333 @@
+
+// $Id:
+
+/**
+ * @file
+ * This is a supplemental file for the sqlite database layer.
+ * It is only included when ALTER TABLE sql statements are used
+ */
+
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+/**
+ * Executes the alter table statement.
+ * This is executer in 6 steps:
+ * 1. create a temporaty table with the schema identical to the original table
+ * 2. copy the data over
+ * -- alter the original table schema
+ * 3. drop the original table
+ * 4. create the new table, also recreate all indicies
+ * 5. copy the data from the temp table to the new table
+ * 6. drop the temporaty table
+ *
+ * @param $table
+ * string - name of table to alter
+ * @param $alterdef
+ * string - the part of alter table statement, without the "ALTER TABLE -tablename-" part
+ */
+function _sqlite_altertable($table, $alterdef) {
+ global $active_db, $queries;
+
+ if($alterdef != '') {
+ $schema = _sqlite_get_table_schema($table);
+ if($schema[$table]['fields']) {
+
+ // create an exact copy of the original table
+ $tmpname = 't'. time();
+ $createtemptableSQL = 'CREATE TEMPORARY TABLE '. $tmpname . ' (' . _sqlite_build_cols_sql($table, $schema[$table]) . ')';
+
+ $prevword = $table;
+ $newcols = array();
+ $replace = array();
+
+ $oldcols = array_keys($schema[$table]['fields']);
+ foreach ($schema[$table]['fields'] as $inner_field => $def) {
+ $newcols[$inner_field] = $inner_field;
+ }
+
+ // copy the data from the original table to ist temporary copy
+ $cols = implode(", ", $newcols);
+ $copytotempsql = 'INSERT INTO '.$tmpname.'('.$cols.') SELECT '.$cols.' FROM '.$table;
+
+ // split the ALTER sentence
+ // this cuold be done, by extracting the first substring till ' '
+ $defparts = preg_split("/[\s]+/", $alterdef, -1, PREG_SPLIT_NO_EMPTY);
+ $action = strtolower($defparts[0]);
+
+ switch($action) {
+ case 'add':
+ if ($defparts[1] == 'PRIMARY' && $defparts[2] == 'KEY') {
+ $defparts[3] = str_replace("(", "", $defparts[3]);
+ $defparts[3] = str_replace(")", "", $defparts[3]);
+ // new primary keys
+ foreach (explode(",", $defparts[3]) as $npk) {
+ $schema[$table]['primary key'][] = $npk;
+ }
+ break;
+ }
+
+ array_shift($defparts);
+
+ if(sizeof($defparts) <= 2) {
+ trigger_error(check_plain('near "'. $defparts[0].($defparts[1] ? ' '. $defparts[1] : '') .'": syntax error'), E_USER_WARNING);
+ return false;
+ }
+
+ $def = array();
+ $def['type'] = $defparts[1];
+
+ $default = '';
+ if (strstr($defparts[2], "NOT")) {
+ $def['not null'] = TRUE;
+ }
+ else if (strstr($defparts[2], "DEFAULT")) {
+ $def['default'] = $default;
+
+ if (strstr($defparts[4], "NOT")) {
+ $def['not null'] = TRUE;
+ }
+ }
+ $schema[$table]['fields'][$defparts[0]] = $def;
+ break;
+
+ case 'change':
+ if(sizeof($defparts) < 3){
+ trigger_error(check_plain('near "' .$defparts[0].($defparts[1] ? ' '. $defparts[1] : '').($defparts[2] ? ' '. $defparts[2] : '').'": syntax error'), E_USER_WARNING);
+ return false;
+ }
+ if($schema['columns'][$defparts[1]]){
+ array_shift($defparts);
+
+ if($newcols[$defparts[0]] != $defparts[0]){
+ trigger_error(check_plain('unknown column "'. $defparts[1] .'" in "'. $table .'"'), E_USER_WARNING);
+ return false;
+ }
+
+ $notnull = FALSE;
+ $default = null;
+ if (strstr($defparts[3], "NOT")) {
+ $notnull = TRUE;
+ }
+ else if (strstr($defparts[3], "DEFAULT")) {
+ $default = $defparts[4];
+
+ if (strstr($defparts[5], "NOT")) {
+ $notnull = TRUE;
+ }
+ }
+
+ $schema[$table]['fields'][$defparts[0]]['name'] = $defparts[1];
+ $schema[$table]['fields'][$defparts[0]]['type'] = $defparts[2];
+
+ if (isset($schema[$table]['fields'][$defparts[0]]['not null']) && !$notnull)
+ unset($schema[$table]['fields'][$defparts[0]]['not null']);
+
+ if ($notnull)
+ $schema[$table]['fields'][$defparts[0]]['not null'] = TRUE;
+
+ if (isset($schema[$table]['fields'][$defparts[0]]['default']) && ($default == null))
+ unset($schema[$table]['fields'][$defparts[0]]['default']);
+
+ if ($default != null)
+ $schema[$table]['fields'][$defparts[0]]['default'] = $default;
+
+ // update mappings
+ $newcols[$defparts[0]] = $defparts[1];
+ }
+ else{
+ trigger_error(check_plain('unknown column "'. $defparts[1] .'" in "'. $table .'"'), E_USER_WARNING);
+ return false;
+ }
+ break;
+
+ case 'drop':
+ if(sizeof($defparts) < 2){
+ trigger_error(check_plain('near "'. $defparts[0] . ($defparts[1] ? ' ' . $defparts[1] : '') .'": syntax error'), E_USER_WARNING);
+ return false;
+ }
+
+ // are we dropping the primary key
+ if ($defparts[1] == 'PRIMARY' && $defparts[2] == 'KEY') {
+ unset($schema[$table]['primary key']);
+ break;
+ }
+ else {
+ // dropping a column
+ if($schema[$table]['fields'][$defparts[1]]){
+ // update mappings
+ unset($schema[$table]['fields'][$defparts[1]]);
+ unset($schema[$table]['primary key'][$defparts[1]]);
+ unset($newcols[$defparts[1]]);
+ _sqlite_remove_col_index($table, $schema, $defparts[1]);
+ }
+ else{
+ trigger_error(check_plain('unknown column "'. $defparts[1] .'" in "'. $table .'"'), E_USER_WARNING);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ trigger_error(check_plain('near "'. $prevword .'": syntax error modifying table '. $table), E_USER_WARNING);
+ return false;
+ }
+ $prevword = $defparts[sizeof($defparts)-1];
+
+ //this block of code generates a test table simply to verify that the columns specifed are valid in an sql statement
+ //this ensures that no reserved words are used as columns, for example
+ $colsSql = _sqlite_build_cols_sql($tmpname, $schema[$table]);
+ $indexSql = implode(" ", _sqlite_build_index_sql($table, $schema[$table]));
+ $testsql = "CREATE TABLE ". $tmpname. "(". $colsSql .");";
+ $testsql .= $indexSql;
+ sqlite_query($active_db, $testsql);
+ if($error_code = sqlite_last_error($active_db)) {
+ trigger_error(check_plain('near "'. $prevword .'": ' . sqlite_error_string($error_code). ' -> syntax error modifying table '. $table), E_USER_WARNING);
+ return false;
+ }
+ $droptempsql = 'DROP TABLE '. $tmpname;
+ // in the end drop the original table
+ $dropoldsql = 'DROP TABLE '.$table;
+ sqlite_query($active_db, $droptempsql);
+ //end block
+
+ $createnewtableSQL = "CREATE TABLE ". $table. "(". $colsSql .");";
+ $createnewtableSQL .= $indexSql;
+
+ $newcolumns = '';
+ $oldcolumns = '';
+ reset($newcols);
+ while(list($key,$val) = each($newcols)) {
+ $newcolumns .= ($newcolumns?', ':'').$val;
+ $oldcolumns .= ($oldcolumns?', ':'').$key;
+ }
+ $copytonewsql = 'INSERT INTO '. $table .'('. $newcolumns .') SELECT '. $oldcolumns .' FROM '. $tmpname;
+
+ sqlite_query($active_db, "BEGIN TRANSACTION");
+ sqlite_query($active_db, $createtemptableSQL); //create temp table
+ sqlite_query($active_db, $copytotempsql); //copy to table
+ sqlite_query($active_db, $dropoldsql); //drop old table
+ sqlite_query($active_db, $createnewtableSQL); //recreate original table
+
+ // all timings will be accounted in the _db_query, this is just to log
+ // which queries are actualli being executed, hence diff = -1;
+ if (variable_get('dev_query', 0)) {
+ $queries[] = array($createtemptableSQL, -1);
+ $queries[] = array($copytotempsql, -1);
+ $queries[] = array($dropoldsql, -1);
+ $queries[] = array($createnewtableSQL, -1);
+ }
+
+ sqlite_query($active_db, $copytonewsql); //copy back to original table
+ sqlite_query($active_db, $droptempsql); //drop temp table?
+
+ if (variable_get('dev_query', 0)) {
+ $queries[] = array($copytonewsql, -1);
+ $queries[] = array($droptempsql, -1);
+ }
+
+ if($error_code = sqlite_last_error($active_db)) {
+ trigger_error(check_plain('error executing altertable statement: '. sqlite_error_string($error_code)), E_USER_WARNING);
+ sqlite_query($active_db, "ROLLBACK");
+ return false;
+ }
+ else {
+ sqlite_query($active_db, "COMMIT");
+ return true;
+ }
+ }
+ else{
+ trigger_error(check_plain('no such table: '. $table), E_USER_WARNING);
+ return false;
+ }
+ return true;
+ }
+}
+
+function _sqlite_get_columns($table) {
+ global $active_db;
+
+ $result = sqlite_query($active_db, "SELECT * FROM $table LIMIT 1");
+ $num = sqlite_num_fields($result);
+
+ for ($i=0; $i < $num; $i++) {
+ $cols[] = sqlite_field_name ($result, $i);
+ }
+ return $cols;
+}
+
+function _sqlite_remove_col_index($table, &$schema, $column) {
+ foreach ($schema[$table]['indexes'] as $name => $collist) {
+ foreach ($collist as $i => $colname) {
+ if (is_array($colname)) {
+ if ($colname[0] == $column)
+ unset($collist[$i]);
+ }
+ else {
+ if ($colname == $column)
+ unset($collist[$i]);
+ }
+ }
+ if (count($collist) == 0)
+ unset($schema[$table]['indexes'][$name]);
+ }
+}
+
+function _sqlite_get_table_schema($tbl_name) {
+ global $active_db;
+
+ $result = sqlite_unbuffered_query($active_db, "PRAGMA table_info('".$tbl_name."')");
+ $schema = array();
+ $schema[$tbl_name] = array();
+ $schema[$tbl_name]['fields'] = array();
+ $schema[$tbl_name]['primary key'] = array();
+ $schema[$tbl_name]['unique keys'] = array();
+ $schema[$tbl_name]['indexes'] = array();
+ while ($result && sqlite_has_more($result)) {
+ $col = sqlite_fetch_array($result, SQLITE_ASSOC);
+ //array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE)
+ $schema[$tbl_name]['fields'][$col['name']] = $col;
+ if ($col['pk']) {
+ $schema[$tbl_name]['primary key'][] = $col['name'];
+ }
+ }
+
+ // build index info, so we can recreate them
+ $schema['indices'] = array();
+ $query = "SELECT * FROM sqlite_master WHERE tbl_name ='".$tbl_name."' AND type='index'";
+ $result = sqlite_unbuffered_query($active_db, $query);
+ while ($result && sqlite_has_more($result)) {
+ $index = sqlite_fetch_array($result, SQLITE_ASSOC);
+ // we don't need to create autoindices
+ if (strstr($index['name'], 'autoindex')) {
+ continue;
+ }
+ preg_match("/\((.+)\)/", $index['sql'], $matches);
+ $indexcols = array();
+ if (count($matches)) {
+ $expl = explode(",", $matches[1]);
+ if (count($expl)) {
+ foreach ($expl as $col_name) {
+ $indexcols[] = trim($col_name);
+ }
+ }
+ else {
+ $indexcols[] = trim($matches[1]);
+ }
+ }
+ if (strstr($index['sql'], "UNIQUE")) {
+ $schema[$tbl_name]['unique keys'][$index['name']] = $indexcols;
+ }
+ else {
+ $schema[$tbl_name]['indexes'][$index['name']] = $indexcols;
+ }
+ }
+ return $schema;
+}
+
+/**
+ * @} End of "ingroup database".
+ */
\ No newline at end of file
Index: includes/database.sqlite.inc
===================================================================
RCS file: includes/database.sqlite.inc
diff -N includes/database.sqlite.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ includes/database.sqlite.inc 8 Nov 2007 18:37:55 -0000
@@ -0,0 +1,971 @@
+ $t('SQLite database'),
+ 'value' => $version,
+ );
+
+ if (version_compare($version, DRUPAL_MINIMUM_SQLITE) < 0) {
+ $form['sqlite']['severity'] = REQUIREMENT_ERROR;
+ $form['sqlite']['description'] = $t('Your SQLite library is too old. Drupal requires at least SQLite %version.', array('%version' => DRUPAL_MINIMUM_SQLITE));
+ }
+
+ return $form;
+}
+
+/**
+ * Returns the version of the database server currently in use.
+ *
+ * @return Database server version
+ */
+function db_version() {
+ list($version) = explode('-', sqlite_libversion());
+ return $version;
+}
+
+/**
+ * Initialize a database connection.
+ *
+ * @param $url
+ * URL
+ * @return
+ * connection
+ */
+function db_connect($url) {
+ // Check if Sqlite support is present in PHP
+ if (!function_exists('sqlite_open')) {
+ // Redirect to installer if using default DB credentials
+ if ($url['user'] == 'username' && $url['pass'] == 'password') {
+ include_once 'includes/install.inc';
+ install_goto('install.php');
+ }
+ drupal_maintenance_theme();
+ drupal_set_title('PHP SQLITE support not enabled');
+ print theme('maintenance_page', 'We were unable to use the SQLITE database because the SQLITE extension for PHP is not installed. Check your PHP.ini to see how you can enable it.
+ If you are unsure what these terms mean you should probably contact your hosting provider.
');
+ exit;
+ }
+
+ // get database filename
+ $url = explode("@", $url);
+ $connection = sqlite_open(urldecode($url[1]));
+
+ // did it connect successfully ?
+ if (!$connection) {
+ drupal_maintenance_theme();
+ drupal_set_title('Unable to open the database');
+ print theme('maintenance_page', 'This either means that the database path in your settings.php file is incorrect or you have insufficient privileges to access the database file.
+Currently, the database path is '. theme('placeholder', $url) .'.
+If you are unsure what these terms mean you should probably contact your hosting provider.
');
+ exit;
+ }
+
+ sqlite_query($connection, "PRAGMA synchronous = OFF;"); // equivalent to MyISAM in MySQL
+ sqlite_query($connection, "PRAGMA short_column_names = 1;"); // no more rewrites
+ sqlite_query($connection, "PRAGMA temp_store = MEMORY;");
+ sqlite_query($connection, "PRAGMA cache_size = 5000");
+ sqlite_query($connection, "PRAGMA count_changes=OFF;"); // no need for that (insert/update returning number of changes as result)
+
+ // register functions which are not buil-in sqlite
+ sqlite_create_function($connection, 'concat', '_sqlite_concat');
+ sqlite_create_function($connection, 'greatest', '_sqlite_greatest');
+ sqlite_create_function($connection, 'rand', '_sqlite_rand');
+ sqlite_create_function($connection, 'if', '_sqlite_if', 3);
+ sqlite_create_function($connection, 'year', '_sqlite_year', 1);
+ sqlite_create_function($connection, 'month', '_sqlite_month', 1);
+ sqlite_create_function($connection, 'FROM_UNIXTIME', '_sqlite_from_unix_timestamp', 1);
+ sqlite_create_function($connection, 'pow', '_sqlite_pow', 2);
+ return $connection;
+}
+
+/**
+ * A user defined function to replace the CONCAT in MYSQL
+ * sqlite_udf_encode_binary in the PHP manual says sg. about first byte should not be 0x01 and there should not be 0x00 chars.
+ * But we can safely assume only UTF-8 strings will be CONCATed, no problem with that.
+ *
+ * @return
+ * string
+ */
+function _sqlite_concat() {
+ $a = func_get_args();
+ return implode('', $a);
+}
+
+function _sqlite_year($date) {
+ return date("Y", strtotime($date));
+}
+
+function _sqlite_month($date) {
+ return date("m", strtotime($date));
+}
+
+//YYYY-MM-DD HH:MM:SS
+function _sqlite_from_unix_timestamp($timestamp) {
+ return date("Y-m-d G:i:s", $timestamp);
+}
+
+function _sqlite_pow($num, $exp) {
+ return pow($num, $exp);
+}
+
+/**
+ * A user defined function to replace the GREATEST in MYSQL
+ *
+ * @return
+ * int
+ */
+function _sqlite_greatest() {
+ $a = func_get_args();
+ return max($a);
+}
+
+function _sqlite_rand() {
+ return rand();
+}
+
+/**
+ * A user defined function to replace the IF in MYSQL
+ *
+ * @param $expr
+ * Boolean expression to evaluate
+ * @param $true_part
+ * What should be returned if $expr evaluates to true
+ * @param $false_part
+ * What should be returned if $expr evaluates to false
+ * @return
+ * true_part if true, false_part else
+ */
+function _sqlite_if($expr, $true_part, $false_part) {
+ if ($expr)
+ return ($true_part);
+ else
+ return ($false_part);
+}
+
+
+function _sqlite_rewrite_query($query) {
+ $old_query = $query;
+
+ $query = preg_replace('/^SELECT COUNT\(DISTINCT\(([^.)]+\.)?([^\)]+)\)\)( AS [^ ]+)? FROM(.+)$/i',
+ 'SELECT COUNT(\2)\3 FROM (SELECT DISTINCT \1\2 FROM\4)',
+ $query);
+
+ return $query;
+}
+
+/**
+ * Runs a basic query in the active database.
+ *
+ * User-supplied arguments to the query should be passed in as separate
+ * parameters so that they can be properly escaped to avoid SQL injection
+ * attacks.
+ *
+ * @param $query
+ * A string containing an SQL query.
+ * @param ...
+ * A variable number of arguments which are substituted into the query
+ * using printf() syntax. Instead of a variable number of query arguments,
+ * you may also pass a single array containing the query arguments.
+ *
+ * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
+ * in '') and %%.
+ *
+ * NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
+ * and TRUE values to decimal 1.
+ *
+ * @return
+ * A database query result resource, or FALSE if the query was not
+ * executed correctly.
+ */
+function db_query($query) {
+ $args = func_get_args();
+ array_shift($args);
+ $query = db_prefix_tables($query);
+ if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
+ $args = $args[0];
+ }
+ _db_query_callback($args, TRUE);
+ $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
+ return _db_query($query);
+}
+
+/**
+ * Helper function for db_query().
+ *
+ * @param $query
+ * string
+ * @param $debug
+ * integer
+ * @return
+ * result
+ */
+function _db_query($query, $debug = 0) {
+ global $active_db, $queries;
+
+ if (variable_get('dev_query', 0)) {
+ list($usec, $sec) = explode(' ', microtime());
+ $timer = (float)$usec + (float)$sec;
+ }
+
+ // special call for ALTER TABLE queries
+ if(strtolower(substr(ltrim($query), 0, 5)) == 'alter') {
+ $queryparts = preg_split("/[\s]+/", $query, 4, PREG_SPLIT_NO_EMPTY);
+ $tablename = $queryparts[2];
+ $alterdefs = $queryparts[3];
+
+ if(strtolower($queryparts[1]) != 'table' || $queryparts[2] == '') {
+ trigger_error (check_plain('near "'.$queryparts[0] . '": syntax error'), E_USER_WARNING);
+ }
+ else {
+ require_once './includes/database.sqlite-altertable.inc';
+ $result = _sqlite_altertable($tablename, $alterdefs);
+ }
+ }
+ // this rewrites the TRUNCATE table clause
+ else if (strtolower(substr(ltrim($query), 0, 8)) == 'truncate') {
+ $queryparts = preg_split("/[\s]+/", $query, 3, PREG_SPLIT_NO_EMPTY);
+ $tablename = $queryparts[2];
+
+ if(strtolower($queryparts[1]) != 'table' || $queryparts[2] == '') {
+ trigger_error (check_plain('near "'.$queryparts[0] . '": syntax error'), E_USER_WARNING);
+ }
+ else {
+ $result = sqlite_query($active_db, "DELETE FROM ". $tablename);
+ }
+ }
+ // compatible queries
+ else {
+ $old_query = $query;
+
+ $query = _sqlite_rewrite_query($query);
+
+ $result = sqlite_query($active_db, $query);
+ }
+
+ if (variable_get('dev_query', 0)) {
+ $bt = debug_backtrace();
+ $query = $bt[2]['function'] . "\n" . $query;
+ list($usec, $sec) = explode(' ', microtime());
+ $stop = (float)$usec + (float)$sec;
+ $diff = $stop - $timer;
+ $queries[] = array($query, $diff);
+ }
+
+ if ($debug != 0)
+ print 'query: '. $query .'
error:'. sqlite_last_error($active_db) .'
';
+
+ if (!($error_code = sqlite_last_error($active_db))) {
+ return $result;
+ }
+ else {
+ trigger_error(check_plain(sqlite_error_string($error_code) ."\nquery: ". htmlspecialchars($query)), E_USER_WARNING);
+ }
+}
+
+/**
+ * Fetch one result row from the previous query as an object.
+ *
+ * @param $result
+ * A database query result resource, as returned from db_query().
+ * @return
+ * An object representing the next row of the result. The attributes of this
+ * object are the table fields selected by the query.
+ */
+function db_fetch_object($result) {
+ if ($result && sqlite_has_more($result)) {
+ return (object)sqlite_fetch_array($result, SQLITE_ASSOC);
+ }
+}
+
+/**
+ * Fetch one result row from the previous query as an array.
+ *
+ * @param $result
+ * A database query result resource, as returned from db_query().
+ * @return
+ * An associative array representing the next row of the result. The keys of
+ * this object are the names of the table fields selected by the query, and
+ * the values are the field values for this result row.
+ */
+function db_fetch_array($result) {
+ if ($result && sqlite_has_more($result)) {
+ return sqlite_fetch_array($result, SQLITE_ASSOC);
+ }
+}
+
+
+/**
+ * Return an individual result field from the previous query.
+ * Only use this function if exactly one field is being selected; otherwise,
+ * use db_fetch_object() or db_fetch_array().
+ *
+ * @param $result
+ * A database query result resource, as returned from db_query().
+ * @param $row
+ * The index of the row whose result is needed.
+ * @return
+ * The resulting field.
+ */
+function db_result($result, $row = 0) {
+ if ($result && sqlite_num_rows($result) > $row) {
+ sqlite_seek($result, $row);
+ return sqlite_fetch_single($result);
+ }
+ return FALSE;
+}
+
+/**
+ * Determine whether the previous query caused an error.
+ *
+ * @return
+ * string
+ */
+function db_error() {
+ global $active_db;
+ return sqlite_last_error($active_db);
+}
+
+/**
+ * Determine the number of rows changed by the preceding query.
+ *
+ * @return
+ * integer
+ */
+function db_affected_rows() {
+ global $active_db;
+ return sqlite_changes($active_db);
+}
+
+/**
+ * Runs a limited-range query in the active database.
+ * Use this as a substitute for db_query() when a subset of the query is to be
+ * returned.
+ * User-supplied arguments to the query should be passed in as separate parameters
+ * so that they can be properly escaped to avoid SQL injection attacks.
+ * @param $query
+ * A string containing an SQL query.
+ * @param ...
+ * A variable number of arguments which are substituted into the query using
+ * printf() syntax.
+ * @param $from
+ * The first result row to return.
+ * @param $count
+ * The maximum number of result rows to return.
+ * @return
+ * A database query result resource, or FALSE if the query was not executed
+ * correctly.
+ */
+function db_query_range($query) {
+ $args = func_get_args();
+ $count = array_pop($args);
+ $from = array_pop($args);
+
+ array_shift($args);
+
+ $query = db_prefix_tables($query);
+ if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
+ $args = $args[0];
+ }
+ _db_query_callback($args, TRUE);
+ $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
+ $query .= ' LIMIT '. (int)$count .' OFFSET '. (int)$from ;
+ return _db_query($query);
+}
+
+
+/**
+ * Runs a SELECT query and stores its results in a temporary table.
+ *
+ * Use this as a substitute for db_query() when the results need to stored
+ * in a temporary table. Temporary tables exist for the duration of the page
+ * request.
+ * User-supplied arguments to the query should be passed in as separate parameters
+ * so that they can be properly escaped to avoid SQL injection attacks.
+ *
+ * Note that if you need to know how many results were returned, you should do
+ * a SELECT COUNT(*) on the temporary table afterwards. db_num_rows() and
+ * db_affected_rows() do not give consistent result across different database
+ * types in this case.
+ *
+ * @param $query
+ * A string containing a normal SELECT SQL query.
+ * @param ...
+ * A variable number of arguments which are substituted into the query
+ * using printf() syntax. The query arguments can be enclosed in one
+ * array instead.
+ * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
+ * in '') and %%.
+ *
+ * NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
+ * and TRUE values to decimal 1.
+ *
+ * @param $table
+ * The name of the temporary table to select into. This name will not be
+ * prefixed as there is no risk of collision.
+ * @return
+ * A database query result resource, or FALSE if the query was not executed
+ * correctly.
+ */
+function db_query_temporary($query) {
+ $args = func_get_args();
+ $tablename = array_pop($args);
+ array_shift($args);
+
+ $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' AS SELECT', db_prefix_tables($query));
+ if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
+ $args = $args[0];
+ }
+ _db_query_callback($args, TRUE);
+ $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
+ return _db_query($query);
+}
+
+/**
+ * Returns the last insert id.
+ *
+ * @param $table
+ * The name of the table you inserted into.
+ * @param $field
+ * The name of the autoincrement field.
+ */
+function db_last_insert_id($table, $field) {
+ global $active_db;
+ return sqlite_last_insert_rowid($active_db);
+}
+
+function _sqlite_create_temp_sql($schema, &$tmpname) {
+ $tmpname = 't'. time();
+ $sql = "CREATE TEMPORARY TABLE {". $tmpname ."} (\n";
+ $sql .= _sqlite_build_cols_sql($schema);
+ return $sql;
+}
+
+function _sqlite_create_copy_sql($src_table, $dst_table, $fields) {
+ $cols = implode(", ", $fields);
+ return 'INSERT INTO '.$dst_table.'('.$cols.') SELECT '.$cols.' FROM '.$src_table;
+}
+
+/**
+ * Returns a properly formatted Binary Large OBject value.
+ *
+ * @param $data
+ * Data to encode.
+ * @return
+ * Encoded data.
+ */
+function db_encode_blob($data) {
+ return "'". sqlite_udf_encode_binary(sqlite_escape_string($data)) ."'";
+}
+
+/**
+ * Returns text from a Binary Large OBject value.
+ *
+ * @param $data
+ * Data to decode.
+ * @return
+ * Decoded data.
+ */
+function db_decode_blob($data) {
+ return sqlite_udf_decode_binary($data);
+}
+
+/**
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
+ *
+ * @param $text
+ * String to escape
+ * @return
+ * Escaped string
+ */
+function db_escape_string($text) {
+ if (is_array($text))
+ return sqlite_escape_string($text[0]);
+ else
+ return sqlite_escape_string($text);
+}
+
+/**
+ * Lock a table.
+ *
+ * @param $table
+ * string
+ */
+function db_lock_table($table) {
+ db_query('BEGIN');
+}
+
+/**
+ * Unlock all locked tables.
+ */
+function db_unlock_tables() {
+ db_query('COMMIT');
+}
+
+/**
+ * Check if a table exists.
+ */
+function db_table_exists($table) {
+ global $active_db;
+ $result = sqlite_unbuffered_query($active_db, "SELECT * FROM sqlite_master WHERE tbl_name = '".$table."'");
+ return sqlite_has_more($result);
+}
+
+/**
+ * Check if a column exists in the given table.
+ */
+function db_column_exists($table, $column) {
+ global $active_db;
+ $result = sqlite_unbuffered_query($active_db, "PRAGMA table_info('".$tbl_name."')");
+ while ($result && sqlite_has_more($result)) {
+ $col = sqlite_fetch_array($result, SQLITE_ASSOC);
+ if ($col['name'] == $column)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * @} End of "ingroup database".
+ */
+
+/**
+ * @ingroup schemaapi
+ * @{
+ */
+
+
+/**
+ * Generate SQL to create a new table from a Drupal schema definition.
+ *
+ * @param $table
+ * A valid Drupal table definition array.
+ * @return
+ * An array of SQL statements to create the table.
+ */
+function db_create_table_sql($name, $table) {
+ $sql = array();
+ $sql[] = "CREATE TABLE {". $name ."} (\n". _sqlite_build_cols_sql($name, $table) ."\n);\n";
+ return array_merge($sql, _sqlite_build_index_sql($name, $table));
+}
+
+function _sqlite_build_index_sql($tablename, $schema) {
+ $sql = array();
+ if (!empty($schema['unique keys'])) {
+ foreach ($schema['unique keys'] as $key => $fields) {
+ $sql[] = "CREATE UNIQUE INDEX ". $tablename ."_". $key ." ON ". $tablename ." (". _db_create_key_sql($fields) ."); \n";
+ }
+ }
+ if (!empty($schema['indexes'])) {
+ foreach ($schema['indexes'] as $index => $fields) {
+ $sql[] = "CREATE INDEX ". $tablename ."_". $index ." ON ". $tablename ." (". _db_create_key_sql($fields) ."); \n";
+ }
+ }
+ return $sql;
+}
+
+function _sqlite_build_cols_sql($tablename, $schema) {
+ $sql = "";
+
+ // Add the SQL statement for each field.
+ foreach ($schema['fields'] as $name => $field) {
+ if ($field['type'] == 'serial') {
+ if (($key = array_search($name, $schema['primary key'])) !== false) {
+ unset($schema['primary key'][$key]);
+ }
+ }
+ $sql .= _db_create_field_sql($name, _db_process_field($field)) .", \n";
+ }
+
+ // Process keys.
+ if (!empty($schema['primary key'])) {
+ $sql .= " PRIMARY KEY (". _db_create_key_sql($schema['primary key']) ."), \n";
+ }
+
+ // Remove the last comma and space.
+ $sql = substr($sql, 0, -3);
+ return $sql;
+}
+
+function _db_create_key_sql($fields) {
+ $ret = array();
+ foreach ($fields as $field) {
+ if (is_array($field)) {
+ $ret[] = $field[0];
+ }
+ else {
+ $ret[] = $field;
+ }
+ }
+ return implode(', ', $ret);
+}
+
+/**
+ * Set database-engine specific properties for a field.
+ *
+ * @param $field
+ * A field description array, as specified in the schema documentation.
+ */
+function _db_process_field($field) {
+
+ if (!isset($field['size'])) {
+ $field['size'] = 'normal';
+ }
+
+ // Set the correct database-engine specific datatype.
+ if (!isset($field['sqlite_type'])) {
+ $map = db_type_map();
+ $field['sqlite_type'] = $map[$field['type'] .':'. $field['size']];
+ }
+
+ if ($field['type'] == 'serial') { // this should check if field is a primary key
+ $field['auto_increment'] = TRUE;
+ }
+
+ return $field;
+}
+
+/**
+ * Create an SQL string for a field to be used in table creation or alteration.
+ *
+ * Before passing a field out of a schema definition into this function it has
+ * to be processed by _db_process_field().
+ *
+ * @param $name
+ * Name of the field.
+ * @param $spec
+ * The field specification, as per the schema data structure format.
+ */
+function _db_create_field_sql($name, $spec) {
+
+ if (!empty($spec['auto_increment'])) {
+ $sql = "". $name ." INTEGER PRIMARY KEY";
+ }
+ else {
+ $sql = "". $name ." ". $spec['sqlite_type'];
+
+ if (isset($spec['length'])) {
+ $sql .= '('. $spec['length'] .')';
+ }
+ //TODO: does scale apply for sqlite ??
+ elseif (isset($spec['precision']) && isset($spec['scale'])) {
+ $sql .= '('. $spec['scale'] .', '. $spec['precision'] .')';
+ }
+
+ if (!empty($spec['not null'])) {
+ $sql .= ' NOT NULL';
+ }
+
+ if (isset($spec['default'])) {
+ if (is_string($spec['default'])) {
+ $spec['default'] = "'". $spec['default'] ."'";
+ }
+ $sql .= ' DEFAULT '. $spec['default'];
+ }
+
+ if (empty($spec['not null']) && !isset($spec['default'])) {
+ $sql .= ' DEFAULT NULL';
+ }
+ }
+ return $sql;
+}
+
+/**
+ * This maps a generic data type in combination with its data size
+ * to the engine-specific data type.
+ */
+function db_type_map() {
+ // Put :normal last so it gets preserved by array_flip. This makes
+ // it much easier for modules (such as schema.module) to map
+ // database types back into schema types.
+ /*
+ a VARCHAR(10),
+ b NVARCHAR(15),
+ c TEXT,
+ d INTEGER,
+ e FLOAT,
+ f BOOLEAN,
+ g CLOB,
+ h BLOB,
+ i TIMESTAMP,
+ j NUMERIC(10,5)
+ k VARYING CHARACTER (24),
+ l NATIONAL VARYING CHARACTER(16)
+ */
+ $map = array(
+ 'varchar:normal' => 'VARCHAR',
+
+ 'text:tiny' => 'TEXT',
+ 'text:small' => 'TEXT',
+ 'text:medium' => 'TEXT',
+ 'text:big' => 'TEXT',
+ 'text:normal' => 'TEXT',
+
+ 'serial:tiny' => 'INTEGER',
+ 'serial:small' => 'INTEGER',
+ 'serial:medium' => 'INTEGER',
+ 'serial:big' => 'INTEGER',
+ 'serial:normal' => 'INTEGER',
+
+ 'int:tiny' => 'INTEGER',
+ 'int:small' => 'INTEGER',
+ 'int:medium' => 'INTEGER',
+ 'int:big' => 'INTEGER',
+ 'int:normal' => 'INTEGER',
+
+ 'float:tiny' => 'FLOAT',
+ 'float:small' => 'FLOAT',
+ 'float:medium' => 'FLOAT',
+ 'float:big' => 'FLOAT',
+ 'float:normal' => 'FLOAT',
+
+ 'numeric:normal' => 'NUMERIC',
+
+ 'blob:big' => 'BLOB',
+ 'blob:normal' => 'BLOB',
+
+ 'datetime:normal' => 'TIMESTAMP',
+ );
+ return $map;
+}
+
+
+/**
+ * Rename a table.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * The table to be renamed.
+ * @param $new_name
+ * The new name for the table.
+ */
+function db_rename_table(&$ret, $table, $new_name) {
+ $ret[] = update_sql('ALTER TABLE {'. $table .'} RENAME TO {'. $new_name .'}');
+}
+
+/**
+ * Drop a table.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * The table to be dropped.
+ */
+function db_drop_table(&$ret, $table) {
+ $ret[] = update_sql('DROP TABLE {'. $table .'}');
+}
+
+/**
+ * Add a new field to a table.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * Name of the table to be altered.
+ * @param $field
+ * Name of the field to be added.
+ * @param $spec
+ * The field specification array, as taken from a schema definition
+ */
+function db_add_field(&$ret, $table, $field, $spec) {
+ $query = 'ALTER TABLE {'. $table .'} ADD ';
+ $query .= _db_create_field_sql($field, _db_process_field($spec));
+ $ret[] = update_sql($query);
+}
+
+/**
+ * Drop a field.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * The table to be altered.
+ * @param $field
+ * The field to be dropped.
+ */
+function db_drop_field(&$ret, $table, $field) {
+ $ret[] = update_sql('ALTER TABLE {'. $table .'} DROP '. $field);
+}
+
+/**
+ * Set the default value for a field.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * The table to be altered.
+ * @param $field
+ * The field to be altered.
+ * @param $default
+ * Default value to be set. NULL for 'default NULL'.
+ */
+function db_field_set_default(&$ret, $table, $field, $default) {
+ if ($default == NULL) {
+ $default = 'NULL';
+ }
+ else {
+ $default = is_string($default) ? "'$default'" : $default;
+ }
+
+ $ret[] = update_sql('ALTER TABLE {'. $table .'} CHANGE '. $field .' SET DEFAULT '. $default);
+}
+
+/**
+ * Set a field to have no default value.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * The table to be altered.
+ * @param $field
+ * The field to be altered.
+ */
+function db_field_set_no_default(&$ret, $table, $field) {
+ $ret[] = update_sql('ALTER TABLE {'. $table .'} CHANGE '. $field .' DROP DEFAULT');
+}
+
+/**
+ * Add a primary key.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * The table to be altered.
+ * @param $fields
+ * Fields for the primary key.
+ */
+function db_add_primary_key(&$ret, $table, $fields) {
+ $ret[] = update_sql('ALTER TABLE {'. $table .'} ADD PRIMARY KEY ('.
+ _db_create_key_sql($fields) .')');
+}
+
+/**
+ * Drop the primary key.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * The table to be altered.
+ */
+function db_drop_primary_key(&$ret, $table) {
+ $ret[] = update_sql('ALTER TABLE {'. $table .'} DROP PRIMARY KEY');
+}
+
+/**
+ * Add a unique key.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * The table to be altered.
+ * @param $name
+ * The name of the key.
+ * @param $fields
+ * An array of field names.
+ */
+function db_add_unique_key(&$ret, $table, $name, $fields) {
+ $ret[] = update_sql('CREATE UNIQUE INDEX '. $name .' ON {'. $table .'}('. _db_create_key_sql($fields) .')');
+}
+
+/**
+ * Drop a unique key.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * The table to be altered.
+ * @param $name
+ * The name of the key.
+ */
+function db_drop_unique_key(&$ret, $table, $name) {
+ $ret[] = update_sql('DROP INDEX '. $name);
+}
+
+/**
+ * Add an index.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * The table to be altered.
+ * @param $name
+ * The name of the index.
+ * @param $fields
+ * An array of field names.
+ */
+function db_add_index(&$ret, $table, $name, $fields) {
+ $ret[] = update_sql('CREATE INDEX '. $name .' ON {'. $table .'}(' . implode($fields, ', ') . ')');
+}
+
+/**
+ * Drop an index.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * The table to be altered.
+ * @param $name
+ * The name of the index.
+ */
+function db_drop_index(&$ret, $table, $name) {
+ $ret[] = update_sql('DROP INDEX '. $name);
+}
+
+/**
+ * Change a field definition.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * Name of the table.
+ * @param $field
+ * Name of the field to change.
+ * @param $field_new
+ * New name for the field (set to the same as $field if you don't want to change the name).
+ * @param $spec
+ * The field specification for the new field.
+ */
+function db_change_field(&$ret, $table, $field, $field_new, $spec) {
+ $ret[] = update_sql("ALTER TABLE {". $table ."} CHANGE $field ".
+ _db_create_field_sql($field_new, _db_process_field($spec)));
+}
+
+/**
+ * Update a field definition to match its schema. If the field is
+ * involved in any keys or indexes, recreate them.
+ *
+ * @param $ret
+ * Array to which query results will be added.
+ * @param $table
+ * Name of the table.
+ * @param $field
+ * Name of the field to update.
+ */
+function db_update_field(&$ret, $table, $field) {
+ $spec = drupal_get_schema($table);
+ db_change_field($ret, $table, $field, $field, $spec['fields'][$field]);
+}
+
+ /**
+ * @} End of "ingroup schemaapi".
+ */
\ No newline at end of file
Index: includes/install.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/install.inc,v
retrieving revision 1.48
diff -u -p -r1.48 install.inc
--- includes/install.inc 7 Sep 2007 10:48:24 -0000 1.48
+++ includes/install.inc 8 Nov 2007 19:11:31 -0000
@@ -144,7 +144,7 @@ function drupal_detect_baseurl($file = '
function drupal_detect_database_types() {
$databases = array();
- foreach (array('mysql', 'mysqli', 'pgsql') as $type) {
+ foreach (array('mysql', 'mysqli', 'pgsql', 'sqlite') as $type) {
if (file_exists('./includes/install.'. $type .'.inc')) {
include_once './includes/install.'. $type .'.inc';
$function = $type .'_is_available';
Index: includes/install.sqlite.inc
===================================================================
RCS file: includes/install.sqlite.inc
diff -N includes/install.sqlite.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ includes/install.sqlite.inc 5 Apr 2007 22:36:26 -0000
@@ -0,0 +1,100 @@
+If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => sqlite_error_string($error))), 'error');
+ return FALSE;
+ }
+
+ $success = array('CONNECT');
+
+ // Test CREATE.
+ $query = 'CREATE TABLE drupal_install_test (id int NULL)';
+ $result = sqlite_query($connection, $query);
+ if ($error = sqlite_last_error($connection)) {
+ drupal_set_message(st('We were unable to create a test table on your SQLite database server with the command %query. SQLite reports the following message: %error.
For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => sqlite_error_string($error))), 'error');
+ return FALSE;
+ }
+ $err = FALSE;
+ $success[] = 'SELECT';
+ $success[] = 'CREATE';
+
+ // Test INSERT.
+ $query = 'INSERT INTO drupal_install_test (id) VALUES (1)';
+ $result = sqlite_query($connection, $query);
+ if ($error = sqlite_last_error($connection)) {
+ drupal_set_message(st('We were unable to insert a value into a test table on your SQLite database server. We tried inserting a value with the command %query and SQLite reported the following error: %error.', array('%query' => $query, '%error' => sqlite_error_string($error))), 'error');
+ $err = TRUE;
+ }
+ else {
+ $success[] = 'INSERT';
+ }
+
+ // Test UPDATE.
+ $query = 'UPDATE drupal_install_test SET id = 2';
+ $result = sqlite_query($connection, $query);
+ if ($error = sqlite_last_error($connection)) {
+ drupal_set_message(st('We were unable to update a value in a test table on your SQLite database server. We tried updating a value with the command %query and SQLite reported the following error: %error.', array('%query' => $query, '%error' => sqlite_error_string($error))), 'error');
+ $err = TRUE;
+ }
+ else {
+ $success[] = 'UPDATE';
+ }
+
+ // Test DELETE.
+ $query = 'DELETE FROM drupal_install_test';
+ $result = sqlite_query($connection, $query);
+ if ($error = sqlite_last_error($connection)) {
+ drupal_set_message(st('We were unable to delete a value from a test table on your SQLite database server. We tried deleting a value with the command %query and SQLite reported the following error: %error.', array('%query' => $query, '%error' => sqlite_error_string($error))), 'error');
+ $err = TRUE;
+ }
+ else {
+ $success[] = 'DELETE';
+ }
+
+ // Test DROP.
+ $query = 'DROP TABLE drupal_install_test';
+ $result = sqlite_query($connection, $query);
+ if ($error = sqlite_last_error($connection)) {
+ drupal_set_message(st('We were unable to drop a test table from your SQLite database server. We tried dropping a table with the command %query and SQLite reported the following error %error.', array('%query' => $query, '%error' => sqlite_error_string($error))), 'error');
+ $err = TRUE;
+ }
+ else {
+ $success[] = 'DROP';
+ }
+
+ if ($err) {
+ return FALSE;
+ }
+
+ sqlite_close($connection);
+ return TRUE;
+}
+
+?>
Index: misc/install.js
===================================================================
RCS file: misc/install.js
diff -N misc/install.js
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ misc/install.js 7 Mar 2007 08:13:12 -0000
@@ -0,0 +1,20 @@
+// Global Killswitch
+if (Drupal.jsEnabled) {
+ $(document).ready(
+ function(){
+ if ($("input[@value='sqlite'][@checked]").val() == 'sqlite') {
+ $("#db_path,#db_user,#db_pass,#advanced_options").hide();
+ }
+ $("input[@name='db_type']").click(function(){
+ if ($("input[@value='sqlite'][@checked]").val() == null) {
+ if ($("#advanced_options").css("display") == 'none') {
+ $("#db_path,#db_user,#db_pass,#advanced_options").show();
+ }
+ }
+ else {
+ $("#db_path,#db_user,#db_pass,#advanced_options").hide();
+ }
+ });
+ }
+ );
+}
\ No newline at end of file
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.550
diff -u -p -r1.550 system.module
--- modules/system/system.module 7 Nov 2007 20:21:33 -0000 1.550
+++ modules/system/system.module 8 Nov 2007 19:11:35 -0000
@@ -13,6 +13,7 @@ define('DRUPAL_MINIMUM_PHP', '4.3.3')
define('DRUPAL_MINIMUM_MYSQL', '4.1.0'); // If using MySQL
define('DRUPAL_MINIMUM_PGSQL', '7.4'); // If using PostgreSQL
define('DRUPAL_MINIMUM_APACHE', '1.3'); // If using Apache
+define('DRUPAL_MINIMUM_SQLITE', '2.7.0'); // If using SQLite
// Maximum age of temporary files in seconds.
define('DRUPAL_MAXIMUM_TEMP_FILE_AGE', 1440);