Index: drupal-6.x-siren/3RD_PARTY_MODULE_HACK_HOWTO.txt =================================================================== RCS file: drupal-6.x-siren/3RD_PARTY_MODULE_HACK_HOWTO.txt diff -N drupal-6.x-siren/3RD_PARTY_MODULE_HACK_HOWTO.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ drupal-6.x-siren/3RD_PARTY_MODULE_HACK_HOWTO.txt 4 Dec 2007 07:56:06 -0000 @@ -0,0 +1,38 @@ +3rd PARTY MODULE HACK HOWTO +--------------------------- + +Based on cross database compatibility concern, this unofficial drupal-6.x-dev +come with lots of core queries hack. Most works are done for you, and it +should run across MySQl/PgSQL/Oracle without any critical problem. + +Anyway, you will also need to apply some 3rd party module. So how to let them +work together with this unofficial core? + +1. ENCLOSE ALL TABLE/COLUMN/CONSTRAINT NAME WITH [] + + Go though you target module, and enclose all table/column/constraint name + with [] syntax, which similar as {} syntax for all table. + + This can be helped by using VI + regex: /{[A-Za-z0-9_]*} + +2. REPLACE ALL '%s' SYNTAX WITH %s + + This is very important for unofficial PDO supporting. + + This can be helped by using VI + regex: :%s/'%s'/%s/gc + +3. REMOVE ANY %% SYNTAX + + PDO don't allow inline % syntax when using with ? placeholder. + + This can be helped by using VI + regex: /%% + +4. UTILIZE ALL DB_* ABSTRACTION IF POSSIBLE + + These abstraction are mainly duel with syntax different among different DB. + +5. USE %s EVEN IT IS AN EMPTY STRING + + Using empty string as placeholder will cause problem among Oracle and + MSSQL. Escape it by using %s. Oracle and MSSQL driver will able to catch + them and replace it as required empty string placeholder internally. Index: drupal-6.x-siren/INSTALL.oci.txt =================================================================== RCS file: drupal-6.x-siren/INSTALL.oci.txt diff -N drupal-6.x-siren/INSTALL.oci.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ drupal-6.x-siren/INSTALL.oci.txt 4 Dec 2007 07:56:06 -0000 @@ -0,0 +1,71 @@ +// $Id$ + +CREATE THE Oracle DATABASE +-------------------------- + +This file describes how to create a Oracle database for Drupal. + +If you control your databases through a web-based control panel, +check its documentation, as the following instructions are for the +command line only. + +This step is only necessary if you don't already have a database +set-up (e.g. by your host). In the following examples, 'dba_user' is +an example Oracle user which has the CREATE and GRANT privileges. Use +the appropriate user name for your system. + +Optionally, you can create a new tablespace for your Drupal site +datebase. Log into sqlplus by following command: + + sqlplus dba_user + +sqlplus will prompt for the 'dba_user' database password. At the +sqlplus prompt, enter following command: + + CREATE TABLESPACE tablespace_name + DATAFILE 'file_directory_path' + SIZE filesize AUTOEXTEND ON NEXT extend_size; + +where + + 'tablespace_name' is the name of you new tablespace + 'file_directory_path' is the file location in database server + 'filesize' is the initial file size, e.g. 50K, 1000M. + 'extend_size' is the volumn for extension when data file is full + +First, you must create a new user for your Drupal site. At the +sqlplus prompt, enter the following command: + + CREATE USER username + IDENTIFIED BY "password"; + DEFAULT TABLESPACE tablespace_name; + GRANT CONNECT, RESOURCE TO username; + +where + + 'tablespace_name' is the name of you tablespace + 'username' is the username of your Oracle account + 'password' is the password required for that username + + Note: Unless your database user has all of the privileges listed + above, you will not be able to run Drupal. + +Oracle SPECIAL REQUIREMENTS +--------------------------- + +1. SYSTEM REQUIREMENT + + Oracle driver for Drupal is fully tested with below softwares: + Oracle Database 10g Release 2 (10.2.0.1.0) for Linux x86, + Zend Core for Oracle v.2 Linux x86, + Zend Framework 1.0.0, + PHP Version 5.2.3, + Apache 2.2.3 (Debian) + + You may use something newer than above, but there is no guarantee for + backward compatible. + +2. TABLE PREFIX LIMITATION + + Table prefix are limited in maximum 12 characters. Proved by testing, it + is suggested to use table prefix within 10 characters. Index: drupal-6.x-siren/install.php =================================================================== RCS file: /cvs/drupal/drupal/install.php,v retrieving revision 1.99 diff -u -p -r1.99 install.php --- drupal-6.x-siren/install.php 30 Nov 2007 23:09:14 -0000 1.99 +++ drupal-6.x-siren/install.php 4 Dec 2007 07:56:07 -0000 @@ -142,7 +142,7 @@ function install_main() { */ function install_verify_drupal() { // Read the variable manually using the @ so we don't trigger an error if it fails. - $result = @db_query("SELECT value FROM {variable} WHERE name = '%s'", 'install_task'); + $result = @db_query("SELECT [value] FROM [{variable}] WHERE [name] = %s", 'install_task'); if ($result) { return unserialize(db_result($result)); } @@ -195,7 +195,7 @@ function install_change_settings($profil include_once './includes/form.inc'; install_task_list('database'); - if ($db_url == 'mysql://username:password@localhost/databasename') { + if ($db_url == 'drupal://username:password@localhost/databasename#mysql') { $db_user = $db_pass = $db_path = ''; } elseif (!empty($db_url)) { @@ -223,6 +223,15 @@ function install_settings_form(&$form_st if (isset($db_types['mysqli'])) { unset($db_types['mysql']); } + // If both 'mysqli' and 'pdo_mysql' are available, we disable 'mysqli': + if (isset($db_types['pdo_mysql'])) { + unset($db_types['mysqli']); + } + + // If both 'pgsql' and 'pdo_pgsql' are available, we disable 'pgsql': + if (isset($db_types['pdo_pgsql'])) { + unset($db_types['pgsql']); + } if (count($db_types) == 0) { $form['no_db_types'] = array( @@ -368,7 +377,8 @@ function _install_settings_form_validate // 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, '://')); + $_db_url = parse_url($_db_url); + $db_type = $_db_url['fragment']; } $databases = drupal_detect_database_types(); if (!in_array($db_type, $databases)) { @@ -376,7 +386,7 @@ function _install_settings_form_validate } else { // Verify - $db_url = $db_type .'://'. urlencode($db_user) . ($db_pass ? ':'. urlencode($db_pass) : '') .'@'. ($db_host ? urlencode($db_host) : 'localhost') . ($db_port ? ":$db_port" : '') .'/'. urlencode($db_path); + $db_url = 'drupal://'. urlencode($db_user) . ($db_pass ? ':'. urlencode($db_pass) : '') .'@'. ($db_host ? urlencode($db_host) : 'localhost') . ($db_port ? ":$db_port" : '') .'/'. urlencode($db_path) .'#'. $db_type; if (isset($form)) { form_set_value($form['_db_url'], $db_url, $form_state); } Index: drupal-6.x-siren/update.php =================================================================== RCS file: /cvs/drupal/drupal/update.php,v retrieving revision 1.238 diff -u -p -r1.238 update.php --- drupal-6.x-siren/update.php 30 Nov 2007 12:19:10 -0000 1.238 +++ drupal-6.x-siren/update.php 4 Dec 2007 07:56:07 -0000 @@ -49,26 +49,26 @@ function db_add_column(&$ret, $table, $c if (array_key_exists('default', $attributes)) { if (is_null($attributes['default'])) { $default_val = 'NULL'; - $default = 'default NULL'; + $default = 'DEFAULT NULL'; } elseif ($attributes['default'] === FALSE) { $default = ''; } else { - $default_val = "$attributes[default]"; - $default = "default $attributes[default]"; + $default_val = $attributes['default']; + $default = "DEFAULT ". $attributes['default']; } } - $ret[] = update_sql("ALTER TABLE {". $table ."} ADD $column $type"); + $ret[] = update_sql("ALTER TABLE [{". $table ."}] ADD [$column] $type"); if (!empty($default)) { - $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column SET $default"); + $ret[] = update_sql("ALTER TABLE [{". $table ."}] ALTER [$column] SET $default"); } if (!empty($not_null)) { if (!empty($default)) { - $ret[] = update_sql("UPDATE {". $table ."} SET $column = $default_val"); + $ret[] = update_sql("UPDATE [{". $table ."}] SET [$column] = $default_val"); } - $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column SET NOT NULL"); + $ret[] = update_sql("ALTER TABLE [{". $table ."}] ALTER [$column] SET NOT NULL"); } } @@ -105,23 +105,23 @@ function db_change_column(&$ret, $table, if (array_key_exists('default', $attributes)) { if (is_null($attributes['default'])) { $default_val = 'NULL'; - $default = 'default NULL'; + $default = 'DEFAULT NULL'; } elseif ($attributes['default'] === FALSE) { $default = ''; } else { - $default_val = "$attributes[default]"; - $default = "default $attributes[default]"; + $default_val = $attributes['default']; + $default = "DEFAULT ". $attributes['default']; } } - $ret[] = update_sql("ALTER TABLE {". $table ."} RENAME $column TO ". $column ."_old"); - $ret[] = update_sql("ALTER TABLE {". $table ."} ADD $column_new $type"); - $ret[] = update_sql("UPDATE {". $table ."} SET $column_new = ". $column ."_old"); - if ($default) { $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column_new SET $default"); } - if ($not_null) { $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column_new SET NOT NULL"); } - $ret[] = update_sql("ALTER TABLE {". $table ."} DROP ". $column ."_old"); + $ret[] = update_sql("ALTER TABLE [{". $table ."}] RENAME [$column] TO [". $column ."_old]"); + $ret[] = update_sql("ALTER TABLE [{". $table ."}] ADD [$column_new] $type"); + $ret[] = update_sql("UPDATE [{". $table ."}] SET [$column_new] = [". $column ."_old]"); + if ($default) { $ret[] = update_sql("ALTER TABLE [{". $table ."}] ALTER [$column_new] SET $default"); } + if ($not_null) { $ret[] = update_sql("ALTER TABLE [{". $table ."}] ALTER [$column_new] SET NOT NULL"); } + $ret[] = update_sql("ALTER TABLE [{". $table ."}] DROP [". $column ."_old]"); } /** @@ -507,19 +507,19 @@ function update_fix_system_table() { foreach ($core_modules as $module) { $old_path = "modules/$module.module"; $new_path = "modules/$module/$module.module"; - db_query("UPDATE {system} SET filename = '%s' WHERE filename = '%s'", $new_path, $old_path); + db_query("UPDATE [{system}] SET [filename] = %s WHERE [filename] = %s", $new_path, $old_path); } - $row = db_fetch_object(db_query_range('SELECT * FROM {system}', 0, 1)); + $row = db_fetch_object(db_query_range('SELECT * FROM [{system}]', 0, 1)); if (!isset($row->weight)) { $ret = array(); switch ($GLOBALS['db_type']) { case 'pgsql': db_add_column($ret, 'system', 'weight', 'smallint', array('not null' => TRUE, 'default' => 0)); - $ret[] = update_sql('CREATE INDEX {system}_weight_idx ON {system} (weight)'); + $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)"); + $ret[] = update_sql("ALTER TABLE [{system}] ADD [weight] TINYINT(2) DEFAULT '0' NOT NULL, ADD KEY ([weight])"); break; } } @@ -545,7 +545,7 @@ function update_fix_access_table() { } // Convert access table to UTF-8 if needed. - $result = db_fetch_array(db_query('SHOW CREATE TABLE {access}')); + $result = db_fetch_array(db_query('SHOW CREATE TABLE [{access}]')); if (!preg_match('/utf8/i', array_pop($result))) { update_convert_table_utf8('access'); } @@ -575,7 +575,7 @@ function update_convert_table_utf8($tabl $convert_to_utf8 = array(); // Set table default charset - $ret[] = update_sql('ALTER TABLE {'. $table .'} DEFAULT CHARACTER SET utf8'); + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DEFAULT CHARACTER SET utf8'); // Find out which columns need converting and build SQL statements $result = db_query('SHOW FULL COLUMNS FROM {'. $table .'}'); @@ -594,9 +594,9 @@ function update_convert_table_utf8($tabl if (count($convert_to_binary)) { // Convert text columns to binary - $ret[] = update_sql('ALTER TABLE {'. $table .'} '. implode(', ', $convert_to_binary)); + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] '. implode(', ', $convert_to_binary)); // Convert binary columns to UTF-8 - $ret[] = update_sql('ALTER TABLE {'. $table .'} '. implode(', ', $convert_to_utf8)); + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] '. implode(', ', $convert_to_utf8)); } return $ret; } @@ -715,7 +715,7 @@ function update_fix_compatibility() { $incompatible = array(); $themes = system_theme_data(); $modules = module_rebuild_cache(); - $query = db_query("SELECT name, type, status FROM {system} WHERE status = 1 AND type IN ('module','theme')"); + $query = db_query("SELECT [name], [type], [status] FROM [{system}] WHERE [status] = 1 AND [type] IN ('module', 'theme')"); while ($result = db_fetch_object($query)) { $name = $result->name; $file = array(); @@ -733,7 +733,7 @@ function update_fix_compatibility() { } } if (!empty($incompatible)) { - $ret[] = update_sql("UPDATE {system} SET status = 0 WHERE name IN ('". implode("','", $incompatible) ."')"); + $ret[] = update_sql("UPDATE [{system}] SET [status] = 0 WHERE [name] IN ('". implode("', '", $incompatible) ."')"); } return $ret; } Index: drupal-6.x-siren/includes/actions.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/actions.inc,v retrieving revision 1.6 diff -u -p -r1.6 actions.inc --- drupal-6.x-siren/includes/actions.inc 30 Nov 2007 09:20:27 -0000 1.6 +++ drupal-6.x-siren/includes/actions.inc 4 Dec 2007 07:56:07 -0000 @@ -54,7 +54,7 @@ function actions_do($action_ids, $object $where_values = array(); foreach ($action_ids as $action_id) { if (is_numeric($action_id)) { - $where[] = 'OR aid = %d'; + $where[] = 'OR [aid] = %d'; $where_values[] = $action_id; } elseif (isset($available_actions[$action_id])) { @@ -68,7 +68,7 @@ function actions_do($action_ids, $object $where_clause = implode(' ', $where); // Strip off leading 'OR '. $where_clause = '('. strstr($where_clause, " ") .')'; - $result_db = db_query('SELECT * FROM {actions} WHERE '. $where_clause, $where_values); + $result_db = db_query('SELECT * FROM [{actions}] WHERE '. $where_clause, $where_values); while ($action = db_fetch_object($result_db)) { $actions[$action->aid] = $action->parameters ? unserialize($action->parameters) : array(); $actions[$action->aid]['callback'] = $action->callback; @@ -93,7 +93,7 @@ function actions_do($action_ids, $object else { // If it's a configurable action, retrieve stored parameters. if (is_numeric($action_ids)) { - $action = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = %d", $action_ids)); + $action = db_fetch_object(db_query("SELECT * FROM [{actions}] WHERE [aid] = %d", $action_ids)); $function = $action->callback; $context = array_merge($context, unserialize($action->parameters)); $result[$action_ids] = $function($object, $context, $a1, $a2); @@ -177,7 +177,7 @@ function actions_list($reset = FALSE) { */ function actions_get_all_actions() { $actions = array(); - $result = db_query("SELECT * FROM {actions}"); + $result = db_query("SELECT * FROM [{actions}]"); while ($action = db_fetch_object($result)) { $actions[$action->aid] = array( 'callback' => $action->callback, @@ -238,7 +238,7 @@ function actions_function_lookup($hash) } // Must be an instance; must check database. - $aid = db_result(db_query("SELECT aid FROM {actions} WHERE MD5(aid) = '%s' AND parameters != ''", $hash)); + $aid = db_result(db_query("SELECT [aid] FROM [{actions}] WHERE MD5([aid]) = %s AND [parameters] != %s", $hash, '')); return $aid; } @@ -255,7 +255,7 @@ function actions_synchronize($actions_in $actions_in_code = actions_list(); } $actions_in_db = array(); - $result = db_query("SELECT * FROM {actions} WHERE parameters = ''"); + $result = db_query("SELECT * FROM [{actions}] WHERE [parameters] = %s", ''); while ($action = db_fetch_object($result)) { $actions_in_db[$action->callback] = array('aid' => $action->aid, 'description' => $action->description); } @@ -271,7 +271,7 @@ function actions_synchronize($actions_in } else { // This is a new singleton that we don't have an aid for; assign one. - db_query("INSERT INTO {actions} (aid, type, callback, parameters, description) VALUES ('%s', '%s', '%s', '%s', '%s')", $callback, $array['type'], $callback, '', $array['description']); + db_query("INSERT INTO [{actions}] ([aid], [type], [callback], [parameters], [description]) VALUES (%s, %s, %s, %s, %s)", $callback, $array['type'], $callback, '', $array['description']); watchdog('actions', "Action '%action' added.", array('%action' => filter_xss_admin($array['description']))); } } @@ -284,14 +284,14 @@ function actions_synchronize($actions_in foreach ($actions_in_db as $callback => $array) { $orphaned[] = $callback; - $placeholder[] = "'%s'"; + $placeholder[] = "%s"; } $orphans = implode(', ', $orphaned); if ($delete_orphans) { $placeholders = implode(', ', $placeholder); - $results = db_query("SELECT a.aid, a.description FROM {actions} a WHERE callback IN ($placeholders)", $orphaned); + $results = db_query("SELECT a.[aid], a.[description] FROM [{actions}] a WHERE [callback] IN ($placeholders)", $orphaned); while ($action = db_fetch_object($results)) { actions_delete($action->aid); watchdog('actions', "Removed orphaned action '%action' from database.", array('%action' => filter_xss_admin($action->description))); @@ -325,15 +325,15 @@ function actions_synchronize($actions_in function actions_save($function, $type, $params, $desc, $aid = NULL) { $serialized = serialize($params); if ($aid) { - db_query("UPDATE {actions} SET callback = '%s', type = '%s', parameters = '%s', description = '%s' WHERE aid = %d", $function, $type, $serialized, $desc, $aid); + db_query("UPDATE [{actions}] SET [callback] = %s, [type] = %s, [parameters] = %s, [description] = %s WHERE [aid] = %d", $function, $type, $serialized, $desc, $aid); watchdog('actions', 'Action %action saved.', array('%action' => $desc)); } else { // aid is the callback for singleton actions so we need to keep a // separate table for numeric aids. - db_query('INSERT INTO {actions_aid} VALUES (default)'); + db_query('INSERT INTO [{actions_aid}] VALUES (default)'); $aid = db_last_insert_id('actions_aid', 'aid'); - db_query("INSERT INTO {actions} (aid, callback, type, parameters, description) VALUES (%d, '%s', '%s', '%s', '%s')", $aid, $function, $type, $serialized, $desc); + db_query("INSERT INTO [{actions}] ([aid], [callback], [type], [parameters], [description]) VALUES (%d, %s, %s, %s, %s)", $aid, $function, $type, $serialized, $desc); watchdog('actions', 'Action %action created.', array('%action' => $desc)); } @@ -350,7 +350,7 @@ function actions_save($function, $type, * The appropriate action row from the database as an object. */ function actions_load($aid) { - return db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = %d", $aid)); + return db_fetch_object(db_query("SELECT * FROM [{actions}] WHERE [aid] = %d", $aid)); } /** @@ -360,6 +360,6 @@ function actions_load($aid) { * integer The ID of the action to delete. */ function actions_delete($aid) { - db_query("DELETE FROM {actions} WHERE aid = %d", $aid); + db_query("DELETE FROM [{actions}] WHERE [aid] = %d", $aid); module_invoke_all('actions_delete', $aid); } Index: drupal-6.x-siren/includes/batch.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/batch.inc,v retrieving revision 1.12 diff -u -p -r1.12 batch.inc --- drupal-6.x-siren/includes/batch.inc 15 Oct 2007 15:18:39 -0000 1.12 +++ drupal-6.x-siren/includes/batch.inc 4 Dec 2007 07:56:07 -0000 @@ -12,7 +12,7 @@ function _batch_page() { $batch =& batch_get(); // Retrieve the current state of batch from db. - if (isset($_REQUEST['id']) && $data = db_result(db_query("SELECT batch FROM {batch} WHERE bid = %d AND token = '%s'", $_REQUEST['id'], drupal_get_token($_REQUEST['id'])))) { + if (isset($_REQUEST['id']) && $data = db_result(db_query("SELECT [batch] FROM [{batch}] WHERE [bid] = %d AND [token] = %s", $_REQUEST['id'], drupal_get_token($_REQUEST['id'])))) { $batch = unserialize($data); } else { @@ -305,7 +305,7 @@ function _batch_finished() { // Cleanup the batch table and unset the global $batch variable. if ($batch['progressive']) { - db_query("DELETE FROM {batch} WHERE bid = %d", $batch['id']); + db_query("DELETE FROM [{batch}] WHERE [bid] = %d", $batch['id']); } $_batch = $batch; $batch = NULL; @@ -349,6 +349,6 @@ function _batch_finished() { */ function _batch_shutdown() { if ($batch = batch_get()) { - db_query("UPDATE {batch} SET batch = '%s' WHERE bid = %d", serialize($batch), $batch['id']); + db_query("UPDATE [{batch}] SET [batch] = %s WHERE [bid] = %d", serialize($batch), $batch['id']); } } Index: drupal-6.x-siren/includes/bootstrap.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v retrieving revision 1.201 diff -u -p -r1.201 bootstrap.inc --- drupal-6.x-siren/includes/bootstrap.inc 30 Nov 2007 12:19:10 -0000 1.201 +++ drupal-6.x-siren/includes/bootstrap.inc 4 Dec 2007 07:56:07 -0000 @@ -384,7 +384,7 @@ function drupal_get_filename($type, $nam // the database. This is required because this function is called both // before we have a database connection (i.e. during installation) and // when a database connection fails. - elseif (db_is_active() && (($file = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s' AND type = '%s'", $name, $type))) && file_exists($file))) { + elseif (db_is_active() && (($file = db_result(db_query("SELECT [filename] FROM [{system}] WHERE [name] = %s AND [type] = %s", $name, $type))) && file_exists($file))) { $files[$type][$name] = $file; } else { @@ -420,7 +420,7 @@ function variable_init($conf = array()) $variables = $cached->data; } else { - $result = db_query('SELECT * FROM {variable}'); + $result = db_query('SELECT * FROM [{variable}]'); while ($variable = db_fetch_object($result)) { $variables[$variable->name] = unserialize($variable->value); } @@ -463,9 +463,9 @@ function variable_set($name, $value) { global $conf; $serialized_value = serialize($value); - db_query("UPDATE {variable} SET value = '%s' WHERE name = '%s'", $serialized_value, $name); + db_query("UPDATE [{variable}] SET [value] = %s WHERE [name] = %s", $serialized_value, $name); if (!db_affected_rows()) { - @db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", $name, $serialized_value); + @db_query("INSERT INTO [{variable}] ([name], [value]) VALUES (%s, %s)", $name, $serialized_value); } cache_clear_all('variables', 'cache'); @@ -482,7 +482,7 @@ function variable_set($name, $value) { function variable_del($name) { global $conf; - db_query("DELETE FROM {variable} WHERE name = '%s'", $name); + db_query("DELETE FROM [{variable}] WHERE [name] = %s", $name); cache_clear_all('variables', 'cache'); unset($conf[$name]); @@ -823,14 +823,14 @@ function drupal_get_messages($type = NUL function drupal_is_denied($type, $mask) { // Because this function is called for every page request, both cached // and non-cached pages, we tried to optimize it as much as possible. - // We deny access if the only matching records in the {access} table have + // We deny access if the only matching records in the [{access}] table have // status 0. If any have status 1, or if there are no matching records, // we allow access. // We only select for records with status 0. If we have some of // these, we return 1 (denied). If no matching records or only ones // with status = 1, we get no return from db_result, so we return // (bool)NULL = 0 (allowed). - return (bool) db_result(db_query_range("SELECT 1 FROM {access} WHERE type = '%s' AND LOWER('%s') LIKE LOWER(mask) AND status = 0", $type, $mask, 0, 1)); + return (bool) db_result(db_query_range("SELECT 1 FROM [{access}] WHERE [type] = %s AND LOWER(%s) LIKE LOWER([mask]) AND [status] = 0", $type, $mask, 0, 1)); } /** @@ -1028,7 +1028,7 @@ function language_list($field = 'languag // Init language list if (!isset($languages)) { if (variable_get('language_count', 1) > 1 || module_exists('locale')) { - $result = db_query('SELECT * FROM {languages} ORDER BY weight ASC, name ASC'); + $result = db_query('SELECT * FROM [{languages}] ORDER BY [weight] ASC, [name] ASC'); while ($row = db_fetch_object($result)) { $languages['language'][$row->language] = $row; } Index: drupal-6.x-siren/includes/cache.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/cache.inc,v retrieving revision 1.16 diff -u -p -r1.16 cache.inc --- drupal-6.x-siren/includes/cache.inc 26 Nov 2007 16:19:37 -0000 1.16 +++ drupal-6.x-siren/includes/cache.inc 4 Dec 2007 07:56:07 -0000 @@ -18,11 +18,11 @@ function cache_get($cid, $table = 'cache $cache_flush = variable_get('cache_flush', 0); if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= time())) { // Time to flush old cache data - db_query("DELETE FROM {". $table ."} WHERE expire != %d AND expire <= %d", CACHE_PERMANENT, $cache_flush); + db_query("DELETE FROM [{". $table ."}] WHERE [expire] != %d AND [expire] <= %d", CACHE_PERMANENT, $cache_flush); variable_set('cache_flush', 0); } - $cache = db_fetch_object(db_query("SELECT data, created, headers, expire, serialized FROM {". $table ."} WHERE cid = '%s'", $cid)); + $cache = db_fetch_object(db_query("SELECT [data], [created], [headers], [expire], [serialized] FROM [{". $table ."}] WHERE [cid] = %s", $cid)); if (isset($cache->data)) { // If the data is permanent or we're not enforcing a minimum cache lifetime // always return the cached data. @@ -105,9 +105,17 @@ function cache_set($cid, $data, $table = $serialized = 1; } $created = time(); - db_query("UPDATE {". $table ."} SET data = %b, created = %d, expire = %d, headers = '%s', serialized = %d WHERE cid = '%s'", $data, $created, $expire, $headers, $serialized, $cid); + $values = array( + array('field' => 'data', 'placeholder' => '%b', 'data' => $data), + array('field' => 'created', 'placeholder' => '%d', 'data' => $created), + array('field' => 'expire', 'placeholder' => '%d', 'data' => $expire), + array('field' => 'headers', 'placeholder' => "%s", 'data' => $headers), + array('field' => 'serialized', 'placeholder' => '%d', 'data' => $serialized), + ); + db_query_update($table, $values, "[cid] = %s", $cid); if (!db_affected_rows()) { - @db_query("INSERT INTO {". $table ."} (cid, data, created, expire, headers, serialized) VALUES ('%s', %b, %d, %d, '%s', %d)", $cid, $data, $created, $expire, $headers, $serialized); + $values[] = array('field' => 'cid', 'placeholder' => "%s", 'data' => $cid); + db_query_insert($table, $values); } } @@ -156,26 +164,26 @@ function cache_clear_all($cid = NULL, $t else if (time() > ($cache_flush + variable_get('cache_lifetime', 0))) { // Clear the cache for everyone, cache_flush_delay seconds have // passed since the first request to clear the cache. - db_query("DELETE FROM {". $table ."} WHERE expire != %d AND expire < %d", CACHE_PERMANENT, time()); + db_query("DELETE FROM [{". $table ."}] WHERE [expire] != %d AND [expire] < %d", CACHE_PERMANENT, time()); variable_set('cache_flush', 0); } } else { // No minimum cache lifetime, flush all temporary cache entries now. - db_query("DELETE FROM {". $table ."} WHERE expire != %d AND expire < %d", CACHE_PERMANENT, time()); + db_query("DELETE FROM [{". $table ."}] WHERE [expire] != %d AND [expire] < %d", CACHE_PERMANENT, time()); } } else { if ($wildcard) { if ($cid == '*') { - db_query("DELETE FROM {". $table ."}"); + db_query("DELETE FROM [{". $table ."}]"); } else { - db_query("DELETE FROM {". $table ."} WHERE cid LIKE '%s%%'", $cid); + db_query("DELETE FROM [{". $table ."}] WHERE [cid] LIKE %s", $cid ."%"); } } else { - db_query("DELETE FROM {". $table ."} WHERE cid = '%s'", $cid); + db_query("DELETE FROM [{". $table ."}] WHERE [cid] = %s", $cid); } } } Index: drupal-6.x-siren/includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.728 diff -u -p -r1.728 common.inc --- drupal-6.x-siren/includes/common.inc 30 Nov 2007 15:31:13 -0000 1.728 +++ drupal-6.x-siren/includes/common.inc 4 Dec 2007 07:56:08 -0000 @@ -837,7 +837,7 @@ function valid_url($url, $absolute = FAL * The name of an event. */ function flood_register_event($name) { - db_query("INSERT INTO {flood} (event, hostname, timestamp) VALUES ('%s', '%s', %d)", $name, ip_address(), time()); + db_query("INSERT INTO [{flood}] ([event], [hostname], [timestamp]) VALUES (%s, %s, %d)", $name, ip_address(), time()); } /** @@ -854,7 +854,7 @@ function flood_register_event($name) { * True if the user did not exceed the hourly threshold. False otherwise. */ function flood_is_allowed($name, $threshold) { - $number = db_result(db_query("SELECT COUNT(*) FROM {flood} WHERE event = '%s' AND hostname = '%s' AND timestamp > %d", $name, ip_address(), time() - 3600)); + $number = db_result(db_query("SELECT COUNT(*) FROM [{flood}] WHERE [event] = %s AND [hostname] = %s AND [timestamp] > %d", $name, ip_address(), time() - 3600)); return ($number < $threshold ? TRUE : FALSE); } @@ -1817,7 +1817,7 @@ function drupal_add_js($data = NULL, $ty static $javascript = array(); if (isset($data)) { - + // Add jquery.js and drupal.js the first time a Javascript file is added. if (empty($javascript)) { $javascript['header'] = array( @@ -1828,7 +1828,7 @@ function drupal_add_js($data = NULL, $ty 'module' => array(), 'theme' => array(), 'setting' => array(), 'inline' => array(), ); } - + if (isset($scope) && !isset($javascript[$scope])) { $javascript[$scope] = array('core' => array(), 'module' => array(), 'theme' => array(), 'setting' => array(), 'inline' => array()); } @@ -1836,7 +1836,7 @@ function drupal_add_js($data = NULL, $ty if (isset($type) && isset($scope) && !isset($javascript[$scope][$type])) { $javascript[$scope][$type] = array(); } - + switch ($type) { case 'setting': $javascript[$scope][$type][] = $data; @@ -1851,7 +1851,7 @@ function drupal_add_js($data = NULL, $ty } if (isset($scope)) { - + if (isset($javascript[$scope])) { return $javascript[$scope]; } @@ -3242,7 +3242,9 @@ function _drupal_initialize_schema($modu **/ function drupal_schema_fields_sql($table, $prefix = NULL) { $schema = drupal_get_schema($table); - $fields = array_keys($schema['fields']); + foreach ($schema['fields'] as $key => $value) { + $fields[] = '['. $key .']'; + } if ($prefix) { $columns = array(); foreach ($fields as $field) { @@ -3267,7 +3269,7 @@ function drupal_schema_fields_sql($table * The object to write. This is a reference, as defaults according to * the schema may be filled in on the object, as well as ID on the serial * type(s). Both array an object types may be passed. - * @param update + * @param primary_keys * If this is an update, specify the primary keys' field names. It is the * caller's responsibility to know if a record for this object already * exists in the database. If there is only 1 key, you may pass a simple string. @@ -3276,19 +3278,15 @@ function drupal_schema_fields_sql($table * fields defined by the $table. For example, $object->nid will be populated * after inserting a new node. */ -function drupal_write_record($table, &$object, $update = array()) { - // Standardize $update to an array. - if (is_string($update)) { - $update = array($update); +function drupal_write_record($table, &$object, $primary_keys = array()) { + // Standardize $primary_keys to an array. + if (!is_array($primary_keys)) { + $primary_keys = array($primary_keys); } // Convert to an object if needed. - if (is_array($object)) { + if ($array = is_array($object)) { $object = (object) $object; - $array = TRUE; - } - else { - $array = FALSE; } $schema = drupal_get_schema($table); @@ -3296,18 +3294,18 @@ function drupal_write_record($table, &$o return FALSE; } - $fields = $defs = $values = $serials = array(); - + $values = array(); + $serials = array(); // Go through our schema, build SQL, and when inserting, fill in defaults for // fields that are not set. foreach ($schema['fields'] as $field => $info) { // Special case -- skip serial types if we are updating. - if ($info['type'] == 'serial' && count($update)) { + if ($info['type'] == 'serial' && count($primary_keys)) { continue; } // For inserts, populate defaults from Schema if not already provided - if (!isset($object->$field) && !count($update) && isset($info['default'])) { + if (!isset($object->$field) && !count($primary_keys) && isset($info['default'])) { $object->$field = $info['default']; } @@ -3320,42 +3318,38 @@ function drupal_write_record($table, &$o // Build arrays for the fields, placeholders, and values in our query. if (isset($object->$field)) { - $fields[] = $field; - $placeholders[] = db_type_placeholder($info['type']); + $value['field'] = $field; + $value['placeholder'] = db_type_placeholder($info['type']); if (empty($info['serialize'])) { - $values[] = $object->$field; + $value['data'] = $object->$field; } else { - $values[] = serialize($object->$field); + $value['data'] = serialize($object->$field); } + + $values[] = $value; } } // Build the SQL. - $query = ''; - if (!count($update)) { - $query = "INSERT INTO {". $table ."} (". implode(', ', $fields) .') VALUES ('. implode(', ', $placeholders) .')'; + if (!count($primary_keys)) { + db_query_insert($table, $values); $return = SAVED_NEW; } else { - $query = ''; - foreach ($fields as $id => $field) { - if ($query) { - $query .= ', '; + foreach ($primary_keys as $key => $value){ + // $primary_key is NOT in key-value pair format. + if (!isset($schema['fields'][$key]) && isset($schema['fields'][$value])) { + $key = $value; + $value = $object->$key; } - $query .= $field .' = '. $placeholders[$id]; + $conditions[] = "[$key] = ". db_type_placeholder($schema['fields'][$key]['type']); + $args[] = $value; } - - foreach ($update as $key){ - $conditions[] = "$key = ". db_type_placeholder($schema['fields'][$key]['type']); - $values[] = $object->$key; - } - - $query = "UPDATE {". $table ."} SET $query WHERE ". implode(' AND ', $conditions); + db_query_update($table, $values, implode(' AND ', $conditions), $args); $return = SAVED_UPDATED; } - db_query($query, $values); if ($serials) { // Get last insert ids and fill them in. @@ -3366,13 +3360,54 @@ function drupal_write_record($table, &$o // If we began with an array, convert back so we don't surprise the caller. if ($array) { - $object = (array)$object; + $object = (array) $object; } return $return; } /** + * Drop a record from the database based upon the schema. + * + * @param $table + * The name of the table; this must exist in schema API. + * @param $object + * The object to drop. This is a reference, as defaults according to + * the schema may be filled in on the object, as well as ID on the serial + * type(s). Both array an object types may be passed. + * @param primary_keys + * Specify the primary keys' field names. If there is only 1 key, you may + * pass a simple string. + * @return (boolean) Failure to write a record will return FALSE. Otherwise, + * TRUE is returned. + */ +function drupal_drop_record($table, $object, $primary_keys = array()) { + // Standardize $primary_keys to an array. + if (!is_array($primary_keys)) { + $primary_keys = array($primary_keys); + } + + // Convert to an object if needed. + if ($array = is_array($object)) { + $object = (object) $object; + } + + $schema = drupal_get_schema($table); + if (empty($schema)) { + return FALSE; + } + + // Execute the request. + foreach ($primary_keys as $key){ + $conditions[] = "[$key] = ". db_type_placeholder($schema['fields'][$key]['type']); + $args[] = $object->$key; + } + db_query_delete($table, implode(' AND ', $conditions), $args); + + return SAVED_DELETED; +} + +/** * @} End of "ingroup schemaapi". */ Index: drupal-6.x-siren/includes/common.mysql.inc =================================================================== RCS file: drupal-6.x-siren/includes/common.mysql.inc diff -N drupal-6.x-siren/includes/common.mysql.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ drupal-6.x-siren/includes/common.mysql.inc 4 Dec 2007 07:56:08 -0000 @@ -0,0 +1,385 @@ + 0) ? "CONCAT($return)" : ''; +} + +/** + * Returns a string that is the equivalent of MySQL IFNULL or Oracle NVL. + * + * @return + * If $expr1 is not NULL, returns $expr1; otherwise it returns $expr2. + */ +function db_if_null($expr1, $expr2) { + return " IFNULL($expr1, $expr2) "; +} + +/** + * Report database status. + */ +function db_status_report($phase) { + $t = get_t(); + + $version = db_version(); + + $form['mysql'] = array( + 'title' => $t('MySQL database'), + 'value' => ($phase == 'runtime') ? l($version, 'admin/reports/status/sql') : $version, + ); + + if (version_compare($version, DRUPAL_MINIMUM_MYSQL) < 0) { + $form['mysql']['severity'] = REQUIREMENT_ERROR; + $form['mysql']['description'] = $t('Your MySQL Server is too old. Drupal requires at least MySQL %version.', array('%version' => DRUPAL_MINIMUM_MYSQL)); + } + + return $form; +} + +/** + * Returns the version of the database server currently in use. + * + * @return Database server version + */ +function db_version() { + global $active_db; + list($version) = explode('-', db_result(db_query("SELECT VERSION();"))); + return $version; +} + +/** + * Insert a row of record into database. + * + * @param $table + * Table to insert. + * @param $values + * An array containing the insert values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_insert($table, $values) { + $fields = array(); + $placeholders = array(); + $data = array(); + foreach ($values as $value) { + $fields[] = $value['field']; + $placeholders[] = $value['placeholder']; + $data[] = $value['data']; + } + + if (!count($fields)) { + return FALSE; + } + + $query = "INSERT INTO [{". $table ."}] ([". implode('], [', $fields) ."]) VALUES (". implode(', ', $placeholders) .")"; + return db_query($query, $data); +} + +/** + * Update a row of record in database. + * + * @param $table + * Table to update. + * @param $values + * An array containing the update values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, 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: %d, %f and %s. + * + * 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_update($table, $values, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 3); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $fields = array(); + $data = array(); + foreach ($values as $value) { + $fields[] = '['. $value['field'] .'] = '. $value['placeholder']; + $data[] = $value['data']; + } + + if (!count($fields)) { + return FALSE; + } + + $query = "UPDATE [{". $table ."}] SET ". implode(', ', $fields); + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $data = array_merge($data, $args); + } + return db_query($query, $data); +} + +/** + * Delete a row of record from database. + * + * @param $table + * Table to delete. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, 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: %d, %f and %s. + * + * 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_delete($table, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 2); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $data = array(); + + $query = "DELETE FROM [{". $table ."}]"; + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $data = $args; + } + return db_query($query, $data); +} + +/** + * 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) { + return db_result(db_query('SELECT LAST_INSERT_ID()')); +} + +/** + * 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. The query arguments can be enclosed in one + * array instead. + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @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 .= ' LIMIT '. (int) $from .', '. (int) $count; + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * 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_affected_rows() does + * 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 %c (character large object). + * + * 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 .' Engine=HEAP SELECT', $query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * Lock a table. + */ +function db_lock_table($table) { + db_query('LOCK TABLES [{'. db_escape_table($table) .'}] WRITE'); +} + +/** + * Unlock all locked tables. + */ +function db_unlock_tables() { + db_query('UNLOCK TABLES'); +} + +/** + * Check if a table exists. + */ +function db_table_exists($table) { + return db_fetch_object(db_query("SHOW TABLES LIKE '{". db_escape_table($table) ."}'")) ? TRUE : FALSE; +} + +/** + * Check if a column exists in the given table. + */ +function db_column_exists($table, $column) { + return db_fetch_object(db_query("SHOW COLUMNS FROM [{%s}] LIKE %s", $table, $column)) ? TRUE : FALSE; +} + +/** + * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to + * the SELECT list entry of the given query and the resulting query is returned. + * This function only applies the wrapper if a DISTINCT doesn't already exist in + * the query. + * + * @param $table Table containing the field to set as DISTINCT + * @param $field Field to set as DISTINCT + * @param $query Query to apply the wrapper to + * @return SQL query with the DISTINCT wrapper surrounding the given table.field. + */ +function db_distinct_field($table, $field, $query) { + $field_to_select = 'DISTINCT('. $table .'.'. $field .')'; + // (? 30) { + // Try to fetch mapping, if not exists, set it up. + $trim = variable_get('oracle_' . $match, NULL); + if (!$trim) { + // Fetch last counter, and +1 for next mapping. + $count = variable_get('oracle_max30', 0) + 1; + variable_set('oracle_max30', $count); + // Setup mapping and reverse mapping. + $trim = substr($match, 0, 30 - strlen($count)) . $count; + variable_set('oracle_' . $match, $trim); + variable_set('oracle_' . $trim, $match); + $match = $trim; + } + } + return DB_QUOTE_OPERATOR . $match . DB_QUOTE_OPERATOR; +} + +/** + * Return a portably concatenate strings. + * + * @param ... + * Variable number of string parameters. + * @return + * Portably concatenate strings. + */ +function db_concat() { + $args = func_get_args(); + return implode(DB_CONCAT_OPERATOR, $args); +} + +/** + * Returns a string that is the equivalent of MySQL IFNULL or Oracle NVL. + * + * @return + * If $expr1 is not NULL, returns $expr1; otherwise it returns $expr2. + */ +function db_if_null($expr1, $expr2) { + return " NVL($expr1, $expr2) "; +} + +/** + * Report database status. + */ +function db_status_report($phase) { + $t = get_t(); + + $version = db_version(); + + $form['oci8'] = array( + 'title' => $t('Oracle database'), + 'value' => $version, + ); + + if (version_compare($version, DRUPAL_MINIMUM_OCI) < 0) { + $form['oci8']['severity'] = REQUIREMENT_ERROR; + $form['oci8']['description'] = $t('Your Oracle Server is too old. Drupal requires at least Oracle %version.', array('%version' => DRUPAL_MINIMUM_OCI)); + } + + return $form; +} + +/** + * Returns the version of the database server currently in use. + * + * @return Database server version + */ +function db_version() { + $banner = db_result(db_query('SELECT BANNER FROM SYS.V_$VERSION')); + preg_match('/\s([0-9.]+)\s/', $banner, $version); + return array_pop($version); +} + +/** + * Insert a row of record into database. + * + * @param $table + * Table to insert. + * @param $values + * An array containing the insert values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_insert($table, $values) { + $fields = array(); + $placeholders = array(); + $args = array(); + $lob_fields = array(); + $lob_placeholders = array(); + $lob_args = array(); + foreach ($values as $value) { + $fields[] = $value['field']; + switch ($value['placeholder']) { + case '%b': + $placeholders[] = 'EMPTY_BLOB()'; + $lob_fields[] = $value['field']; + $lob_placeholders[] = $value['placeholder']; + $lob_args[] = $value['data']; + break; + case '%c': + $placeholders[] = 'EMPTY_CLOB()'; + $lob_fields[] = $value['field']; + $lob_placeholders[] = $value['placeholder']; + $lob_args[] = $value['data']; + break; + default: + $placeholders[] = $value['placeholder']; + $args[] = $value['data']; + } + } + + $query = "INSERT INTO [{". $table ."}] ([". implode('], [', $fields) ."]) VALUES (". implode(', ', $placeholders) .")"; + if (count($lob_fields)) { + $query .= " RETURNING [". implode('], [', $lob_fields) ."] INTO ". implode(', ', $lob_placeholders); + $args = array_merge($args, $lob_args); + } + return db_query($query, $args); +} + +/** + * Update a row of record in database. + * + * @param $table + * Table to update. + * @param $values + * An array containing the update values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, 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: %d, %f and %s. + * + * 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_update($table, $values, $where_clause = NULL) { + global $active_db, $last_result, $queries; + + $where_args = func_get_args(); + $where_args = array_slice($where_args, 3); + if (isset($where_args[0]) and is_array($where_args[0])) { // 'All arguments in one array' syntax + $where_args = $where_args[0]; + } + + $fields = array(); + $args = array(); + $lob_fields = array(); + $lob_placeholders = array(); + $lob_args = array(); + foreach ($values as $value) { + switch ($value['placeholder']) { + case '%b': + $fields[] = '['. $value['field'] .'] = EMPTY_BLOB()'; + $lob_fields[] = $value['field']; + $lob_placeholders[] = $value['placeholder']; + $lob_args[] = $value['data']; + break; + case '%c': + $fields[] = '['. $value['field'] .'] = EMPTY_CLOB()'; + $lob_fields[] = $value['field']; + $lob_placeholders[] = $value['placeholder']; + $lob_args[] = $value['data']; + break; + default: + $fields[] = '['. $value['field'] .'] = '. $value['placeholder']; + $args[] = $value['data']; + } + } + + $query = "UPDATE [{". $table ."}] SET ". implode(', ', $fields); + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $args = array_merge($args, $where_args); + } + if (count($lob_fields)) { + $query .= " RETURNING [". implode('], [', $lob_fields) ."] INTO ". implode(', ', $lob_placeholders); + $args = array_merge($args, $lob_args); + } + return db_query($query, $args); +} + +/** + * Delete a row of record from database. + * + * @param $table + * Table to delete. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, 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: %d, %f and %s. + * + * 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_delete($table, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 2); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $query['query'] = "DELETE FROM [{". $table ."}]"; + if ($where_clause) { + $query['query'] .= " WHERE ". $where_clause; + } + return db_query($query, $args); +} + +/** + * Returns the last insert id. This function is thread safe. + * + * @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) { + return db_result(db_query("SELECT [seq_{" . $table . "}_" . $field . "].CURRVAL FROM DUAL")); +} + +/** + * 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. 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 %c (character large object). + * + * NOTE: use NULL as arguments substitution for %b and %c. This will be + * replaced as corresponding empty LOB value placeholder, based on the + * database specific representation. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @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 = 'SELECT * FROM (SELECT [sub1].*, ROWNUM AS [line2] FROM ('. $query .') [sub1]) WHERE [line2] BETWEEN '. ($from + 1) .' AND '. ($from + $count); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * 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_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 %c (character large object). + * + * NOTE: use NULL as arguments substitution for %b and %c. This will be + * replaced as corresponding empty LOB value placeholder, based on the + * database specific representation. + * + * 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 GLOBAL TEMPORARY TABLE ['. $tablename .'] ON COMMIT PRESERVE ROWS AS SELECT', $query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * Lock a table. + * This function automatically starts a transaction. + */ +function db_lock_table($table) { + db_query('LOCK TABLE [{'. db_escape_table($table) .'}] IN EXCLUSIVE MODE'); +} + +/** + * Unlock all locked tables. + * This function automatically commits a transaction. + */ +function db_unlock_tables() { + global $active_db; + oci_commit($active_db); +} + +/** + * Check if a table exists. + */ +function db_table_exists($table) { + return db_result(db_query("SELECT COUNT(TABLE_NAME) FROM USER_TABLES WHERE TABLE_NAME LIKE '{" . db_escape_table($table) . "}'")) ? TRUE : FALSE; +} + +/** + * Check if a column exists in the given table. + */ +function db_column_exists($table, $column) { + return db_result(db_query("SELECT COUNT(COLUMN_NAME) FROM USER_TAB_COLS WHERE TABLE_NAME LIKE '{". db_escape_table($table) ."}' AND COLUMN_NAME LIKE '". trim($column) ."'")) ? TRUE : FALSE; +} + +/** + * Check if constraint exists in the given table. + */ +function db_constraint_exists($table, $fields) { + $queries = array(); + foreach ($fields as $key => $value) { + $queries[] = "SELECT CONSTRAINT_NAME FROM USER_CONS_COLUMNS WHERE TABLE_NAME = '{" . $table . "}' AND COLUMN_NAME = '" . $value . "'"; + } + return db_result(db_query(implode(' INTERSECT ', $queries))) ? TRUE : FALSE; +} + +/** + * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to + * the SELECT list entry of the given query and the resulting query is returned. + * This function only applies the wrapper if a DISTINCT doesn't already exist in + * the query. + * + * @param $table Table containing the field to set as DISTINCT + * @param $field Field to set as DISTINCT + * @param $query Query to apply the wrapper to + * @return SQL query with the DISTINCT wrapper surrounding the given table.field. + */ +function db_distinct_field($table, $field, $query) { + $field_to_select = 'DISTINCT ('. $table .'.'. $field .')'; + // (? $t('PostgreSQL database'), + 'value' => $version, + ); + + if (version_compare($version, DRUPAL_MINIMUM_PGSQL) < 0) { + $form['pgsql']['severity'] = REQUIREMENT_ERROR; + $form['pgsql']['description'] = $t('Your PostgreSQL Server is too old. Drupal requires at least PostgreSQL %version.', array('%version' => DRUPAL_MINIMUM_PGSQL)); + } + + return $form; +} + +/** + * Returns the version of the database server currently in use. + * + * @return Database server version + */ +function db_version() { + return db_result(db_query("SHOW SERVER_VERSION")); +} + +/** + * Insert a row of record into database. + * + * @param $table + * Table to insert. + * @param $values + * An array containing the insert values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_insert($table, $values) { + $fields = array(); + $placeholders = array(); + $data = array(); + foreach ($values as $value) { + $fields[] = $value['field']; + $placeholders[] = $value['placeholder']; + $data[] = $value['data']; + } + + if (!count($fields)) { + return FALSE; + } + + $query = "INSERT INTO [{". $table ."}] ([". implode('], [', $fields) ."]) VALUES (". implode(', ', $placeholders) .")"; + return db_query($query, $data); +} + +/** + * Update a row of record in database. + * + * @param $table + * Table to update. + * @param $values + * An array containing the update values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, 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: %d, %f and %s. + * + * 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_update($table, $values, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 3); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $fields = array(); + $data = array(); + foreach ($values as $value) { + $fields[] = '['. $value['field'] .'] = '. $value['placeholder']; + $data[] = $value['data']; + } + + if (!count($fields)) { + return FALSE; + } + + $query = "UPDATE [{". $table ."}] SET ". implode(', ', $fields); + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $data = array_merge($data, $args); + } + return db_query($query, $data); +} + +/** + * Delete a row of record from database. + * + * @param $table + * Table to delete. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, 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: %d, %f and %s. + * + * 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_delete($table, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 2); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $data = array(); + + $query = "DELETE FROM [{". $table ."}]"; + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $data = $args; + } + return db_query($query, $data); +} + +/** + * Returns the last insert id. This function is thread safe. + * + * @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) { + return db_result(db_query("SELECT CURRVAL(%s)", db_prefix_tables('{'. $table .'}') .'_'. $field .'_seq')); +} + +/** + * 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. 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 %c (character large object). + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @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 .= ' LIMIT '. (int) $count .' OFFSET '. (int) $from; + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * 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_affected_rows() does + * 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 %c (character large object). + * + * 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', $query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * Lock a table. + * This function automatically starts a transaction. + */ +function db_lock_table($table) { + db_query('LOCK TABLE [{'. db_escape_table($table) .'}] IN EXCLUSIVE MODE'); +} + +/** + * Unlock all locked tables. + * This function automatically commits a transaction. + */ +function db_unlock_tables() { + db_query('COMMIT'); +} + +/** + * Check if a table exists. + */ +function db_table_exists($table) { + return db_result(db_query("SELECT 1 FROM [pg_class] WHERE [relname] = '{". db_escape_table($table) ."}'")) ? TRUE : FALSE; +} + +/** + * Check if a column exists in the given table. + */ +function db_column_exists($table, $column) { + return db_result(db_query("SELECT 1 FROM [pg_class], [pg_attribute] WHERE [pg_attribute].[attrelid] = [pg_class].[oid] AND [pg_class].[relname] = '{". db_escape_table($table) ."}' AND [attname] = %s", $column)) ? TRUE : FALSE; +} + +/** + * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to + * the SELECT list entry of the given query and the resulting query is returned. + * This function only applies the wrapper if a DISTINCT doesn't already exist in + * the query. + * + * @param $table Table containing the field to set as DISTINCT + * @param $field Field to set as DISTINCT + * @param $query Query to apply the wrapper to + * @return SQL query with the DISTINCT wrapper surrounding the given table.field. + */ +function db_distinct_field($table, $field, $query) { + $field_to_select = 'DISTINCT ON ('. $table .'.'. $field .") $table.$field"; + // (?PostgreSQL documentation.', array('%encoding' => $encoding, '@url' => 'http://www.postgresql.org/docs/7.4/interactive/multibyte.html')), 'status'); + } +} + +/** + * @} End of "ingroup database". + */ Index: drupal-6.x-siren/includes/database.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.inc,v retrieving revision 1.85 diff -u -p -r1.85 database.inc --- drupal-6.x-siren/includes/database.inc 30 Nov 2007 12:19:10 -0000 1.85 +++ drupal-6.x-siren/includes/database.inc 4 Dec 2007 07:56:08 -0000 @@ -139,7 +139,8 @@ function db_set_active($name = 'default' $connect_url = $db_url; } - $db_type = substr($connect_url, 0, strpos($connect_url, '://')); + $_connect_url = parse_url($connect_url); + $db_type = $_connect_url['fragment']; $handler = "./includes/database.$db_type.inc"; if (is_file($handler)) { @@ -148,7 +149,7 @@ function db_set_active($name = 'default' else { drupal_maintenance_theme(); drupal_set_title('Unsupported database type'); - print theme('maintenance_page', '

The database type '. theme('placeholder', $db_type) .' is unsupported. Please use either mysql for MySQL 3.x & 4.0.x databases, mysqli for MySQL 4.1.x+ databases, or pgsql for PostgreSQL databases. The database information is in your settings.php file.

+ print theme('maintenance_page', '

The database type '. theme('placeholder', $db_type) .' is unsupported. Please use either mysql for MySQL 3.x & 4.0.x databases, mysqli for MySQL 4.1.x+ databases, pdo_mysql for MySQL 3.x/4.x/5.x databases with PHP PDO driver, pgsql for PostgreSQL databases, pdo_pgsql for PostgreSQL databases with PHP PDO driver, or oci8 for Oracle 10gR2+. The database information is in your settings.php file.

For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.

'); exit; } @@ -175,23 +176,30 @@ function db_is_active() { * Helper function for db_query(). */ function _db_query_callback($match, $init = FALSE) { - static $args = NULL; + static $args = NULL, $ident = NULL, $count = 0; if ($init) { - $args = $match; - return; + if ($match) { + $count = 0; + $ident = substr(md5($match['query']), 1, 8); + $args = array_values($match['args']); + return; + } + return $args; } + $current = $count++; + $locator = ":l". $ident . $current; switch ($match[1]) { - case '%d': // We must use type casting to int to convert FALSE/NULL/(TRUE?) - return (int) array_shift($args); // We don't need db_escape_string as numbers are db-safe - case '%s': - return db_escape_string(array_shift($args)); - case '%%': - return '%'; + case '%d': + return db_escape_decimal($args[$current], $locator); case '%f': - return (float) array_shift($args); - case '%b': // binary data - return db_encode_blob(array_shift($args)); + return db_escape_float($args[$current], $locator); + case '%s': + return db_escape_string($args[$current], $locator); + case '%b': // Binary Large OBject. + return db_encode_blob($args[$current], $locator); + case '%c': // Character Large OBject. + return db_encode_clob($args[$current], $locator); } } @@ -214,7 +222,7 @@ function db_placeholders($arguments, $ty /** * Indicates the place holders that should be replaced in _db_query_callback(). */ -define('DB_QUERY_REGEXP', '/(%d|%s|%%|%f|%b)/'); +define('DB_QUERY_REGEXP', '/(%d|%f|%s|%b|%c)/'); /** * Helper function for db_rewrite_sql. @@ -235,7 +243,7 @@ define('DB_QUERY_REGEXP', '/(%d|%s|%%|%f * @return * An array: join statements, where statements, field or DISTINCT(field). */ -function _db_rewrite_sql($query = '', $primary_table = 'n', $primary_field = 'nid', $args = array()) { +function _db_rewrite_sql($query = '', $primary_table = 'n', $primary_field = '[nid]', $args = array()) { $where = array(); $join = array(); $distinct = FALSE; @@ -278,7 +286,7 @@ function _db_rewrite_sql($query = '', $p * @return * The original query with JOIN and WHERE statements inserted from hook_db_rewrite_sql implementations. nid is rewritten if needed. */ -function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array()) { +function db_rewrite_sql($query, $primary_table = 'n', $primary_field = '[nid]', $args = array()) { list($join, $where, $distinct) = _db_rewrite_sql($query, $primary_table, $primary_field, $args); if ($distinct) { @@ -500,15 +508,7 @@ function db_type_placeholder($type) { case 'varchar': case 'text': case 'datetime': - return '\'%s\''; - case 'numeric': - // For 'numeric' values, we use '%s', not '\'%s\'' as with - // string types, because numeric values should not be enclosed - // in quotes in queries (though they can be, at least on mysql - // and pgsql). Numerics should only have [0-9.+-] and - // presumably no db's "escape string" function will mess with - // those characters. return '%s'; case 'serial': @@ -520,6 +520,9 @@ function db_type_placeholder($type) { case 'blob': return '%b'; + + case 'clob': + return '%c'; } // There is no safe value to return here, so return something that Index: drupal-6.x-siren/includes/database.mysql-common.inc =================================================================== RCS file: drupal-6.x-siren/includes/database.mysql-common.inc diff -N drupal-6.x-siren/includes/database.mysql-common.inc --- drupal-6.x-siren/includes/database.mysql-common.inc 2 Oct 2007 16:15:56 -0000 1.13 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,532 +0,0 @@ - $field) { - $sql .= _db_create_field_sql($field_name, _db_process_field($field)) .", \n"; - } - - // Process keys & indexes. - $keys = _db_create_keys_sql($table); - if (count($keys)) { - $sql .= implode(", \n", $keys) .", \n"; - } - - // Remove the last comma and space. - $sql = substr($sql, 0, -3) ."\n) "; - - $sql .= $table['mysql_suffix']; - - return array($sql); -} - -function _db_create_keys_sql($spec) { - $keys = array(); - - if (!empty($spec['primary key'])) { - $keys[] = 'PRIMARY KEY ('. _db_create_key_sql($spec['primary key']) .')'; - } - if (!empty($spec['unique keys'])) { - foreach ($spec['unique keys'] as $key => $fields) { - $keys[] = 'UNIQUE KEY '. $key .' ('. _db_create_key_sql($fields) .')'; - } - } - if (!empty($spec['indexes'])) { - foreach ($spec['indexes'] as $index => $fields) { - $keys[] = 'INDEX '. $index .' ('. _db_create_key_sql($fields) .')'; - } - } - - return $keys; -} - -function _db_create_key_sql($fields) { - $ret = array(); - foreach ($fields as $field) { - if (is_array($field)) { - $ret[] = $field[0] .'('. $field[1] .')'; - } - 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['mysql_type'])) { - $map = db_type_map(); - $field['mysql_type'] = $map[$field['type'] .':'. $field['size']]; - } - - if ($field['type'] == 'serial') { - $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) { - $sql = "`". $name ."` ". $spec['mysql_type']; - - if (isset($spec['length'])) { - $sql .= '('. $spec['length'] .')'; - } - elseif (isset($spec['precision']) && isset($spec['scale'])) { - $sql .= '('. $spec['scale'] .', '. $spec['precision'] .')'; - } - - if (!empty($spec['unsigned'])) { - $sql .= ' unsigned'; - } - - if (!empty($spec['not null'])) { - $sql .= ' NOT NULL'; - } - - if (!empty($spec['auto_increment'])) { - $sql .= ' auto_increment'; - } - - 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. - $map = array( - 'varchar:normal' => 'VARCHAR', - - 'text:tiny' => 'SMALLTEXT', - 'text:small' => 'SMALLTEXT', - 'text:medium' => 'MEDIUMTEXT', - 'text:big' => 'LONGTEXT', - 'text:normal' => 'TEXT', - - 'serial:tiny' => 'TINYINT', - 'serial:small' => 'SMALLINT', - 'serial:medium' => 'MEDIUMINT', - 'serial:big' => 'BIGINT', - 'serial:normal' => 'INT', - - 'int:tiny' => 'TINYINT', - 'int:small' => 'SMALLINT', - 'int:medium' => 'MEDIUMINT', - 'int:big' => 'BIGINT', - 'int:normal' => 'INT', - - 'float:tiny' => 'FLOAT', - 'float:small' => 'FLOAT', - 'float:medium' => 'FLOAT', - 'float:big' => 'DOUBLE', - 'float:normal' => 'FLOAT', - - 'numeric:normal' => 'NUMERIC', - - 'blob:big' => 'LONGBLOB', - 'blob:normal' => 'BLOB', - - 'datetime:normal' => 'DATETIME', - ); - 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. - * The specification may also contain the key 'initial', the newly - * created field will be set to the value of the key in all rows. - * This is most useful for creating NOT NULL columns with no default - * value in existing tables. - * @param $keys_new - * Optional keys and indexes specification to be created on the - * table along with adding the field. The format is the same as a - * table specification but without the 'fields' element. If you are - * adding a type 'serial' field, you MUST specify at least one key - * or index including it in this array. @see db_change_field for more - * explanation why. - */ -function db_add_field(&$ret, $table, $field, $spec, $keys_new = array()) { - $fixnull = FALSE; - if (!empty($spec['not null']) && !isset($spec['default'])) { - $fixnull = TRUE; - $spec['not null'] = FALSE; - } - $query = 'ALTER TABLE {'. $table .'} ADD '; - $query .= _db_create_field_sql($field, _db_process_field($spec)); - if (count($keys_new)) { - $query .= ', ADD '. implode(', ADD ', _db_create_keys_sql($keys_new)); - } - $ret[] = update_sql($query); - if (isset($spec['initial'])) { - // All this because update_sql does not support %-placeholders. - $sql = 'UPDATE {'. $table .'} SET '. $field .' = '. db_type_placeholder($spec['type']); - $result = db_query($sql, $spec['initial']); - $ret[] = array('success' => $result !== FALSE, 'query' => check_plain($sql .' ('. $spec['initial'] .')')); - } - if ($fixnull) { - $spec['not null'] = TRUE; - db_change_field($ret, $table, $field, $field, $spec); - } -} - -/** - * 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 .'} ALTER COLUMN '. $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 .'} ALTER COLUMN '. $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('ALTER TABLE {'. $table .'} ADD UNIQUE KEY '. - $name .' ('. _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('ALTER TABLE {'. $table .'} DROP KEY '. $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) { - $query = 'ALTER TABLE {'. $table .'} ADD INDEX '. $name .' ('. _db_create_key_sql($fields) .')'; - $ret[] = update_sql($query); -} - -/** - * 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('ALTER TABLE {'. $table .'} DROP INDEX '. $name); -} - -/** - * Change a field definition. - * - * IMPORTANT NOTE: To maintain database portability, you have to explicitly - * recreate all indices and primary keys that are using the changed field. - * - * That means that you have to drop all affected keys and indexes with - * db_drop_{primary_key,unique_key,index}() before calling db_change_field(). - * To recreate the keys and indices, pass the key definitions as the - * optional $keys_new argument directly to db_change_field(). - * - * For example, suppose you have: - * @code - * $schema['foo'] = array( - * 'fields' => array( - * 'bar' => array('type' => 'int', 'not null' => TRUE) - * ), - * 'primary key' => array('bar') - * ); - * @endcode - * and you want to change foo.bar to be type serial, leaving it as the - * primary key. The correct sequence is: - * @code - * db_drop_primary_key($ret, 'foo'); - * db_change_field($ret, 'foo', 'bar', 'bar', - * array('type' => 'serial', 'not null' => TRUE), - * array('primary key' => array('bar'))); - * @endcode - * - * The reasons for this are due to the different database engines: - * - * On PostgreSQL, changing a field definition involves adding a new field - * and dropping an old one which* causes any indices, primary keys and - * sequences (from serial-type fields) that use the changed field to be dropped. - * - * On MySQL, all type 'serial' fields must be part of at least one key - * or index as soon as they are created. You cannot use - * db_add_{primary_key,unique_key,index}() for this purpose because - * the ALTER TABLE command will fail to add the column without a key - * or index specification. The solution is to use the optional - * $keys_new argument to create the key or index at the same time as - * field. - * - * You could use db_add_{primary_key,unique_key,index}() in all cases - * unless you are converting a field to be type serial. You can use - * the $keys_new argument in all cases. - * - * @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. - * @param $keys_new - * Optional keys and indexes specification to be created on the - * table along with changing the field. The format is the same as a - * table specification but without the 'fields' element. - */ - -function db_change_field(&$ret, $table, $field, $field_new, $spec, $keys_new = array()) { - $sql = 'ALTER TABLE {'. $table .'} CHANGE '. $field .' '. - _db_create_field_sql($field_new, _db_process_field($spec)); - if (count($keys_new)) { - $sql .= ', ADD '.implode(', ADD ', _db_create_keys_sql($keys_new)); - } - $ret[] = update_sql($sql); -} - -/** - * 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) { - return db_result(db_query('SELECT LAST_INSERT_ID()')); -} Index: drupal-6.x-siren/includes/database.mysql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.mysql.inc,v retrieving revision 1.83 diff -u -p -r1.83 database.mysql.inc --- drupal-6.x-siren/includes/database.mysql.inc 20 Oct 2007 21:57:49 -0000 1.83 +++ drupal-6.x-siren/includes/database.mysql.inc 4 Dec 2007 07:56:08 -0000 @@ -11,48 +11,18 @@ * @{ */ -// Include functions shared between mysql and mysqli. -require_once './includes/database.mysql-common.inc'; +// Include functions shared between mysql, mysqli and pdo_mysql. +require_once './includes/common.mysql.inc'; -/** - * Report database status. - */ -function db_status_report($phase) { - $t = get_t(); - - $version = db_version(); - - $form['mysql'] = array( - 'title' => $t('MySQL database'), - 'value' => ($phase == 'runtime') ? l($version, 'admin/reports/status/sql') : $version, - ); - - if (version_compare($version, DRUPAL_MINIMUM_MYSQL) < 0) { - $form['mysql']['severity'] = REQUIREMENT_ERROR; - $form['mysql']['description'] = $t('Your MySQL Server is too old. Drupal requires at least MySQL %version.', array('%version' => DRUPAL_MINIMUM_MYSQL)); - } - - return $form; -} - -/** - * Returns the version of the database server currently in use. - * - * @return Database server version - */ -function db_version() { - list($version) = explode('-', mysql_get_server_info()); - return $version; -} +// Include schema API shared between mysql, mysqli and pdo_mysql. +require_once './includes/schema.mysql.inc'; /** * Initialize a database connection. */ function db_connect($url) { - $url = parse_url($url); - // Check if MySQL support is present in PHP - if (!function_exists('mysql_connect')) { + if (!(function_exists('mysql_connect') && extension_loaded('mysql'))) { drupal_maintenance_theme(); drupal_set_title('PHP MySQL support not enabled'); print theme('maintenance_page', '

We were unable to use the MySQL database because the MySQL extension for PHP is not installed. Check your PHP.ini to see how you can enable it.

@@ -60,6 +30,8 @@ function db_connect($url) { exit; } + $url = parse_url($url); + // Decode url-encoded information in the db connection string $url['user'] = urldecode($url['user']); // Test if database url has a password. @@ -125,6 +97,43 @@ function db_connect($url) { } /** + * 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 %c (character large object). + * + * 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); + $query = db_escape_quote($query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + _db_query_callback(array('query' => $query, 'args' => $args), TRUE); + $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); + return _db_query($query); +} + +/** * Helper function for db_query(). */ function _db_query($query, $debug = 0) { @@ -237,94 +246,26 @@ function db_affected_rows() { return mysql_affected_rows($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. 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 $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. +/* + * Prepare user input for use in a database query, preventing SQL injection attacks. */ -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)$from .', '. (int)$count; - return _db_query($query); +function db_escape_decimal($data) { + return (int) $data; } /** - * 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_affected_rows() does - * 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. + * Prepare user input for use in a database query, preventing SQL injection attacks. */ -function db_query_temporary($query) { - $args = func_get_args(); - $tablename = array_pop($args); - array_shift($args); +function db_escape_float($data) { + return (float) $data; +} - $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' Engine=HEAP 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); +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + */ +function db_escape_string($data) { + global $active_db; + return "'". mysql_real_escape_string($data, $active_db) ."'"; } /** @@ -333,7 +274,7 @@ function db_query_temporary($query) { * @param $data * Data to encode. * @return - * Encoded data. + * Encoded data. */ function db_encode_blob($data) { global $active_db; @@ -346,63 +287,35 @@ function db_encode_blob($data) { * @param $data * Data to decode. * @return - * Decoded data. + * Decoded data. */ function db_decode_blob($data) { return $data; } /** - * Prepare user input for use in a database query, preventing SQL injection attacks. + * Returns a properly formatted Character Large OBject value. + * + * @param $data + * Data to encode. + * @return + * Encoded data. */ -function db_escape_string($text) { +function db_encode_clob($data) { global $active_db; - return mysql_real_escape_string($text, $active_db); -} - -/** - * Lock a table. - */ -function db_lock_table($table) { - db_query('LOCK TABLES {'. db_escape_table($table) .'} WRITE'); -} - -/** - * Unlock all locked tables. - */ -function db_unlock_tables() { - db_query('UNLOCK TABLES'); -} - -/** - * Check if a table exists. - */ -function db_table_exists($table) { - return db_fetch_object(db_query("SHOW TABLES LIKE '{". db_escape_table($table) ."}'")) ? TRUE : FALSE; -} - -/** - * Check if a column exists in the given table. - */ -function db_column_exists($table, $column) { - return db_fetch_object(db_query("SHOW COLUMNS FROM {%s} LIKE '%s'", $table, $column)) ? TRUE : FALSE; + return "'". mysql_real_escape_string($data, $active_db) ."'"; } /** - * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to - * the SELECT list entry of the given query and the resulting query is returned. - * This function only applies the wrapper if a DISTINCT doesn't already exist in - * the query. + * Returns text from a Character Large Object value. * - * @param $table Table containing the field to set as DISTINCT - * @param $field Field to set as DISTINCT - * @param $query Query to apply the wrapper to - * @return SQL query with the DISTINCT wrapper surrounding the given table.field. + * @param $data + * Data to decode. + * @return + * Decoded data. */ -function db_distinct_field($table, $field, $query) { - $field_to_select = 'DISTINCT('. $table .'.'. $field .')'; - // (? $t('MySQL database'), - 'value' => ($phase == 'runtime') ? l($version, 'admin/reports/status/sql') : $version, - ); - - if (version_compare($version, DRUPAL_MINIMUM_MYSQL) < 0) { - $form['mysql']['severity'] = REQUIREMENT_ERROR; - $form['mysql']['description'] = $t('Your MySQL Server is too old. Drupal requires at least MySQL %version.', array('%version' => DRUPAL_MINIMUM_MYSQL)); - } - - return $form; -} - -/** - * Returns the version of the database server currently in use. - * - * @return Database server version - */ -function db_version() { - global $active_db; - list($version) = explode('-', mysqli_get_server_info($active_db)); - return $version; -} +// Include schema API shared between mysql, mysqli and pdo_mysql. +require_once './includes/schema.mysql.inc'; /** * Initialise a database connection. @@ -57,7 +28,7 @@ function db_version() { */ function db_connect($url) { // Check if MySQLi support is present in PHP - if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) { + if (!(function_exists('mysqli_init') && extension_loaded('mysqli'))) { drupal_maintenance_theme(); drupal_set_title('PHP MySQLi support not enabled'); print theme('maintenance_page', '

We were unable to use the MySQLi database because the MySQLi extension for PHP is not installed. Check your PHP.ini to see how you can enable it.

@@ -125,6 +96,43 @@ function db_connect($url) { } /** + * 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 %c (character large object). + * + * 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); + $query = db_escape_quote($query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + _db_query_callback(array('query' => $query, 'args' => $args), TRUE); + $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); + return _db_query($query); +} + +/** * Helper function for db_query(). */ function _db_query($query, $debug = 0) { @@ -239,94 +247,26 @@ function db_affected_rows() { return mysqli_affected_rows($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. 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 $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. +/* + * Prepare user input for use in a database query, preventing SQL injection attacks. */ -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)$from .', '. (int)$count; - return _db_query($query); +function db_escape_decimal($data) { + return (int) $data; } /** - * 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_affected_rows() does - * 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. + * Prepare user input for use in a database query, preventing SQL injection attacks. */ -function db_query_temporary($query) { - $args = func_get_args(); - $tablename = array_pop($args); - array_shift($args); +function db_escape_float($data) { + return (float) $data; +} - $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' Engine=HEAP 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); +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + */ +function db_escape_string($data) { + global $active_db; + return "'". mysqli_real_escape_string($active_db, $data) ."'"; } /** @@ -335,7 +275,7 @@ function db_query_temporary($query) { * @param $data * Data to encode. * @return - * Encoded data. + * Encoded data. */ function db_encode_blob($data) { global $active_db; @@ -343,71 +283,42 @@ function db_encode_blob($data) { } /** - * Returns text from a Binary Large OBject value. + * Returns text from a Binary Large Object value. * * @param $data * Data to decode. * @return - * Decoded data. + * Decoded data. */ function db_decode_blob($data) { return $data; } /** - * Prepare user input for use in a database query, preventing SQL injection attacks. + * Returns a properly formatted Character Large OBject value. + * + * @param $data + * Data to encode. + * @return + * Encoded data. */ -function db_escape_string($text) { +function db_encode_clob($data) { global $active_db; - return mysqli_real_escape_string($active_db, $text); -} - -/** - * Lock a table. - */ -function db_lock_table($table) { - db_query('LOCK TABLES {'. db_escape_table($table) .'} WRITE'); -} - -/** - * Unlock all locked tables. - */ -function db_unlock_tables() { - db_query('UNLOCK TABLES'); -} - -/** - * Check if a table exists. - */ -function db_table_exists($table) { - return db_fetch_object(db_query("SHOW TABLES LIKE '{". db_escape_table($table) ."}'")) ? TRUE : FALSE; -} - -/** - * Check if a column exists in the given table. - */ -function db_column_exists($table, $column) { - return db_fetch_object(db_query("SHOW COLUMNS FROM {%s} LIKE '%s'", $table, $column)) ? TRUE : FALSE; + return "'". mysqli_real_escape_string($active_db, $data) ."'"; } /** - * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to - * the SELECT list entry of the given query and the resulting query is returned. - * This function only applies the wrapper if a DISTINCT doesn't already exist in - * the query. + * Returns text from a Character Large Object value. * - * @param $table Table containing the field to set as DISTINCT - * @param $field Field to set as DISTINCT - * @param $query Query to apply the wrapper to - * @return SQL query with the DISTINCT wrapper surrounding the given table.field. + * @param $data + * Data to decode. + * @return + * Decoded data. */ -function db_distinct_field($table, $field, $query) { - $field_to_select = 'DISTINCT('. $table .'.'. $field .')'; - // (?
");
+  print_r($msg);
+  print("
"); +} + +function _debug_query($query) { + //_print($query); + + if (preg_match('/[^\[\'{a-z0-9_:]([a-z0-9_{}]{3,})[^\]\'}a-z0-9_]/Ds', $query, $matches) && !preg_match('/[0-9]/', $matches[1])) { + _print("NO []: ". $query); + _print($matches); + } + if (preg_match("/'%s'/", $query)) { + _print("OLD '%s': ". $query); + } + if (preg_match("/[ ,]''[ ,]/", $query)) { + _print("EMPTY STRING '': ". $query); + } +} + +/** + * @file + * Database interface code for Oracle database servers. + */ + +/** + * Indicates the maximum size of last_results pool. We will free old + * statements which exists this limit, in order to prevent ORA-01000 error. + */ +define('OCI8_MAX_LAST_RESULTS', 256); + +/** + * Indicates the empty string placeholder. + */ +define('OCI8_EMPTY_STRING_PLACEHOLDER', chr(1)); + +/** + * @ingroup database + * @{ + */ + +// Include functions shared between oci8. +require_once './includes/common.oracle.inc'; + +// Include schema API shared between oci8. +require_once './includes/schema.oracle.inc'; + +/** + * Initialize a database connection. + */ +function db_connect($url) { + + // Check if Oracle support is present in PHP 5 + if (!(function_exists('oci_connect'))) { + drupal_maintenance_theme(); + drupal_set_title('PHP Oracle support not enabled'); + print theme('maintenance_page', '

We were unable to use the Oracle database because the Oracle extension for PHP is not installed. Check your PHP.ini to see how you can enable it.

'); + //TODO: create a book page about Oracle support. + exit; + } + + $url = parse_url($url); + + // Decode url-encoded information in the db connection string. + $url['user'] = urldecode($url['user']); + $url['pass'] = urldecode($url['pass']); + $url['host'] = urldecode($url['host']); + $url['path'] = urldecode($url['path']); + + // Build oci8 connection string and allow for non-standard Oracle port. + $conn_string = '//' . $url['host'] . (isset($url['port']) ? ':' . $url['port'] : '') . '/' . substr($url['path'], 1); + + // Even we can indicate charset parameter for oci_connect, which will be + // used in the new connection, we will not use this feature. Therefore + // NLS_LANG environment variable will be used instead. + $connection = @oci_connect($url['user'], $url['pass'], $conn_string); + + // Test connecting to the database. + if (!$connection && ($error = oci_error())) { + drupal_maintenance_theme(); + drupal_set_header('HTTP/1.1 503 Service Unavailable'); + drupal_set_title('Unable to connect to database'); + print theme('maintenance_page', '

If you still have to install Drupal, proceed to the installation page.

+

If you have already finished installed Drupal, this either means that the username and password information in your settings.php file is incorrect or that we can\'t connect to the Oracle database server. This could mean your hosting provider\'s database server is down.

+

The Oracle error was: '. theme('placeholder', $error['message']) .'.

+

Currently, the username is '. theme('placeholder', $url['user']) .' and the database server is '. theme('placeholder', $url['host']) .'.

+ +

For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.

'); + exit; + } + + return $connection; +} + +/** + * 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 %c (character large object). + * + * NOTE: use NULL as arguments substitution for %b and %c. This will be + * replaced as corresponding empty LOB value placeholder, based on the + * database specific representation. + * + * 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); + _debug_query($query); + $query = db_prefix_tables($query); + $query = db_escape_quote($query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + _db_query_callback(array('query' => $query, 'args' => $args), TRUE); + $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); + $args = _db_query_callback(NULL, TRUE); + return _db_query(array('query' => $query, 'args' => $args)); +} + +/** + * Helper function for db_query(). + */ +function _db_query($query, $debug = 0) { + global $active_db, $last_result, $queries; + static $last_stmts; + + // Expand $query if it is in array format. + $args = array(); + if (is_array($query)) { + $args = $query['args']; + $query = $query['query']; + + // Check if locator exists in query, or else unset it. + foreach ($args as $key => $value) { + if (!is_array($args[$key]) || !isset($args[$key]['locator']) || !strstr($query, $args[$key]['locator'])) { + unset($args[$key]); + } + } + } + + if (variable_get('dev_query', 0)) { + list($usec, $sec) = explode(' ', microtime()); + $timer = (float)$usec + (float)$sec; + // If devel.module query logging is enabled, prepend a comment with the username and calling function + // to the SQL string. This is useful when running mysql's SHOW PROCESSLIST to learn what exact + // code is issueing the slow query. + $bt = debug_backtrace(); + // t() may not be available yet so we don't wrap 'Anonymous' + $name = $user->uid ? $user->name : variable_get('anonymous', 'Anonymous'); + // str_replace() to prevent SQL injection via username or anonymous name. + $name = str_replace(array('*', '/'), '', $name); + $query = '/* '. $name .' : '. $bt[2]['function'] .' */ '. $query; + } + + $last_stmts = array_filter((array) $last_stmts); + $ident = md5($query); + if (isset($last_stmts[$ident])) { + // We parse this query once before, just reuse it. + $stmt = $last_stmts[$ident]; + unset($last_stmts[$ident]); + } + else { + // Perform actual query and return the result set. + $stmt = oci_parse($active_db, $query); + } + + // Try to free resources associated with Oracle's cursor or statement, + // or else our conection pool may busted. + array_push($last_stmts, array($ident => $stmt)); + while (count($last_stmts) >= ORACLE_MAX_CACHE_STMT) { + @oci_free_statement(array_shift($last_stmts)); + } + + if ($stmt === FALSE) { + // Indicate to drupal_error_handler that this is a database error. + ${DB_ERROR} = TRUE; + $error = oci_error($stmt); + trigger_error(check_plain($error['message']."\nquery: ". $query), E_USER_WARNING); + // On error, rollback the transaction. + oci_rollback($active_db); + return FALSE; + } + + if (count($args)) { + foreach ($args as $key => $value) { + if (isset($args[$key]['obj']) && is_object($args[$key]['obj'])) { + // Bind the returned Oracle LOB locator to the PHP LOB object. + oci_bind_by_name($stmt, $args[$key]['locator'], $args[$key]['obj'], -1, $args[$key]['type']); + } + else if (isset($args[$key]['type'])) { + oci_bind_by_name($stmt, $args[$key]['locator'], $args[$key]['data'], -1, $args[$key]['type']); + } + else { + oci_bind_by_name($stmt, $args[$key]['locator'], $args[$key]['data']); + } + } + } + +