- Patch #225450 by Crell, chx, bjaspan, catch, swentel, recidive et al: next generation database layer for Drupal 7.
							parent
							
								
									0e79597812
								
							
						
					
					
						commit
						69e6f411a9
					
				| 
						 | 
					@ -2,6 +2,11 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Drupal 7.0, xxxx-xx-xx (development version)
 | 
					Drupal 7.0, xxxx-xx-xx (development version)
 | 
				
			||||||
----------------------
 | 
					----------------------
 | 
				
			||||||
 | 
					- Database:
 | 
				
			||||||
 | 
					    * Fully rewritten database layer utilizing PHP 5's PDO abstraction layer.
 | 
				
			||||||
 | 
					    * Added query builders for INSERT, UPDATE, DELETE, MERGE, and SELECT queries.
 | 
				
			||||||
 | 
					    * Support for Master/slave replication, transactions, multi-insert queries,
 | 
				
			||||||
 | 
					      delayed inserts, and other features.
 | 
				
			||||||
- Security:
 | 
					- Security:
 | 
				
			||||||
    * Protected cron.php -- cron will only run if the proper key is provided.
 | 
					    * Protected cron.php -- cron will only run if the proper key is provided.
 | 
				
			||||||
    * Changed to much stronger password hashes that are also compatible with the
 | 
					    * Changed to much stronger password hashes that are also compatible with the
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -323,7 +323,7 @@ function conf_init() {
 | 
				
			||||||
  global $base_url, $base_path, $base_root;
 | 
					  global $base_url, $base_path, $base_root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Export the following settings.php variables to the global namespace
 | 
					  // Export the following settings.php variables to the global namespace
 | 
				
			||||||
  global $db_url, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access;
 | 
					  global $databases, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access;
 | 
				
			||||||
  $conf = array();
 | 
					  $conf = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (file_exists('./' . conf_path() . '/settings.php')) {
 | 
					  if (file_exists('./' . conf_path() . '/settings.php')) {
 | 
				
			||||||
| 
						 | 
					@ -520,11 +520,7 @@ function variable_get($name, $default) {
 | 
				
			||||||
function variable_set($name, $value) {
 | 
					function variable_set($name, $value) {
 | 
				
			||||||
  global $conf;
 | 
					  global $conf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $serialized_value = serialize($value);
 | 
					  db_merge('variable')->key(array('name' => $name))->fields(array('value' => serialize($value)))->execute();
 | 
				
			||||||
  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);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cache_clear_all('variables', 'cache');
 | 
					  cache_clear_all('variables', 'cache');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -813,24 +809,33 @@ function request_uri() {
 | 
				
			||||||
function watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL) {
 | 
					function watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL) {
 | 
				
			||||||
  global $user, $base_root;
 | 
					  global $user, $base_root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Prepare the fields to be logged
 | 
					  static $in_error_state = FALSE;
 | 
				
			||||||
  $log_message = array(
 | 
					
 | 
				
			||||||
    'type'        => $type,
 | 
					  // It is possible that the error handling will itself trigger an error.  In that case, we could
 | 
				
			||||||
    'message'     => $message,
 | 
					  // end up in an infinite loop.  To avoid that, we implement a simple static semaphore.
 | 
				
			||||||
    'variables'   => $variables,
 | 
					  if (!$in_error_state) {
 | 
				
			||||||
    'severity'    => $severity,
 | 
					    $in_error_state = TRUE;
 | 
				
			||||||
    'link'        => $link,
 | 
					
 | 
				
			||||||
    'user'        => $user,
 | 
					    // Prepare the fields to be logged
 | 
				
			||||||
    'request_uri' => $base_root . request_uri(),
 | 
					    $log_message = array(
 | 
				
			||||||
    'referer'     => referer_uri(),
 | 
					      'type'        => $type,
 | 
				
			||||||
    'ip'          => ip_address(),
 | 
					      'message'     => $message,
 | 
				
			||||||
    'timestamp'   => time(),
 | 
					      'variables'   => $variables,
 | 
				
			||||||
 | 
					      'severity'    => $severity,
 | 
				
			||||||
 | 
					      'link'        => $link,
 | 
				
			||||||
 | 
					      'user'        => $user,
 | 
				
			||||||
 | 
					      'request_uri' => $base_root . request_uri(),
 | 
				
			||||||
 | 
					      'referer'     => referer_uri(),
 | 
				
			||||||
 | 
					      'ip'          => ip_address(),
 | 
				
			||||||
 | 
					      'timestamp'   => time(),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Call the logging hooks to log/process the message
 | 
					    // Call the logging hooks to log/process the message
 | 
				
			||||||
  foreach (module_implements('watchdog', TRUE) as $module) {
 | 
					    foreach (module_implements('watchdog', TRUE) as $module) {
 | 
				
			||||||
    module_invoke($module, 'watchdog', $log_message);
 | 
					      module_invoke($module, 'watchdog', $log_message);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  $in_error_state = FALSE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -973,9 +978,24 @@ function drupal_bootstrap($phase) {
 | 
				
			||||||
    $current_phase = $phases[$phase_index];
 | 
					    $current_phase = $phases[$phase_index];
 | 
				
			||||||
    unset($phases[$phase_index++]);
 | 
					    unset($phases[$phase_index++]);
 | 
				
			||||||
    _drupal_bootstrap($current_phase);
 | 
					    _drupal_bootstrap($current_phase);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    global $_drupal_current_bootstrap_phase;
 | 
				
			||||||
 | 
					    $_drupal_current_bootstrap_phase = $current_phase;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Return the current bootstrap phase for this Drupal process.  The
 | 
				
			||||||
 | 
					 * current phase is the one most recently completed by
 | 
				
			||||||
 | 
					 * drupal_bootstrap().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see drupal_bootstrap
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function drupal_get_bootstrap_phase() {
 | 
				
			||||||
 | 
					  global $_drupal_current_bootstrap_phase;
 | 
				
			||||||
 | 
					  return $_drupal_current_bootstrap_phase;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function _drupal_bootstrap($phase) {
 | 
					function _drupal_bootstrap($phase) {
 | 
				
			||||||
  global $conf;
 | 
					  global $conf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1003,9 +1023,9 @@ function _drupal_bootstrap($phase) {
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case DRUPAL_BOOTSTRAP_DATABASE:
 | 
					    case DRUPAL_BOOTSTRAP_DATABASE:
 | 
				
			||||||
      // Initialize the default database.
 | 
					      // Initialize the database system.  Note that the connection
 | 
				
			||||||
      require_once './includes/database.inc';
 | 
					      // won't be initialized until it is actually requested.
 | 
				
			||||||
      db_set_active();
 | 
					      require_once './includes/database/database.inc';
 | 
				
			||||||
      // Register autoload functions so that we can access classes and interfaces.
 | 
					      // Register autoload functions so that we can access classes and interfaces.
 | 
				
			||||||
      spl_autoload_register('drupal_autoload_class');
 | 
					      spl_autoload_register('drupal_autoload_class');
 | 
				
			||||||
      spl_autoload_register('drupal_autoload_interface');
 | 
					      spl_autoload_register('drupal_autoload_interface');
 | 
				
			||||||
| 
						 | 
					@ -1209,6 +1229,87 @@ function ip_address($reset = false) {
 | 
				
			||||||
  return $ip_address;
 | 
					  return $ip_address;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup schemaapi
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Get the schema definition of a table, or the whole database schema.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The returned schema will include any modifications made by any
 | 
				
			||||||
 | 
					 * module that implements hook_schema_alter().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param $table
 | 
				
			||||||
 | 
					 *   The name of the table. If not given, the schema of all tables is returned.
 | 
				
			||||||
 | 
					 * @param $rebuild
 | 
				
			||||||
 | 
					 *   If true, the schema will be rebuilt instead of retrieved from the cache.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function drupal_get_schema($table = NULL, $rebuild = FALSE) {
 | 
				
			||||||
 | 
					  static $schema = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (empty($schema) || $rebuild) {
 | 
				
			||||||
 | 
					    // Try to load the schema from cache.
 | 
				
			||||||
 | 
					    if (!$rebuild && $cached = cache_get('schema')) {
 | 
				
			||||||
 | 
					      $schema = $cached->data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // Otherwise, rebuild the schema cache.
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      $schema = array();
 | 
				
			||||||
 | 
					      // Load the .install files to get hook_schema.
 | 
				
			||||||
 | 
					      // On some databases this function may be called before bootstrap has
 | 
				
			||||||
 | 
					      // been completed, so we force the functions we need to load just in case.
 | 
				
			||||||
 | 
					      if (drupal_function_exists('module_load_all_includes')) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // There is currently a bug in module_list() where it caches what it
 | 
				
			||||||
 | 
					        // was last called with, which is not always what you want.
 | 
				
			||||||
 | 
					        // module_load_all_includes() calls module_list(), but if this function
 | 
				
			||||||
 | 
					        // is called very early in the bootstrap process then it will be
 | 
				
			||||||
 | 
					        // uninitialized and therefore return no modules.  Instead, we have to
 | 
				
			||||||
 | 
					        // "prime" module_list() here to to values we want, specifically
 | 
				
			||||||
 | 
					        // "yes rebuild the list and don't limit to bootstrap".
 | 
				
			||||||
 | 
					        // TODO: Remove this call after http://drupal.org/node/222109 is fixed.
 | 
				
			||||||
 | 
					        module_list(TRUE, FALSE);
 | 
				
			||||||
 | 
					        module_load_all_includes('install');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Invoke hook_schema for all modules.
 | 
				
			||||||
 | 
					      foreach (module_implements('schema') as $module) {
 | 
				
			||||||
 | 
					        $current = module_invoke($module, 'schema');
 | 
				
			||||||
 | 
					        require_once('./includes/common.inc');
 | 
				
			||||||
 | 
					        if (drupal_function_exists('_drupal_initialize_schema')) {
 | 
				
			||||||
 | 
					          _drupal_initialize_schema($module, $current);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $schema = array_merge($schema, $current);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (drupal_function_exists('drupal_alter')) {
 | 
				
			||||||
 | 
					        drupal_alter('schema', $schema);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (drupal_get_bootstrap_phase() == DRUPAL_BOOTSTRAP_FULL) {
 | 
				
			||||||
 | 
					        cache_set('schema', $schema);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!isset($table)) {
 | 
				
			||||||
 | 
					    return $schema;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  elseif (isset($schema[$table])) {
 | 
				
			||||||
 | 
					    return $schema[$table];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    return FALSE;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @} End of "ingroup schemaapi".
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @ingroup registry
 | 
					 * @ingroup registry
 | 
				
			||||||
 * @{
 | 
					 * @{
 | 
				
			||||||
| 
						 | 
					@ -1245,7 +1346,7 @@ function drupal_function_exists($function) {
 | 
				
			||||||
    return TRUE;
 | 
					    return TRUE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $file = db_result(db_query("SELECT filename FROM {registry} WHERE name = '%s' AND type = '%s'", $function, 'function'));
 | 
					  $file = db_result(db_query("SELECT filename FROM {registry} WHERE name = :name AND type = :type", array(':name' => $function, ':type' => 'function')));
 | 
				
			||||||
  if ($file) {
 | 
					  if ($file) {
 | 
				
			||||||
    require_once($file);
 | 
					    require_once($file);
 | 
				
			||||||
    $checked[$function] = function_exists($function);
 | 
					    $checked[$function] = function_exists($function);
 | 
				
			||||||
| 
						 | 
					@ -1293,7 +1394,7 @@ function drupal_autoload_class($class) {
 | 
				
			||||||
 * Helper for registry_check_{interface, class}.
 | 
					 * Helper for registry_check_{interface, class}.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function _registry_check_code($type, $name) {
 | 
					function _registry_check_code($type, $name) {
 | 
				
			||||||
  $file = db_result(db_query("SELECT filename FROM {registry} WHERE name = '%s' AND type = '%s'", $name, $type));
 | 
					  $file = db_result(db_query("SELECT filename FROM {registry} WHERE name = :name AND type = :type", array(':name' => $name, ':type' => $type)));
 | 
				
			||||||
  if ($file) {
 | 
					  if ($file) {
 | 
				
			||||||
    require_once($file);
 | 
					    require_once($file);
 | 
				
			||||||
    registry_mark_code($type, $name);
 | 
					    registry_mark_code($type, $name);
 | 
				
			||||||
| 
						 | 
					@ -1358,7 +1459,7 @@ function registry_cache_hook_implementations($hook, $write_to_persistent_cache =
 | 
				
			||||||
  if ($write_to_persistent_cache === TRUE) {
 | 
					  if ($write_to_persistent_cache === TRUE) {
 | 
				
			||||||
    // Only write this to cache if the implementations data we are going to cache
 | 
					    // Only write this to cache if the implementations data we are going to cache
 | 
				
			||||||
    // is different to what we loaded earlier in the request.
 | 
					    // is different to what we loaded earlier in the request.
 | 
				
			||||||
    if ($implementations != registry_get_hook_implementations_cache()) {
 | 
					    if ($implementations != module_implements()) {
 | 
				
			||||||
      cache_set('hooks', $implementations, 'cache_registry');
 | 
					      cache_set('hooks', $implementations, 'cache_registry');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -1412,23 +1513,6 @@ function registry_load_path_files($return = FALSE) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * registry_get_hook_implementations_cache
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function registry_get_hook_implementations_cache() {
 | 
					 | 
				
			||||||
  static $implementations;
 | 
					 | 
				
			||||||
  if ($implementations === NULL) {
 | 
					 | 
				
			||||||
    if ($cache = cache_get('hooks', 'cache_registry')) {
 | 
					 | 
				
			||||||
      $implementations = $cache->data;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      $implementations = array();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return $implementations;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @} End of "ingroup registry".
 | 
					 * @} End of "ingroup registry".
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,6 @@ function cache_get($cid, $table = 'cache') {
 | 
				
			||||||
    // If the data is permanent or we're not enforcing a minimum cache lifetime
 | 
					    // If the data is permanent or we're not enforcing a minimum cache lifetime
 | 
				
			||||||
    // always return the cached data.
 | 
					    // always return the cached data.
 | 
				
			||||||
    if ($cache->expire == CACHE_PERMANENT || !variable_get('cache_lifetime', 0)) {
 | 
					    if ($cache->expire == CACHE_PERMANENT || !variable_get('cache_lifetime', 0)) {
 | 
				
			||||||
      $cache->data = db_decode_blob($cache->data);
 | 
					 | 
				
			||||||
      if ($cache->serialized) {
 | 
					      if ($cache->serialized) {
 | 
				
			||||||
        $cache->data = unserialize($cache->data);
 | 
					        $cache->data = unserialize($cache->data);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -45,7 +44,6 @@ function cache_get($cid, $table = 'cache') {
 | 
				
			||||||
        return FALSE;
 | 
					        return FALSE;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      else {
 | 
					      else {
 | 
				
			||||||
        $cache->data = db_decode_blob($cache->data);
 | 
					 | 
				
			||||||
        if ($cache->serialized) {
 | 
					        if ($cache->serialized) {
 | 
				
			||||||
          $cache->data = unserialize($cache->data);
 | 
					          $cache->data = unserialize($cache->data);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -101,16 +99,22 @@ function cache_get($cid, $table = 'cache') {
 | 
				
			||||||
 *   A string containing HTTP header information for cached pages.
 | 
					 *   A string containing HTTP header information for cached pages.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function cache_set($cid, $data, $table = 'cache', $expire = CACHE_PERMANENT, $headers = NULL) {
 | 
					function cache_set($cid, $data, $table = 'cache', $expire = CACHE_PERMANENT, $headers = NULL) {
 | 
				
			||||||
  $serialized = 0;
 | 
					  $fields = array(
 | 
				
			||||||
 | 
					    'serialized' => 0,
 | 
				
			||||||
 | 
					    'created' => time(),
 | 
				
			||||||
 | 
					    'expire' => $expire,
 | 
				
			||||||
 | 
					    'headers' => $headers,
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
  if (!is_string($data)) {
 | 
					  if (!is_string($data)) {
 | 
				
			||||||
    $data = serialize($data);
 | 
					    $fields['data'] = serialize($data);
 | 
				
			||||||
    $serialized = 1;
 | 
					    $fields['serialized'] = 1;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  $created = time();
 | 
					  else {
 | 
				
			||||||
  db_query("UPDATE {" . $table . "} SET data = %b, created = %d, expire = %d, headers = '%s', serialized = %d WHERE cid = '%s'", $data, $created, $expire, $headers, $serialized, $cid);
 | 
					    $fields['data'] = $data;
 | 
				
			||||||
  if (!db_affected_rows()) {
 | 
					    $fields['serialized'] = 0;
 | 
				
			||||||
    @db_query("INSERT INTO {" . $table . "} (cid, data, created, expire, headers, serialized) VALUES ('%s', %b, %d, %d, '%s', %d)", $cid, $data, $created, $expire, $headers, $serialized);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  db_merge($table)->key(array('cid' => $cid))->fields($fields)->execute();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -170,14 +174,14 @@ function cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
 | 
				
			||||||
  else {
 | 
					  else {
 | 
				
			||||||
    if ($wildcard) {
 | 
					    if ($wildcard) {
 | 
				
			||||||
      if ($cid == '*') {
 | 
					      if ($cid == '*') {
 | 
				
			||||||
        db_query("DELETE FROM {" . $table . "}");
 | 
					        db_delete($table)->execute();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      else {
 | 
					      else {
 | 
				
			||||||
        db_query("DELETE FROM {" . $table . "} WHERE cid LIKE '%s%%'", $cid);
 | 
					        db_delete($table)->condition('cid', $cid .'%', 'LIKE')->execute();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
      db_query("DELETE FROM {" . $table . "} WHERE cid = '%s'", $cid);
 | 
					      db_delete($table)->condition('cid', $cid)->execute();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2083,7 +2083,7 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
 | 
				
			||||||
  // with HTML 4, we need to comment out the CDATA-tag.
 | 
					  // with HTML 4, we need to comment out the CDATA-tag.
 | 
				
			||||||
  $embed_prefix = "\n<!--//--><![CDATA[//><!--\n";
 | 
					  $embed_prefix = "\n<!--//--><![CDATA[//><!--\n";
 | 
				
			||||||
  $embed_suffix = "\n//--><!]]>\n";
 | 
					  $embed_suffix = "\n//--><!]]>\n";
 | 
				
			||||||
 
 | 
					
 | 
				
			||||||
  foreach ($javascript as $type => $data) {
 | 
					  foreach ($javascript as $type => $data) {
 | 
				
			||||||
    if (!$data) continue;
 | 
					    if (!$data) continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2487,6 +2487,9 @@ function _drupal_bootstrap_full() {
 | 
				
			||||||
  fix_gpc_magic();
 | 
					  fix_gpc_magic();
 | 
				
			||||||
  // Load all enabled modules
 | 
					  // Load all enabled modules
 | 
				
			||||||
  module_load_all();
 | 
					  module_load_all();
 | 
				
			||||||
 | 
					  // Rebuild the module hook cache
 | 
				
			||||||
 | 
					  module_implements('', NULL, TRUE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Let all modules take action before menu system handles the request
 | 
					  // Let all modules take action before menu system handles the request
 | 
				
			||||||
  // We do not want this while running update.php.
 | 
					  // We do not want this while running update.php.
 | 
				
			||||||
  if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') {
 | 
					  if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') {
 | 
				
			||||||
| 
						 | 
					@ -2663,7 +2666,6 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1)
 | 
				
			||||||
  return $files;
 | 
					  return $files;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This dispatch function hands off structured Drupal arrays to type-specific
 | 
					 * This dispatch function hands off structured Drupal arrays to type-specific
 | 
				
			||||||
 * *_alter implementations. It ensures a consistent interface for all altering
 | 
					 * *_alter implementations. It ensures a consistent interface for all altering
 | 
				
			||||||
| 
						 | 
					@ -2712,7 +2714,6 @@ function drupal_alter($type, &$data) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Renders HTML given a structured array tree.
 | 
					 * Renders HTML given a structured array tree.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -3060,54 +3061,6 @@ function drupal_common_theme() {
 | 
				
			||||||
 * @{
 | 
					 * @{
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Get the schema definition of a table, or the whole database schema.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The returned schema will include any modifications made by any
 | 
					 | 
				
			||||||
 * module that implements hook_schema_alter().
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $table
 | 
					 | 
				
			||||||
 *   The name of the table. If not given, the schema of all tables is returned.
 | 
					 | 
				
			||||||
 * @param $rebuild
 | 
					 | 
				
			||||||
 *   If true, the schema will be rebuilt instead of retrieved from the cache.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function drupal_get_schema($table = NULL, $rebuild = FALSE) {
 | 
					 | 
				
			||||||
  static $schema = array();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (empty($schema) || $rebuild) {
 | 
					 | 
				
			||||||
    // Try to load the schema from cache.
 | 
					 | 
				
			||||||
    if (!$rebuild && $cached = cache_get('schema')) {
 | 
					 | 
				
			||||||
      $schema = $cached->data;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    // Otherwise, rebuild the schema cache.
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      $schema = array();
 | 
					 | 
				
			||||||
      // Load the .install files to get hook_schema.
 | 
					 | 
				
			||||||
      module_load_all_includes('install');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Invoke hook_schema for all modules.
 | 
					 | 
				
			||||||
      foreach (module_implements('schema') as $module) {
 | 
					 | 
				
			||||||
        $current = module_invoke($module, 'schema');
 | 
					 | 
				
			||||||
        _drupal_initialize_schema($module, $current);
 | 
					 | 
				
			||||||
        $schema = array_merge($schema, $current);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      drupal_alter('schema', $schema);
 | 
					 | 
				
			||||||
      cache_set('schema', $schema);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!isset($table)) {
 | 
					 | 
				
			||||||
    return $schema;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  elseif (isset($schema[$table])) {
 | 
					 | 
				
			||||||
    return $schema[$table];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Create all tables that a module defines in its hook_schema().
 | 
					 * Create all tables that a module defines in its hook_schema().
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -3153,7 +3106,9 @@ function drupal_uninstall_schema($module) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $ret = array();
 | 
					  $ret = array();
 | 
				
			||||||
  foreach ($schema as $table) {
 | 
					  foreach ($schema as $table) {
 | 
				
			||||||
    db_drop_table($ret, $table['name']);
 | 
					    if (db_table_exists($table['name'])) {
 | 
				
			||||||
 | 
					      db_drop_table($ret, $table['name']);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return $ret;
 | 
					  return $ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,581 +0,0 @@
 | 
				
			||||||
<?php
 | 
					 | 
				
			||||||
// $Id$
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * Wrapper for database interface code.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * A hash value to check when outputting database errors, md5('DB_ERROR').
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @see drupal_error_handler()
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
define('DB_ERROR', 'a515ac9c2796ca0e23adbe92c68fc9fc');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @defgroup database Database abstraction layer
 | 
					 | 
				
			||||||
 * @{
 | 
					 | 
				
			||||||
 * Allow the use of different database servers using the same code base.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Drupal provides a slim database abstraction layer to provide developers with
 | 
					 | 
				
			||||||
 * the ability to support multiple database servers easily. The intent of this
 | 
					 | 
				
			||||||
 * layer is to preserve the syntax and power of SQL as much as possible, while
 | 
					 | 
				
			||||||
 * letting Drupal control the pieces of queries that need to be written
 | 
					 | 
				
			||||||
 * differently for different servers and provide basic security checks.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Most Drupal database queries are performed by a call to db_query() or
 | 
					 | 
				
			||||||
 * db_query_range(). Module authors should also consider using pager_query() for
 | 
					 | 
				
			||||||
 * queries that return results that need to be presented on multiple pages, and
 | 
					 | 
				
			||||||
 * tablesort_sql() for generating appropriate queries for sortable tables.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * For example, one might wish to return a list of the most recent 10 nodes
 | 
					 | 
				
			||||||
 * authored by a given user. Instead of directly issuing the SQL query
 | 
					 | 
				
			||||||
 * @code
 | 
					 | 
				
			||||||
 *   SELECT n.title, n.body, n.created FROM node n WHERE n.uid = $uid LIMIT 0, 10;
 | 
					 | 
				
			||||||
 * @endcode
 | 
					 | 
				
			||||||
 * one would instead call the Drupal functions:
 | 
					 | 
				
			||||||
 * @code
 | 
					 | 
				
			||||||
 *   $result = db_query_range('SELECT n.title, n.body, n.created
 | 
					 | 
				
			||||||
 *     FROM {node} n WHERE n.uid = %d', $uid, 0, 10);
 | 
					 | 
				
			||||||
 *   while ($node = db_fetch_object($result)) {
 | 
					 | 
				
			||||||
 *     // Perform operations on $node->body, etc. here.
 | 
					 | 
				
			||||||
 *   }
 | 
					 | 
				
			||||||
 * @endcode
 | 
					 | 
				
			||||||
 * Curly braces are used around "node" to provide table prefixing via
 | 
					 | 
				
			||||||
 * db_prefix_tables(). The explicit use of a user ID is pulled out into an
 | 
					 | 
				
			||||||
 * argument passed to db_query() so that SQL injection attacks from user input
 | 
					 | 
				
			||||||
 * can be caught and nullified. The LIMIT syntax varies between database servers,
 | 
					 | 
				
			||||||
 * so that is abstracted into db_query_range() arguments. Finally, note the
 | 
					 | 
				
			||||||
 * common pattern of iterating over the result set using db_fetch_object().
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Perform an SQL query and return success or failure.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $sql
 | 
					 | 
				
			||||||
 *   A string containing a complete SQL query.  %-substitution
 | 
					 | 
				
			||||||
 *   parameters are not supported.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   An array containing the keys:
 | 
					 | 
				
			||||||
 *      success: a boolean indicating whether the query succeeded
 | 
					 | 
				
			||||||
 *      query: the SQL query executed, passed through check_plain()
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function update_sql($sql) {
 | 
					 | 
				
			||||||
  $result = db_query($sql, true);
 | 
					 | 
				
			||||||
  return array('success' => $result !== FALSE, 'query' => check_plain($sql));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Append a database prefix to all tables in a query.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Queries sent to Drupal should wrap all table names in curly brackets. This
 | 
					 | 
				
			||||||
 * function searches for this syntax and adds Drupal's table prefix to all
 | 
					 | 
				
			||||||
 * tables, allowing Drupal to coexist with other systems in the same database if
 | 
					 | 
				
			||||||
 * necessary.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $sql
 | 
					 | 
				
			||||||
 *   A string containing a partial or entire SQL query.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   The properly-prefixed string.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_prefix_tables($sql) {
 | 
					 | 
				
			||||||
  global $db_prefix;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (is_array($db_prefix)) {
 | 
					 | 
				
			||||||
    if (array_key_exists('default', $db_prefix)) {
 | 
					 | 
				
			||||||
      $tmp = $db_prefix;
 | 
					 | 
				
			||||||
      unset($tmp['default']);
 | 
					 | 
				
			||||||
      foreach ($tmp as $key => $val) {
 | 
					 | 
				
			||||||
        $sql = strtr($sql, array('{' . $key . '}' => $val . $key));
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return strtr($sql, array('{' => $db_prefix['default'], '}' => ''));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      foreach ($db_prefix as $key => $val) {
 | 
					 | 
				
			||||||
        $sql = strtr($sql, array('{' . $key . '}' => $val . $key));
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return strtr($sql, array('{' => '', '}' => ''));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    return strtr($sql, array('{' => $db_prefix, '}' => ''));
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Activate a database for future queries.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * If it is necessary to use external databases in a project, this function can
 | 
					 | 
				
			||||||
 * be used to change where database queries are sent. If the database has not
 | 
					 | 
				
			||||||
 * yet been used, it is initialized using the URL specified for that name in
 | 
					 | 
				
			||||||
 * Drupal's configuration file. If this name is not defined, a duplicate of the
 | 
					 | 
				
			||||||
 * default connection is made instead.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Be sure to change the connection back to the default when done with custom
 | 
					 | 
				
			||||||
 * code.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $name
 | 
					 | 
				
			||||||
 *   The name assigned to the newly active database connection. If omitted, the
 | 
					 | 
				
			||||||
 *   default connection will be made active.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return the name of the previously active database or FALSE if non was found.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_set_active($name = 'default') {
 | 
					 | 
				
			||||||
  global $db_url, $db_type, $active_db, $db_prefix;
 | 
					 | 
				
			||||||
  static $db_conns, $active_name = FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (empty($db_url)) {
 | 
					 | 
				
			||||||
    include_once 'includes/install.inc';
 | 
					 | 
				
			||||||
    install_goto('install.php');
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!isset($db_conns[$name])) {
 | 
					 | 
				
			||||||
    // Initiate a new connection, using the named DB URL specified.
 | 
					 | 
				
			||||||
    if (is_array($db_url)) {
 | 
					 | 
				
			||||||
      $connect_url = array_key_exists($name, $db_url) ? $db_url[$name] : $db_url['default'];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      $connect_url = $db_url;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $db_type = substr($connect_url, 0, strpos($connect_url, '://'));
 | 
					 | 
				
			||||||
    $handler = "./includes/database.$db_type.inc";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (is_file($handler)) {
 | 
					 | 
				
			||||||
      include_once $handler;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      _db_error_page("The database type '" . $db_type . "' is unsupported. Please use either 'mysql' or 'mysqli' for MySQL, or 'pgsql' for PostgreSQL databases.");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $db_conns[$name] = db_connect($connect_url);
 | 
					 | 
				
			||||||
    // We need to pass around the simpletest database prefix in the request
 | 
					 | 
				
			||||||
    // and we put that in the user_agent header.
 | 
					 | 
				
			||||||
    if (preg_match("/^simpletest\d+$/", $_SERVER['HTTP_USER_AGENT'])) {
 | 
					 | 
				
			||||||
      $db_prefix = $_SERVER['HTTP_USER_AGENT'];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $previous_name = $active_name;
 | 
					 | 
				
			||||||
  // Set the active connection.
 | 
					 | 
				
			||||||
  $active_name = $name;
 | 
					 | 
				
			||||||
  $active_db = $db_conns[$name];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return $previous_name;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Helper function to show fatal database errors.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Prints a themed maintenance page with the 'Site offline' text,
 | 
					 | 
				
			||||||
 * adding the provided error message in the case of 'display_errors'
 | 
					 | 
				
			||||||
 * set to on. Ends the page request; no return.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $error
 | 
					 | 
				
			||||||
 *   The error message to be appended if 'display_errors' is on.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function _db_error_page($error = '') {
 | 
					 | 
				
			||||||
  global $db_type;
 | 
					 | 
				
			||||||
  drupal_maintenance_theme();
 | 
					 | 
				
			||||||
  drupal_set_header('HTTP/1.1 503 Service Unavailable');
 | 
					 | 
				
			||||||
  drupal_set_title('Site offline');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $message = '<p>The site is currently not available due to technical problems. Please try again later. Thank you for your understanding.</p>';
 | 
					 | 
				
			||||||
  $message .= '<hr /><p><small>If you are the maintainer of this site, please check your database settings in the <code>settings.php</code> file and ensure that your hosting provider\'s database server is running. For more help, see the <a href="http://drupal.org/node/258">handbook</a>, or contact your hosting provider.</small></p>';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ($error && ini_get('display_errors')) {
 | 
					 | 
				
			||||||
    $message .= '<p><small>The ' . theme('placeholder', $db_type) . ' error was: ' . theme('placeholder', $error) . '.</small></p>';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  print theme('maintenance_page', $message);
 | 
					 | 
				
			||||||
  exit;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Returns a boolean depending on the availability of the database.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_is_active() {
 | 
					 | 
				
			||||||
  global $active_db;
 | 
					 | 
				
			||||||
  return !empty($active_db);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Helper function for db_query().
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function _db_query_callback($match, $init = FALSE) {
 | 
					 | 
				
			||||||
  static $args = NULL;
 | 
					 | 
				
			||||||
  if ($init) {
 | 
					 | 
				
			||||||
    $args = $match;
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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 '%n':
 | 
					 | 
				
			||||||
      // Numeric values have arbitrary precision, so can't be treated as float.
 | 
					 | 
				
			||||||
      // is_numeric() allows hex values (0xFF), but they are not valid.
 | 
					 | 
				
			||||||
      $value = trim(array_shift($args));
 | 
					 | 
				
			||||||
      return (is_numeric($value) && !stripos($value, 'x')) ? $value : '0';
 | 
					 | 
				
			||||||
    case '%%':
 | 
					 | 
				
			||||||
      return '%';
 | 
					 | 
				
			||||||
    case '%f':
 | 
					 | 
				
			||||||
      return (float) array_shift($args);
 | 
					 | 
				
			||||||
    case '%b': // binary data
 | 
					 | 
				
			||||||
      return db_encode_blob(array_shift($args));
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Generate placeholders for an array of query arguments of a single type.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Given a Schema API field type, return correct %-placeholders to
 | 
					 | 
				
			||||||
 * embed in a query
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $arguments
 | 
					 | 
				
			||||||
 *  An array with at least one element.
 | 
					 | 
				
			||||||
 * @param $type
 | 
					 | 
				
			||||||
 *   The Schema API type of a field (e.g. 'int', 'text', or 'varchar').
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_placeholders($arguments, $type = 'int') {
 | 
					 | 
				
			||||||
  $placeholder = db_type_placeholder($type);
 | 
					 | 
				
			||||||
  return implode(',', array_fill(0, count($arguments), $placeholder));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Indicates the place holders that should be replaced in _db_query_callback().
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
define('DB_QUERY_REGEXP', '/(%d|%s|%%|%f|%b|%n)/');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Helper function for db_rewrite_sql.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Collects JOIN and WHERE statements via hook_db_rewrite_sql()
 | 
					 | 
				
			||||||
 * Decides whether to select primary_key or DISTINCT(primary_key)
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $query
 | 
					 | 
				
			||||||
 *   Query to be rewritten.
 | 
					 | 
				
			||||||
 * @param $primary_table
 | 
					 | 
				
			||||||
 *   Name or alias of the table which has the primary key field for this query.
 | 
					 | 
				
			||||||
 *   Typical table names would be: {blocks}, {comments}, {forum}, {node},
 | 
					 | 
				
			||||||
 *   {menu}, {term_data} or {vocabulary}. However, in most cases the usual
 | 
					 | 
				
			||||||
 *   table alias (b, c, f, n, m, t or v) is used instead of the table name.
 | 
					 | 
				
			||||||
 * @param $primary_field
 | 
					 | 
				
			||||||
 *   Name of the primary field.
 | 
					 | 
				
			||||||
 * @param $args
 | 
					 | 
				
			||||||
 *   Array of additional arguments.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   An array: join statements, where statements, field or DISTINCT(field).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function _db_rewrite_sql($query = '', $primary_table = 'n', $primary_field = 'nid', $args = array()) {
 | 
					 | 
				
			||||||
  $where = array();
 | 
					 | 
				
			||||||
  $join = array();
 | 
					 | 
				
			||||||
  $distinct = FALSE;
 | 
					 | 
				
			||||||
  foreach (module_implements('db_rewrite_sql') as $module) {
 | 
					 | 
				
			||||||
    $result = module_invoke($module, 'db_rewrite_sql', $query, $primary_table, $primary_field, $args);
 | 
					 | 
				
			||||||
    if (isset($result) && is_array($result)) {
 | 
					 | 
				
			||||||
      if (isset($result['where'])) {
 | 
					 | 
				
			||||||
        $where[] = $result['where'];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (isset($result['join'])) {
 | 
					 | 
				
			||||||
        $join[] = $result['join'];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (isset($result['distinct']) && $result['distinct']) {
 | 
					 | 
				
			||||||
        $distinct = TRUE;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    elseif (isset($result)) {
 | 
					 | 
				
			||||||
      $where[] = $result;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $where = empty($where) ? '' : '(' . implode(') AND (', $where) . ')';
 | 
					 | 
				
			||||||
  $join = empty($join) ? '' : implode(' ', $join);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return array($join, $where, $distinct);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Rewrites node, taxonomy and comment queries. Use it for listing queries. Do not
 | 
					 | 
				
			||||||
 * use FROM table1, table2 syntax, use JOIN instead.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $query
 | 
					 | 
				
			||||||
 *   Query to be rewritten.
 | 
					 | 
				
			||||||
 * @param $primary_table
 | 
					 | 
				
			||||||
 *   Name or alias of the table which has the primary key field for this query.
 | 
					 | 
				
			||||||
 *   Typical table names would be: {blocks}, {comments}, {forum}, {node},
 | 
					 | 
				
			||||||
 *   {menu}, {term_data} or {vocabulary}. However, it is more common to use the
 | 
					 | 
				
			||||||
 *   the usual table aliases: b, c, f, n, m, t or v.
 | 
					 | 
				
			||||||
 * @param $primary_field
 | 
					 | 
				
			||||||
 *   Name of the primary field.
 | 
					 | 
				
			||||||
 * @param $args
 | 
					 | 
				
			||||||
 *   An array of arguments, passed to the implementations of hook_db_rewrite_sql.
 | 
					 | 
				
			||||||
 * @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()) {
 | 
					 | 
				
			||||||
  list($join, $where, $distinct) = _db_rewrite_sql($query, $primary_table, $primary_field, $args);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ($distinct) {
 | 
					 | 
				
			||||||
    $query = db_distinct_field($primary_table, $primary_field, $query);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!empty($where) || !empty($join)) {
 | 
					 | 
				
			||||||
    $pattern = '{
 | 
					 | 
				
			||||||
      # Beginning of the string
 | 
					 | 
				
			||||||
      ^
 | 
					 | 
				
			||||||
      ((?P<anonymous_view>
 | 
					 | 
				
			||||||
        # Everything within this set of parentheses is named "anonymous view"
 | 
					 | 
				
			||||||
        (?:
 | 
					 | 
				
			||||||
          [^()]++                   # anything not parentheses
 | 
					 | 
				
			||||||
        |
 | 
					 | 
				
			||||||
          \( (?P>anonymous_view) \)          # an open parenthesis, more "anonymous view" and finally a close parenthesis.
 | 
					 | 
				
			||||||
        )*
 | 
					 | 
				
			||||||
      )[^()]+WHERE)
 | 
					 | 
				
			||||||
    }x';
 | 
					 | 
				
			||||||
    preg_match($pattern, $query, $matches);
 | 
					 | 
				
			||||||
    if ($where) {
 | 
					 | 
				
			||||||
      $n = strlen($matches[1]);
 | 
					 | 
				
			||||||
      $second_part = substr($query, $n);
 | 
					 | 
				
			||||||
      $first_part = substr($matches[1], 0, $n - 5) . " $join WHERE $where AND ( ";
 | 
					 | 
				
			||||||
      // PHP 4 does not support strrpos for strings. We emulate it.
 | 
					 | 
				
			||||||
      $haystack_reverse = strrev($second_part);
 | 
					 | 
				
			||||||
      // No need to use strrev on the needle, we supply GROUP, ORDER, LIMIT
 | 
					 | 
				
			||||||
      // reversed.
 | 
					 | 
				
			||||||
      foreach (array('PUORG', 'REDRO', 'TIMIL') as $needle_reverse) {
 | 
					 | 
				
			||||||
        $pos = strpos($haystack_reverse, $needle_reverse);
 | 
					 | 
				
			||||||
        if ($pos !== FALSE) {
 | 
					 | 
				
			||||||
          // All needles are five characters long.
 | 
					 | 
				
			||||||
          $pos += 5;
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if ($pos === FALSE) {
 | 
					 | 
				
			||||||
        $query = $first_part . $second_part . ')';
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      else {
 | 
					 | 
				
			||||||
        $query = $first_part . substr($second_part, 0, -$pos) . ')' . substr($second_part, -$pos);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      $query = $matches[1] . " $join " . substr($query, strlen($matches[1]));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return $query;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Restrict a dynamic table, column or constraint name to safe characters.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Only keeps alphanumeric and underscores.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_escape_table($string) {
 | 
					 | 
				
			||||||
  return preg_replace('/[^A-Za-z0-9_]+/', '', $string);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @} End of "defgroup database".
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @defgroup schemaapi Schema API
 | 
					 | 
				
			||||||
 * @{
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * A Drupal schema definition is an array structure representing one or
 | 
					 | 
				
			||||||
 * more tables and their related keys and indexes. A schema is defined by
 | 
					 | 
				
			||||||
 * hook_schema(), which usually lives in a modulename.install file.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * By implementing hook_schema() and specifying the tables your module
 | 
					 | 
				
			||||||
 * declares, you can easily create and drop these tables on all
 | 
					 | 
				
			||||||
 * supported database engines. You don't have to deal with the
 | 
					 | 
				
			||||||
 * different SQL dialects for table creation and alteration of the
 | 
					 | 
				
			||||||
 * supported database engines.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * hook_schema() should return an array with a key for each table that
 | 
					 | 
				
			||||||
 * the module defines.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The following keys are defined:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *   - 'description': A string describing this table and its purpose.
 | 
					 | 
				
			||||||
 *     References to other tables should be enclosed in
 | 
					 | 
				
			||||||
 *     curly-brackets.  For example, the node_revisions table
 | 
					 | 
				
			||||||
 *     description field might contain "Stores per-revision title and
 | 
					 | 
				
			||||||
 *     body data for each {node}."
 | 
					 | 
				
			||||||
 *   - 'fields': An associative array ('fieldname' => specification)
 | 
					 | 
				
			||||||
 *     that describes the table's database columns.  The specification
 | 
					 | 
				
			||||||
 *     is also an array.  The following specification parameters are defined:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *     - 'description': A string describing this field and its purpose.
 | 
					 | 
				
			||||||
 *       References to other tables should be enclosed in
 | 
					 | 
				
			||||||
 *       curly-brackets.  For example, the node table vid field
 | 
					 | 
				
			||||||
 *       description might contain "Always holds the largest (most
 | 
					 | 
				
			||||||
 *       recent) {node_revisions}.vid value for this nid."
 | 
					 | 
				
			||||||
 *     - 'type': The generic datatype: 'varchar', 'int', 'serial'
 | 
					 | 
				
			||||||
 *       'float', 'numeric', 'text', 'blob' or 'datetime'.  Most types
 | 
					 | 
				
			||||||
 *       just map to the according database engine specific
 | 
					 | 
				
			||||||
 *       datatypes.  Use 'serial' for auto incrementing fields. This
 | 
					 | 
				
			||||||
 *       will expand to 'int auto_increment' on mysql.
 | 
					 | 
				
			||||||
 *     - 'size': The data size: 'tiny', 'small', 'medium', 'normal',
 | 
					 | 
				
			||||||
 *       'big'.  This is a hint about the largest value the field will
 | 
					 | 
				
			||||||
 *       store and determines which of the database engine specific
 | 
					 | 
				
			||||||
 *       datatypes will be used (e.g. on MySQL, TINYINT vs. INT vs. BIGINT).
 | 
					 | 
				
			||||||
 *       'normal', the default, selects the base type (e.g. on MySQL,
 | 
					 | 
				
			||||||
 *       INT, VARCHAR, BLOB, etc.).
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *       Not all sizes are available for all data types. See
 | 
					 | 
				
			||||||
 *       db_type_map() for possible combinations.
 | 
					 | 
				
			||||||
 *     - 'not null': If true, no NULL values will be allowed in this
 | 
					 | 
				
			||||||
 *       database column.  Defaults to false.
 | 
					 | 
				
			||||||
 *     - 'default': The field's default value.  The PHP type of the
 | 
					 | 
				
			||||||
 *       value matters: '', '0', and 0 are all different.  If you
 | 
					 | 
				
			||||||
 *       specify '0' as the default value for a type 'int' field it
 | 
					 | 
				
			||||||
 *       will not work because '0' is a string containing the
 | 
					 | 
				
			||||||
 *       character "zero", not an integer.
 | 
					 | 
				
			||||||
 *     - 'length': The maximal length of a type 'varchar' or 'text'
 | 
					 | 
				
			||||||
 *       field.  Ignored for other field types.
 | 
					 | 
				
			||||||
 *     - 'unsigned': A boolean indicating whether a type 'int', 'float'
 | 
					 | 
				
			||||||
 *       and 'numeric' only is signed or unsigned.  Defaults to
 | 
					 | 
				
			||||||
 *       FALSE.  Ignored for other field types.
 | 
					 | 
				
			||||||
 *     - 'precision', 'scale': For type 'numeric' fields, indicates
 | 
					 | 
				
			||||||
 *       the precision (total number of significant digits) and scale
 | 
					 | 
				
			||||||
 *       (decimal digits right of the decimal point).  Both values are
 | 
					 | 
				
			||||||
 *       mandatory.  Ignored for other field types.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *     All parameters apart from 'type' are optional except that type
 | 
					 | 
				
			||||||
 *     'numeric' columns must specify 'precision' and 'scale'.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *  - 'primary key': An array of one or more key column specifiers (see below)
 | 
					 | 
				
			||||||
 *    that form the primary key.
 | 
					 | 
				
			||||||
 *  - 'unique key': An associative array of unique keys ('keyname' =>
 | 
					 | 
				
			||||||
 *    specification).  Each specification is an array of one or more
 | 
					 | 
				
			||||||
 *    key column specifiers (see below) that form a unique key on the table.
 | 
					 | 
				
			||||||
 *  - 'indexes':  An associative array of indexes ('indexame' =>
 | 
					 | 
				
			||||||
 *    specification).  Each specification is an array of one or more
 | 
					 | 
				
			||||||
 *    key column specifiers (see below) that form an index on the
 | 
					 | 
				
			||||||
 *    table.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * A key column specifier is either a string naming a column or an
 | 
					 | 
				
			||||||
 * array of two elements, column name and length, specifying a prefix
 | 
					 | 
				
			||||||
 * of the named column.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * As an example, here is a SUBSET of the schema definition for
 | 
					 | 
				
			||||||
 * Drupal's 'node' table.  It show four fields (nid, vid, type, and
 | 
					 | 
				
			||||||
 * title), the primary key on field 'nid', a unique key named 'vid' on
 | 
					 | 
				
			||||||
 * field 'vid', and two indexes, one named 'nid' on field 'nid' and
 | 
					 | 
				
			||||||
 * one named 'node_title_type' on the field 'title' and the first four
 | 
					 | 
				
			||||||
 * bytes of the field 'type':
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @code
 | 
					 | 
				
			||||||
 * $schema['node'] = array(
 | 
					 | 
				
			||||||
 *   'fields' => array(
 | 
					 | 
				
			||||||
 *     'nid'      => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
 | 
					 | 
				
			||||||
 *     'vid'      => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
 | 
					 | 
				
			||||||
 *     'type'     => array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => ''),
 | 
					 | 
				
			||||||
 *     'title'    => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''),
 | 
					 | 
				
			||||||
 *   ),
 | 
					 | 
				
			||||||
 *   'primary key' => array('nid'),
 | 
					 | 
				
			||||||
 *   'unique keys' => array(
 | 
					 | 
				
			||||||
 *     'vid'     => array('vid')
 | 
					 | 
				
			||||||
 *   ),
 | 
					 | 
				
			||||||
 *   'indexes' => array(
 | 
					 | 
				
			||||||
 *     'nid'                 => array('nid'),
 | 
					 | 
				
			||||||
 *     'node_title_type'     => array('title', array('type', 4)),
 | 
					 | 
				
			||||||
 *   ),
 | 
					 | 
				
			||||||
 * );
 | 
					 | 
				
			||||||
 * @endcode
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @see drupal_install_schema()
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 /**
 | 
					 | 
				
			||||||
 * Create a new table from a Drupal table definition.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $ret
 | 
					 | 
				
			||||||
 *   Array to which query results will be added.
 | 
					 | 
				
			||||||
 * @param $name
 | 
					 | 
				
			||||||
 *   The name of the table to create.
 | 
					 | 
				
			||||||
 * @param $table
 | 
					 | 
				
			||||||
 *   A Schema API table definition array.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_create_table(&$ret, $name, $table) {
 | 
					 | 
				
			||||||
  $statements = db_create_table_sql($name, $table);
 | 
					 | 
				
			||||||
  foreach ($statements as $statement) {
 | 
					 | 
				
			||||||
    $ret[] = update_sql($statement);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Return an array of field names from an array of key/index column specifiers.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This is usually an identity function but if a key/index uses a column prefix
 | 
					 | 
				
			||||||
 * specification, this function extracts just the name.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $fields
 | 
					 | 
				
			||||||
 *   An array of key/index column specifiers.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   An array of field names.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_field_names($fields) {
 | 
					 | 
				
			||||||
  $ret = array();
 | 
					 | 
				
			||||||
  foreach ($fields as $field) {
 | 
					 | 
				
			||||||
    if (is_array($field)) {
 | 
					 | 
				
			||||||
      $ret[] = $field[0];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      $ret[] = $field;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return $ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Given a Schema API field type, return the correct %-placeholder.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Embed the placeholder in a query to be passed to db_query and and pass as an
 | 
					 | 
				
			||||||
 * argument to db_query a value of the specified type.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $type
 | 
					 | 
				
			||||||
 *   The Schema API type of a field.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   The placeholder string to embed in a query for that type.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_type_placeholder($type) {
 | 
					 | 
				
			||||||
  switch ($type) {
 | 
					 | 
				
			||||||
    case 'varchar':
 | 
					 | 
				
			||||||
    case 'char':
 | 
					 | 
				
			||||||
    case 'text':
 | 
					 | 
				
			||||||
    case 'datetime':
 | 
					 | 
				
			||||||
      return "'%s'";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case 'numeric':
 | 
					 | 
				
			||||||
      // Numeric values are arbitrary precision numbers.  Syntacically, numerics
 | 
					 | 
				
			||||||
      // should be specified directly in SQL. However, without single quotes
 | 
					 | 
				
			||||||
      // the %s placeholder does not protect against non-numeric characters such
 | 
					 | 
				
			||||||
      // as spaces which would expose us to SQL injection.
 | 
					 | 
				
			||||||
      return '%n';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case 'serial':
 | 
					 | 
				
			||||||
    case 'int':
 | 
					 | 
				
			||||||
      return '%d';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case 'float':
 | 
					 | 
				
			||||||
      return '%f';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case 'blob':
 | 
					 | 
				
			||||||
      return '%b';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // There is no safe value to return here, so return something that
 | 
					 | 
				
			||||||
  // will cause the query to fail.
 | 
					 | 
				
			||||||
  return 'unsupported type ' . $type . 'for db_type_placeholder';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @} End of "defgroup schemaapi".
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,533 +0,0 @@
 | 
				
			||||||
<?php
 | 
					 | 
				
			||||||
// $Id$
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * Functions shared between mysql and mysqli database engines.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Runs a basic query in the active database.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * User-supplied arguments to the query should be passed in as separate
 | 
					 | 
				
			||||||
 * parameters so that they can be properly escaped to avoid SQL injection
 | 
					 | 
				
			||||||
 * attacks.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $query
 | 
					 | 
				
			||||||
 *   A string containing an SQL query.
 | 
					 | 
				
			||||||
 * @param ...
 | 
					 | 
				
			||||||
 *   A variable number of arguments which are substituted into the query
 | 
					 | 
				
			||||||
 *   using printf() syntax. Instead of a variable number of query arguments,
 | 
					 | 
				
			||||||
 *   you may also pass a single array containing the query arguments.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
 | 
					 | 
				
			||||||
 *   in '') and %%.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
 | 
					 | 
				
			||||||
 *   and TRUE values to decimal 1.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   A database query result resource, or FALSE if the query was not
 | 
					 | 
				
			||||||
 *   executed correctly.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_query($query) {
 | 
					 | 
				
			||||||
  $args = func_get_args();
 | 
					 | 
				
			||||||
  array_shift($args);
 | 
					 | 
				
			||||||
  $query = db_prefix_tables($query);
 | 
					 | 
				
			||||||
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
 | 
					 | 
				
			||||||
    $args = $args[0];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  _db_query_callback($args, TRUE);
 | 
					 | 
				
			||||||
  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
 | 
					 | 
				
			||||||
  return _db_query($query);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @ingroup schemaapi
 | 
					 | 
				
			||||||
 * @{
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Generate SQL to create a new table from a Drupal schema definition.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $name
 | 
					 | 
				
			||||||
 *   The name of the table to create.
 | 
					 | 
				
			||||||
 * @param $table
 | 
					 | 
				
			||||||
 *   A Schema API table definition array.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   An array of SQL statements to create the table.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_create_table_sql($name, $table) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (empty($table['mysql_suffix'])) {
 | 
					 | 
				
			||||||
    $table['mysql_suffix'] = "/*!40100 DEFAULT CHARACTER SET UTF8 */";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $sql = "CREATE TABLE {" . $name . "} (\n";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Add the SQL statement for each field.
 | 
					 | 
				
			||||||
  foreach ($table['fields'] as $field_name => $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['precision'] . ', ' . $spec['scale'] . ')';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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',
 | 
					 | 
				
			||||||
    'char:normal'     => 'CHAR',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    'text:tiny'       => 'TINYTEXT',
 | 
					 | 
				
			||||||
    'text:small'      => 'TINYTEXT',
 | 
					 | 
				
			||||||
    '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'  => 'DECIMAL',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    '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()'));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,372 +0,0 @@
 | 
				
			||||||
<?php
 | 
					 | 
				
			||||||
// $Id$
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * Database interface code for MySQL database servers.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @ingroup database
 | 
					 | 
				
			||||||
 * @{
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Include functions shared between mysql and mysqli.
 | 
					 | 
				
			||||||
require_once './includes/database.mysql-common.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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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')) {
 | 
					 | 
				
			||||||
    _db_error_page('Unable to use the MySQL database because the MySQL extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Decode url-encoded information in the db connection string
 | 
					 | 
				
			||||||
  $url['user'] = urldecode($url['user']);
 | 
					 | 
				
			||||||
  // Test if database url has a password.
 | 
					 | 
				
			||||||
  $url['pass'] = isset($url['pass']) ? urldecode($url['pass']) : '';
 | 
					 | 
				
			||||||
  $url['host'] = urldecode($url['host']);
 | 
					 | 
				
			||||||
  $url['path'] = urldecode($url['path']);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Allow for non-standard MySQL port.
 | 
					 | 
				
			||||||
  if (isset($url['port'])) {
 | 
					 | 
				
			||||||
    $url['host'] = $url['host'] . ':' . $url['port'];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // - TRUE makes mysql_connect() always open a new link, even if
 | 
					 | 
				
			||||||
  //   mysql_connect() was called before with the same parameters.
 | 
					 | 
				
			||||||
  //   This is important if you are using two databases on the same
 | 
					 | 
				
			||||||
  //   server.
 | 
					 | 
				
			||||||
  // - 2 means CLIENT_FOUND_ROWS: return the number of found
 | 
					 | 
				
			||||||
  //   (matched) rows, not the number of affected rows.
 | 
					 | 
				
			||||||
  $connection = @mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2);
 | 
					 | 
				
			||||||
  if (!$connection || !mysql_select_db(substr($url['path'], 1))) {
 | 
					 | 
				
			||||||
    // Show error screen otherwise
 | 
					 | 
				
			||||||
    _db_error_page(mysql_error());
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  // Require ANSI mode to improve SQL portability.
 | 
					 | 
				
			||||||
  mysql_query("SET SESSION sql_mode='ANSI'", $connection);
 | 
					 | 
				
			||||||
  // Force UTF-8.
 | 
					 | 
				
			||||||
  mysql_query('SET NAMES "utf8"', $connection);
 | 
					 | 
				
			||||||
  return $connection;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Helper function for db_query().
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function _db_query($query, $debug = 0) {
 | 
					 | 
				
			||||||
  global $active_db, $queries, $user;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $result = mysql_query($query, $active_db);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (variable_get('dev_query', 0)) {
 | 
					 | 
				
			||||||
    $query = $bt[2]['function'] . "\n" . $query;
 | 
					 | 
				
			||||||
    list($usec, $sec) = explode(' ', microtime());
 | 
					 | 
				
			||||||
    $stop = (float)$usec + (float)$sec;
 | 
					 | 
				
			||||||
    $diff = $stop - $timer;
 | 
					 | 
				
			||||||
    $queries[] = array($query, $diff);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ($debug) {
 | 
					 | 
				
			||||||
    print '<p>query: ' . $query . '<br />error:' . mysql_error($active_db) . '</p>';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!mysql_errno($active_db)) {
 | 
					 | 
				
			||||||
    return $result;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    // Indicate to drupal_error_handler that this is a database error.
 | 
					 | 
				
			||||||
    ${DB_ERROR} = TRUE;
 | 
					 | 
				
			||||||
    trigger_error(check_plain(mysql_error($active_db) . "\nquery: " . $query), E_USER_WARNING);
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Fetch one result row from the previous query as an object.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $result
 | 
					 | 
				
			||||||
 *   A database query result resource, as returned from db_query().
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   An object representing the next row of the result, or FALSE. The attributes
 | 
					 | 
				
			||||||
 *   of this object are the table fields selected by the query.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_fetch_object($result) {
 | 
					 | 
				
			||||||
  if ($result) {
 | 
					 | 
				
			||||||
    return mysql_fetch_object($result);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Fetch one result row from the previous query as an array.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $result
 | 
					 | 
				
			||||||
 *   A database query result resource, as returned from db_query().
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   An associative array representing the next row of the result, or FALSE.
 | 
					 | 
				
			||||||
 *   The keys of this object are the names of the table fields selected by the
 | 
					 | 
				
			||||||
 *   query, and the values are the field values for this result row.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_fetch_array($result) {
 | 
					 | 
				
			||||||
  if ($result) {
 | 
					 | 
				
			||||||
    return mysql_fetch_array($result, MYSQL_ASSOC);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Return an individual result field from the previous query.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Only use this function if exactly one field is being selected; otherwise,
 | 
					 | 
				
			||||||
 * use db_fetch_object() or db_fetch_array().
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $result
 | 
					 | 
				
			||||||
 *   A database query result resource, as returned from db_query().
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   The resulting field or FALSE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_result($result) {
 | 
					 | 
				
			||||||
  if ($result && mysql_num_rows($result) > 0) {
 | 
					 | 
				
			||||||
    // The mysql_fetch_row function has an optional second parameter $row
 | 
					 | 
				
			||||||
    // but that can't be used for compatibility with Oracle, DB2, etc.
 | 
					 | 
				
			||||||
    $array = mysql_fetch_row($result);
 | 
					 | 
				
			||||||
    return $array[0];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return FALSE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Determine whether the previous query caused an error.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_error() {
 | 
					 | 
				
			||||||
  global $active_db;
 | 
					 | 
				
			||||||
  return mysql_errno($active_db);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Determine the number of rows changed by the preceding query.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_affected_rows() {
 | 
					 | 
				
			||||||
  global $active_db;
 | 
					 | 
				
			||||||
  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.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
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', db_prefix_tables($query));
 | 
					 | 
				
			||||||
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
 | 
					 | 
				
			||||||
    $args = $args[0];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  _db_query_callback($args, TRUE);
 | 
					 | 
				
			||||||
  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
 | 
					 | 
				
			||||||
  return _db_query($query);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Returns a properly formatted Binary Large OBject value.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $data
 | 
					 | 
				
			||||||
 *   Data to encode.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  Encoded data.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_encode_blob($data) {
 | 
					 | 
				
			||||||
  global $active_db;
 | 
					 | 
				
			||||||
  return "'" . mysql_real_escape_string($data, $active_db) . "'";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Returns text from a Binary Large Object value.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $data
 | 
					 | 
				
			||||||
 *   Data to decode.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  Decoded data.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_decode_blob($data) {
 | 
					 | 
				
			||||||
  return $data;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Prepare user input for use in a database query, preventing SQL injection attacks.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_escape_string($text) {
 | 
					 | 
				
			||||||
  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 (bool) db_fetch_object(db_query("SHOW TABLES LIKE '{" . db_escape_table($table) . "}'"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Check if a column exists in the given table.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_column_exists($table, $column) {
 | 
					 | 
				
			||||||
  return (bool) db_fetch_object(db_query("SHOW COLUMNS FROM {" . db_escape_table($table) . "} LIKE '" . db_escape_table($column) . "'"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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 . ')';
 | 
					 | 
				
			||||||
  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
 | 
					 | 
				
			||||||
  return preg_replace('/(SELECT.*)(?:' . $table . '\.|\s)(?<!DISTINCT\()(?<!DISTINCT\(' . $table . '\.)' . $field . '(.*FROM )/AUsi', '\1 ' . $field_to_select . '\2', $query);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @} End of "ingroup database".
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,376 +0,0 @@
 | 
				
			||||||
<?php
 | 
					 | 
				
			||||||
// $Id$
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * Database interface code for MySQL database servers using the mysqli client libraries. mysqli is included in PHP 5 by default and allows developers to use the advanced features of MySQL 4.1.x, 5.0.x and beyond.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 // Maintainers of this file should consult:
 | 
					 | 
				
			||||||
 // http://www.php.net/manual/en/ref.mysqli.php
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @ingroup database
 | 
					 | 
				
			||||||
 * @{
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Include functions shared between mysql and mysqli.
 | 
					 | 
				
			||||||
require_once './includes/database.mysql-common.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() {
 | 
					 | 
				
			||||||
  global $active_db;
 | 
					 | 
				
			||||||
  list($version) = explode('-', mysqli_get_server_info($active_db));
 | 
					 | 
				
			||||||
  return $version;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Initialise a database connection.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Note that mysqli does not support persistent connections.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_connect($url) {
 | 
					 | 
				
			||||||
  // Check if MySQLi support is present in PHP
 | 
					 | 
				
			||||||
  if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) {
 | 
					 | 
				
			||||||
    _db_error_page('Unable to use the MySQLi database because the MySQLi extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $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.
 | 
					 | 
				
			||||||
  $url['pass'] = isset($url['pass']) ? urldecode($url['pass']) : '';
 | 
					 | 
				
			||||||
  $url['host'] = urldecode($url['host']);
 | 
					 | 
				
			||||||
  $url['path'] = urldecode($url['path']);
 | 
					 | 
				
			||||||
  if (!isset($url['port'])) {
 | 
					 | 
				
			||||||
    $url['port'] = NULL;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $connection = mysqli_init();
 | 
					 | 
				
			||||||
  @mysqli_real_connect($connection, $url['host'], $url['user'], $url['pass'], substr($url['path'], 1), $url['port'], NULL, MYSQLI_CLIENT_FOUND_ROWS);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (mysqli_connect_errno() > 0) {
 | 
					 | 
				
			||||||
    _db_error_page(mysqli_connect_error());
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Force UTF-8.
 | 
					 | 
				
			||||||
  mysqli_query($connection, 'SET NAMES "utf8"');
 | 
					 | 
				
			||||||
  // Require ANSI mode to improve SQL portability.
 | 
					 | 
				
			||||||
  mysqli_query($connection, "SET SESSION sql_mode='ANSI'");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return $connection;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Helper function for db_query().
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function _db_query($query, $debug = 0) {
 | 
					 | 
				
			||||||
  global $active_db, $queries, $user;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $result = mysqli_query($active_db, $query);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (variable_get('dev_query', 0)) {
 | 
					 | 
				
			||||||
    $query = $bt[2]['function'] . "\n" . $query;
 | 
					 | 
				
			||||||
    list($usec, $sec) = explode(' ', microtime());
 | 
					 | 
				
			||||||
    $stop = (float)$usec + (float)$sec;
 | 
					 | 
				
			||||||
    $diff = $stop - $timer;
 | 
					 | 
				
			||||||
    $queries[] = array($query, $diff);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ($debug) {
 | 
					 | 
				
			||||||
    print '<p>query: ' . $query . '<br />error:' . mysqli_error($active_db) . '</p>';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!mysqli_errno($active_db)) {
 | 
					 | 
				
			||||||
    return $result;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    // Indicate to drupal_error_handler that this is a database error.
 | 
					 | 
				
			||||||
    ${DB_ERROR} = TRUE;
 | 
					 | 
				
			||||||
    trigger_error(check_plain(mysqli_error($active_db) . "\nquery: " . $query), E_USER_WARNING);
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Fetch one result row from the previous query as an object.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $result
 | 
					 | 
				
			||||||
 *   A database query result resource, as returned from db_query().
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   An object representing the next row of the result, or FALSE. The attributes
 | 
					 | 
				
			||||||
 *   of this object are the table fields selected by the query.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_fetch_object($result) {
 | 
					 | 
				
			||||||
  if ($result) {
 | 
					 | 
				
			||||||
    $object = mysqli_fetch_object($result);
 | 
					 | 
				
			||||||
    return isset($object) ? $object : FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Fetch one result row from the previous query as an array.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $result
 | 
					 | 
				
			||||||
 *   A database query result resource, as returned from db_query().
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   An associative array representing the next row of the result, or FALSE.
 | 
					 | 
				
			||||||
 *   The keys of this object are the names of the table fields selected by the
 | 
					 | 
				
			||||||
 *   query, and the values are the field values for this result row.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_fetch_array($result) {
 | 
					 | 
				
			||||||
  if ($result) {
 | 
					 | 
				
			||||||
    $array = mysqli_fetch_array($result, MYSQLI_ASSOC);
 | 
					 | 
				
			||||||
    return isset($array) ? $array : FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Return an individual result field from the previous query.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Only use this function if exactly one field is being selected; otherwise,
 | 
					 | 
				
			||||||
 * use db_fetch_object() or db_fetch_array().
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $result
 | 
					 | 
				
			||||||
 *   A database query result resource, as returned from db_query().
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   The resulting field or FALSE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_result($result) {
 | 
					 | 
				
			||||||
  if ($result && mysqli_num_rows($result) > 0) {
 | 
					 | 
				
			||||||
    // The mysqli_fetch_row function has an optional second parameter $row
 | 
					 | 
				
			||||||
    // but that can't be used for compatibility with Oracle, DB2, etc.
 | 
					 | 
				
			||||||
    $array = mysqli_fetch_row($result);
 | 
					 | 
				
			||||||
    return $array[0];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return FALSE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Determine whether the previous query caused an error.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_error() {
 | 
					 | 
				
			||||||
  global $active_db;
 | 
					 | 
				
			||||||
  return mysqli_errno($active_db);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Determine the number of rows changed by the preceding query.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_affected_rows() {
 | 
					 | 
				
			||||||
  global $active_db; /* mysqli connection resource */
 | 
					 | 
				
			||||||
  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.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
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', db_prefix_tables($query));
 | 
					 | 
				
			||||||
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
 | 
					 | 
				
			||||||
    $args = $args[0];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  _db_query_callback($args, TRUE);
 | 
					 | 
				
			||||||
  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
 | 
					 | 
				
			||||||
  return _db_query($query);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Returns a properly formatted Binary Large Object value.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $data
 | 
					 | 
				
			||||||
 *   Data to encode.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  Encoded data.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_encode_blob($data) {
 | 
					 | 
				
			||||||
  global $active_db;
 | 
					 | 
				
			||||||
  return "'" . mysqli_real_escape_string($active_db, $data) . "'";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Returns text from a Binary Large OBject value.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $data
 | 
					 | 
				
			||||||
 *   Data to decode.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  Decoded data.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_decode_blob($data) {
 | 
					 | 
				
			||||||
  return $data;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Prepare user input for use in a database query, preventing SQL injection attacks.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_escape_string($text) {
 | 
					 | 
				
			||||||
  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 (bool) db_fetch_object(db_query("SHOW TABLES LIKE '{" . db_escape_table($table) . "}'"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Check if a column exists in the given table.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_column_exists($table, $column) {
 | 
					 | 
				
			||||||
  return (bool) db_fetch_object(db_query("SHOW COLUMNS FROM {" . db_escape_table($table) . "} LIKE '" . db_escape_table($column) . "'"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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 . ')';
 | 
					 | 
				
			||||||
  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
 | 
					 | 
				
			||||||
  return preg_replace('/(SELECT.*)(?:' . $table . '\.|\s)(?<!DISTINCT\()(?<!DISTINCT\(' . $table . '\.)' . $field . '(.*FROM )/AUsi', '\1 ' . $field_to_select . '\2', $query);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @} End of "ingroup database".
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,949 +0,0 @@
 | 
				
			||||||
<?php
 | 
					 | 
				
			||||||
// $Id$
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 * Database interface code for PostgreSQL database servers.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @ingroup database
 | 
					 | 
				
			||||||
 * @{
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Report database status.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_status_report() {
 | 
					 | 
				
			||||||
  $t = get_t();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $version = db_version();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $form['pgsql'] = array(
 | 
					 | 
				
			||||||
    'title' => $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"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Initialize a database connection.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_connect($url) {
 | 
					 | 
				
			||||||
  // Check if PostgreSQL support is present in PHP
 | 
					 | 
				
			||||||
  if (!function_exists('pg_connect')) {
 | 
					 | 
				
			||||||
    _db_error_page('Unable to use the PostgreSQL database because the PostgreSQL extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $url = parse_url($url);
 | 
					 | 
				
			||||||
  $conn_string = '';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Decode url-encoded information in the db connection string
 | 
					 | 
				
			||||||
  if (isset($url['user'])) {
 | 
					 | 
				
			||||||
    $conn_string .= ' user=' . urldecode($url['user']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($url['pass'])) {
 | 
					 | 
				
			||||||
    $conn_string .= ' password=' . urldecode($url['pass']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($url['host'])) {
 | 
					 | 
				
			||||||
    $conn_string .= ' host=' . urldecode($url['host']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($url['path'])) {
 | 
					 | 
				
			||||||
    $conn_string .= ' dbname=' . substr(urldecode($url['path']), 1);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($url['port'])) {
 | 
					 | 
				
			||||||
    $conn_string .= ' port=' . urldecode($url['port']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // pg_last_error() does not return a useful error message for database
 | 
					 | 
				
			||||||
  // connection errors. We must turn on error tracking to get at a good error
 | 
					 | 
				
			||||||
  // message, which will be stored in $php_errormsg.
 | 
					 | 
				
			||||||
  $track_errors_previous = ini_get('track_errors');
 | 
					 | 
				
			||||||
  ini_set('track_errors', 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $connection = @pg_connect($conn_string);
 | 
					 | 
				
			||||||
  if (!$connection) {
 | 
					 | 
				
			||||||
    require_once './includes/unicode.inc';
 | 
					 | 
				
			||||||
    _db_error_page(decode_entities($php_errormsg));
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Restore error tracking setting
 | 
					 | 
				
			||||||
  ini_set('track_errors', $track_errors_previous);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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 %%.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
 | 
					 | 
				
			||||||
 *   and TRUE values to decimal 1.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   A database query result resource, or FALSE if the query was not
 | 
					 | 
				
			||||||
 *   executed correctly.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_query($query) {
 | 
					 | 
				
			||||||
  $args = func_get_args();
 | 
					 | 
				
			||||||
  array_shift($args);
 | 
					 | 
				
			||||||
  $query = db_prefix_tables($query);
 | 
					 | 
				
			||||||
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
 | 
					 | 
				
			||||||
    $args = $args[0];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  _db_query_callback($args, TRUE);
 | 
					 | 
				
			||||||
  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
 | 
					 | 
				
			||||||
  return _db_query($query);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Helper function for db_query().
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function _db_query($query, $debug = 0) {
 | 
					 | 
				
			||||||
  global $active_db, $last_result, $queries;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (variable_get('dev_query', 0)) {
 | 
					 | 
				
			||||||
    list($usec, $sec) = explode(' ', microtime());
 | 
					 | 
				
			||||||
    $timer = (float)$usec + (float)$sec;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $last_result = pg_query($active_db, $query);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (variable_get('dev_query', 0)) {
 | 
					 | 
				
			||||||
    $bt = debug_backtrace();
 | 
					 | 
				
			||||||
    $query = $bt[2]['function'] . "\n" . $query;
 | 
					 | 
				
			||||||
    list($usec, $sec) = explode(' ', microtime());
 | 
					 | 
				
			||||||
    $stop = (float)$usec + (float)$sec;
 | 
					 | 
				
			||||||
    $diff = $stop - $timer;
 | 
					 | 
				
			||||||
    $queries[] = array($query, $diff);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ($debug) {
 | 
					 | 
				
			||||||
    print '<p>query: ' . $query . '<br />error:' . pg_last_error($active_db) . '</p>';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ($last_result !== FALSE) {
 | 
					 | 
				
			||||||
    return $last_result;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    // Indicate to drupal_error_handler that this is a database error.
 | 
					 | 
				
			||||||
    ${DB_ERROR} = TRUE;
 | 
					 | 
				
			||||||
    trigger_error(check_plain(pg_last_error($active_db) . "\nquery: " . $query), E_USER_WARNING);
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Fetch one result row from the previous query as an object.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $result
 | 
					 | 
				
			||||||
 *   A database query result resource, as returned from db_query().
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   An object representing the next row of the result, or FALSE. The attributes
 | 
					 | 
				
			||||||
 *   of this object are the table fields selected by the query.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_fetch_object($result) {
 | 
					 | 
				
			||||||
  if ($result) {
 | 
					 | 
				
			||||||
    return pg_fetch_object($result);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Fetch one result row from the previous query as an array.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $result
 | 
					 | 
				
			||||||
 *   A database query result resource, as returned from db_query().
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   An associative array representing the next row of the result, or FALSE.
 | 
					 | 
				
			||||||
 *   The keys of this object are the names of the table fields selected by the
 | 
					 | 
				
			||||||
 *   query, and the values are the field values for this result row.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_fetch_array($result) {
 | 
					 | 
				
			||||||
  if ($result) {
 | 
					 | 
				
			||||||
    return pg_fetch_assoc($result);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Return an individual result field from the previous query.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Only use this function if exactly one field is being selected; otherwise,
 | 
					 | 
				
			||||||
 * use db_fetch_object() or db_fetch_array().
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $result
 | 
					 | 
				
			||||||
 *   A database query result resource, as returned from db_query().
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   The resulting field or FALSE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_result($result) {
 | 
					 | 
				
			||||||
  if ($result && pg_num_rows($result) > 0) {
 | 
					 | 
				
			||||||
    $array = pg_fetch_row($result);
 | 
					 | 
				
			||||||
    return $array[0];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return FALSE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Determine whether the previous query caused an error.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_error() {
 | 
					 | 
				
			||||||
  global $active_db;
 | 
					 | 
				
			||||||
  return pg_last_error($active_db);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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('{" . db_escape_table($table) . "}_" . db_escape_table($field) . "_seq')"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Determine the number of rows changed by the preceding query.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_affected_rows() {
 | 
					 | 
				
			||||||
  global $last_result;
 | 
					 | 
				
			||||||
  return empty($last_result) ? 0 : pg_affected_rows($last_result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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 %%.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *   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 = db_prefix_tables($query);
 | 
					 | 
				
			||||||
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
 | 
					 | 
				
			||||||
    $args = $args[0];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  _db_query_callback($args, TRUE);
 | 
					 | 
				
			||||||
  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
 | 
					 | 
				
			||||||
  $query .= ' LIMIT ' . (int)$count . ' OFFSET ' . (int)$from;
 | 
					 | 
				
			||||||
  return _db_query($query);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Runs a SELECT query and stores its results in a temporary table.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Use this as a substitute for db_query() when the results need to stored
 | 
					 | 
				
			||||||
 * in a temporary table. Temporary tables exist for the duration of the page
 | 
					 | 
				
			||||||
 * request.
 | 
					 | 
				
			||||||
 * User-supplied arguments to the query should be passed in as separate parameters
 | 
					 | 
				
			||||||
 * so that they can be properly escaped to avoid SQL injection attacks.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Note that if you need to know how many results were returned, you should do
 | 
					 | 
				
			||||||
 * a SELECT COUNT(*) on the temporary table afterwards. db_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.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_query_temporary($query) {
 | 
					 | 
				
			||||||
  $args = func_get_args();
 | 
					 | 
				
			||||||
  $tablename = array_pop($args);
 | 
					 | 
				
			||||||
  array_shift($args);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE ' . $tablename . ' AS SELECT', db_prefix_tables($query));
 | 
					 | 
				
			||||||
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
 | 
					 | 
				
			||||||
    $args = $args[0];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  _db_query_callback($args, TRUE);
 | 
					 | 
				
			||||||
  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
 | 
					 | 
				
			||||||
  return _db_query($query);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Returns a properly formatted Binary Large OBject value.
 | 
					 | 
				
			||||||
 * In case of PostgreSQL encodes data for insert into bytea field.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $data
 | 
					 | 
				
			||||||
 *   Data to encode.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  Encoded data.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_encode_blob($data) {
 | 
					 | 
				
			||||||
  return "'" . pg_escape_bytea($data) . "'";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Returns text from a Binary Large OBject value.
 | 
					 | 
				
			||||||
 * In case of PostgreSQL decodes data after select from bytea field.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $data
 | 
					 | 
				
			||||||
 *   Data to decode.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  Decoded data.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_decode_blob($data) {
 | 
					 | 
				
			||||||
  return pg_unescape_bytea($data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Prepare user input for use in a database query, preventing SQL injection attacks.
 | 
					 | 
				
			||||||
 * Note: This function requires PostgreSQL 7.2 or later.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_escape_string($text) {
 | 
					 | 
				
			||||||
  return pg_escape_string($text);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Lock a table.
 | 
					 | 
				
			||||||
 * This function automatically starts a transaction.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_lock_table($table) {
 | 
					 | 
				
			||||||
  db_query('BEGIN; 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 (bool) db_result(db_query("SELECT COUNT(*) FROM pg_class WHERE relname = '{" . db_escape_table($table) . "}'"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Check if a column exists in the given table.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_column_exists($table, $column) {
 | 
					 | 
				
			||||||
  return (bool) db_result(db_query("SELECT COUNT(pg_attribute.attname) FROM pg_class, pg_attribute WHERE pg_attribute.attrelid = pg_class.oid AND pg_class.relname = '{" . db_escape_table($table) . "}' AND attname = '" . db_escape_table($column) . "'"));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Verify if the database is set up correctly.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_check_setup() {
 | 
					 | 
				
			||||||
  $t = get_t();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $encoding = db_result(db_query('SHOW server_encoding'));
 | 
					 | 
				
			||||||
  if (!in_array(strtolower($encoding), array('unicode', 'utf8'))) {
 | 
					 | 
				
			||||||
    drupal_set_message($t('Your PostgreSQL database is set up with the wrong character encoding (%encoding). It is possible it will not work as expected. It is advised to recreate it with UTF-8/Unicode encoding. More information can be found in the <a href="@url">PostgreSQL documentation</a>.', array('%encoding' => $encoding, '@url' => 'http://www.postgresql.org/docs/7.4/interactive/multibyte.html')), 'status');
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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";
 | 
					 | 
				
			||||||
  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
 | 
					 | 
				
			||||||
  $query = preg_replace('/(SELECT.*)(?:' . $table . '\.|\s)(?<!DISTINCT\()(?<!DISTINCT\(' . $table . '\.)' . $field . '(.*FROM )/AUsi', '\1 ' . $field_to_select . '\2', $query);
 | 
					 | 
				
			||||||
  $query = preg_replace('/(ORDER BY )(?!' . $table . '\.' . $field . ')/', '\1' . "$table.$field, ", $query);
 | 
					 | 
				
			||||||
  return $query;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @} End of "ingroup database".
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @ingroup schemaapi
 | 
					 | 
				
			||||||
 * @{
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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',
 | 
					 | 
				
			||||||
    'char:normal' => 'character',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    'text:tiny' => 'text',
 | 
					 | 
				
			||||||
    'text:small' => 'text',
 | 
					 | 
				
			||||||
    'text:medium' => 'text',
 | 
					 | 
				
			||||||
    'text:big' => 'text',
 | 
					 | 
				
			||||||
    'text:normal' => 'text',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    'int:tiny' => 'smallint',
 | 
					 | 
				
			||||||
    'int:small' => 'smallint',
 | 
					 | 
				
			||||||
    'int:medium' => 'int',
 | 
					 | 
				
			||||||
    'int:big' => 'bigint',
 | 
					 | 
				
			||||||
    'int:normal' => 'int',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    'float:tiny' => 'real',
 | 
					 | 
				
			||||||
    'float:small' => 'real',
 | 
					 | 
				
			||||||
    'float:medium' => 'real',
 | 
					 | 
				
			||||||
    'float:big' => 'double precision',
 | 
					 | 
				
			||||||
    'float:normal' => 'real',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    'numeric:normal' => 'numeric',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    'blob:big' => 'bytea',
 | 
					 | 
				
			||||||
    'blob:normal' => 'bytea',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    'datetime:normal' => 'timestamp',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    'serial:tiny' => 'serial',
 | 
					 | 
				
			||||||
    'serial:small' => 'serial',
 | 
					 | 
				
			||||||
    'serial:medium' => 'serial',
 | 
					 | 
				
			||||||
    'serial:big' => 'bigserial',
 | 
					 | 
				
			||||||
    'serial:normal' => 'serial',
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
  return $map;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Generate SQL to create a new table from a Drupal schema definition.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $name
 | 
					 | 
				
			||||||
 *   The name of the table to create.
 | 
					 | 
				
			||||||
 * @param $table
 | 
					 | 
				
			||||||
 *   A Schema API table definition array.
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *   An array of SQL statements to create the table.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_create_table_sql($name, $table) {
 | 
					 | 
				
			||||||
  $sql_fields = array();
 | 
					 | 
				
			||||||
  foreach ($table['fields'] as $field_name => $field) {
 | 
					 | 
				
			||||||
    $sql_fields[] = _db_create_field_sql($field_name, _db_process_field($field));
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $sql_keys = array();
 | 
					 | 
				
			||||||
  if (isset($table['primary key']) && is_array($table['primary key'])) {
 | 
					 | 
				
			||||||
    $sql_keys[] = 'PRIMARY KEY (' . implode(', ', $table['primary key']) . ')';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($table['unique keys']) && is_array($table['unique keys'])) {
 | 
					 | 
				
			||||||
    foreach ($table['unique keys'] as $key_name => $key) {
 | 
					 | 
				
			||||||
      $sql_keys[] = 'CONSTRAINT {' . $name . '}_' . $key_name . '_key UNIQUE (' . implode(', ', $key) . ')';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $sql = "CREATE TABLE {" . $name . "} (\n\t";
 | 
					 | 
				
			||||||
  $sql .= implode(",\n\t", $sql_fields);
 | 
					 | 
				
			||||||
  if (count($sql_keys) > 0) {
 | 
					 | 
				
			||||||
    $sql .= ",\n\t";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  $sql .= implode(",\n\t", $sql_keys);
 | 
					 | 
				
			||||||
  $sql .= "\n)";
 | 
					 | 
				
			||||||
  $statements[] = $sql;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (isset($table['indexes']) && is_array($table['indexes'])) {
 | 
					 | 
				
			||||||
    foreach ($table['indexes'] as $key_name => $key) {
 | 
					 | 
				
			||||||
      $statements[] = _db_create_index_sql($name, $key_name, $key);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return $statements;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function _db_create_index_sql($table, $name, $fields) {
 | 
					 | 
				
			||||||
  $query = 'CREATE INDEX {' . $table . '}_' . $name . '_idx ON {' . $table . '} (';
 | 
					 | 
				
			||||||
  $query .= _db_create_key_sql($fields) . ')';
 | 
					 | 
				
			||||||
  return $query;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function _db_create_key_sql($fields) {
 | 
					 | 
				
			||||||
  $ret = array();
 | 
					 | 
				
			||||||
  foreach ($fields as $field) {
 | 
					 | 
				
			||||||
    if (is_array($field)) {
 | 
					 | 
				
			||||||
      $ret[] = 'substr(' . $field[0] . ', 1, ' . $field[1] . ')';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      $ret[] = $field;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return implode(', ', $ret);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function _db_create_keys(&$ret, $table, $new_keys) {
 | 
					 | 
				
			||||||
  if (isset($new_keys['primary key'])) {
 | 
					 | 
				
			||||||
    db_add_primary_key($ret, $table, $new_keys['primary key']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($new_keys['unique keys'])) {
 | 
					 | 
				
			||||||
    foreach ($new_keys['unique keys'] as $name => $fields) {
 | 
					 | 
				
			||||||
      db_add_unique_key($ret, $table, $name, $fields);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($new_keys['indexes'])) {
 | 
					 | 
				
			||||||
    foreach ($new_keys['indexes'] as $name => $fields) {
 | 
					 | 
				
			||||||
      db_add_index($ret, $table, $name, $fields);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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['pgsql_type'])) {
 | 
					 | 
				
			||||||
    $map = db_type_map();
 | 
					 | 
				
			||||||
    $field['pgsql_type'] = $map[$field['type'] . ':' . $field['size']];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if ($field['type'] == 'serial') {
 | 
					 | 
				
			||||||
    unset($field['not null']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  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['pgsql_type'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ($spec['type'] == 'serial') {
 | 
					 | 
				
			||||||
    unset($spec['not null']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // pgsql does not have unsigned types but supports constraints to
 | 
					 | 
				
			||||||
  // restricted a signed field to be non-negative (e.g. CHECK (VALUE
 | 
					 | 
				
			||||||
  // >= 0)).  system.module defines {,small,big}int_unsigned as the
 | 
					 | 
				
			||||||
  // corresponding integer type with this constraint but does not do
 | 
					 | 
				
			||||||
  // so for serial or numeric types.  It probably would have been
 | 
					 | 
				
			||||||
  // cleaner to unify unsigned handling but, for now, we use the
 | 
					 | 
				
			||||||
  // *int_unsigned types for int and otherwise apply a column
 | 
					 | 
				
			||||||
  // constraint explicitly.
 | 
					 | 
				
			||||||
  if (!empty($spec['unsigned'])) {
 | 
					 | 
				
			||||||
    switch ($spec['type']) {
 | 
					 | 
				
			||||||
      case 'int':
 | 
					 | 
				
			||||||
        $sql .= '_unsigned';
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      case 'serial':
 | 
					 | 
				
			||||||
      case 'float':
 | 
					 | 
				
			||||||
        $sql .= " CHECK ($name >= 0)";
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      case 'numeric':
 | 
					 | 
				
			||||||
        // handled below
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      default:
 | 
					 | 
				
			||||||
        // unsigned is not supported on other column types
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!empty($spec['length'])) {
 | 
					 | 
				
			||||||
    $sql .= '(' . $spec['length'] . ')';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  elseif (isset($spec['precision']) && isset($spec['scale'])) {
 | 
					 | 
				
			||||||
    $sql .= '(' . $spec['precision'] . ', ' . $spec['scale'] . ')';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // For numeric columns this has to come after (precision,scale).
 | 
					 | 
				
			||||||
  if ($spec['type'] == 'numeric' && !empty($spec['unsigned'])) {
 | 
					 | 
				
			||||||
    $sql .= " CHECK ($name >= 0)";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (isset($spec['not null']) && $spec['not null']) {
 | 
					 | 
				
			||||||
    $sql .= ' NOT NULL';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($spec['default'])) {
 | 
					 | 
				
			||||||
    $default = is_string($spec['default']) ? "'" . $spec['default'] . "'" : $spec['default'];
 | 
					 | 
				
			||||||
    $sql .= " default $default";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return $sql;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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, $new_keys = array()) {
 | 
					 | 
				
			||||||
  $fixnull = FALSE;
 | 
					 | 
				
			||||||
  if (!empty($spec['not null']) && !isset($spec['default'])) {
 | 
					 | 
				
			||||||
    $fixnull = TRUE;
 | 
					 | 
				
			||||||
    $spec['not null'] = FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  $query = 'ALTER TABLE {' . $table . '} ADD COLUMN ';
 | 
					 | 
				
			||||||
  $query .= _db_create_field_sql($field, _db_process_field($spec));
 | 
					 | 
				
			||||||
  $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) {
 | 
					 | 
				
			||||||
    $ret[] = update_sql("ALTER TABLE {" . $table . "} ALTER $field SET NOT NULL");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($new_keys)) {
 | 
					 | 
				
			||||||
    _db_create_keys($ret, $table, $new_keys);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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 COLUMN ' . $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 (' .
 | 
					 | 
				
			||||||
    implode(',', $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 CONSTRAINT {' . $table . '}_pkey');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 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) {
 | 
					 | 
				
			||||||
  $name = '{' . $table . '}_' . $name . '_key';
 | 
					 | 
				
			||||||
  $ret[] = update_sql('ALTER TABLE {' . $table . '} ADD CONSTRAINT ' .
 | 
					 | 
				
			||||||
    $name . ' UNIQUE (' . implode(',', $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) {
 | 
					 | 
				
			||||||
  $name = '{' . $table . '}_' . $name . '_key';
 | 
					 | 
				
			||||||
  $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $name);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Add an index.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $ret
 | 
					 | 
				
			||||||
 *   Array to which query results will be added.
 | 
					 | 
				
			||||||
 * @param $table
 | 
					 | 
				
			||||||
 *   The table to be altered.
 | 
					 | 
				
			||||||
 * @param $name
 | 
					 | 
				
			||||||
 *   The name of the index.
 | 
					 | 
				
			||||||
 * @param $fields
 | 
					 | 
				
			||||||
 *   An array of field names.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_add_index(&$ret, $table, $name, $fields) {
 | 
					 | 
				
			||||||
  $ret[] = update_sql(_db_create_index_sql($table, $name, $fields));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Drop an index.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param $ret
 | 
					 | 
				
			||||||
 *   Array to which query results will be added.
 | 
					 | 
				
			||||||
 * @param $table
 | 
					 | 
				
			||||||
 *   The table to be altered.
 | 
					 | 
				
			||||||
 * @param $name
 | 
					 | 
				
			||||||
 *   The name of the index.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function db_drop_index(&$ret, $table, $name) {
 | 
					 | 
				
			||||||
  $name = '{' . $table . '}_' . $name . '_idx';
 | 
					 | 
				
			||||||
  $ret[] = update_sql('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 $new_keys 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
 | 
					 | 
				
			||||||
 * $new_keys 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 $new_keys 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 $new_keys
 | 
					 | 
				
			||||||
 *   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, $new_keys = array()) {
 | 
					 | 
				
			||||||
  $ret[] = update_sql("ALTER TABLE {" . $table . "} RENAME $field TO " . $field . "_old");
 | 
					 | 
				
			||||||
  $not_null = isset($spec['not null']) ? $spec['not null'] : FALSE;
 | 
					 | 
				
			||||||
  unset($spec['not null']);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  db_add_field($ret, $table, "$field_new", $spec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $ret[] = update_sql("UPDATE {" . $table . "} SET $field_new = " . $field . "_old");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ($not_null) {
 | 
					 | 
				
			||||||
    $ret[] = update_sql("ALTER TABLE {" . $table . "} ALTER $field_new SET NOT NULL");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  db_drop_field($ret, $table, $field . '_old');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (isset($new_keys)) {
 | 
					 | 
				
			||||||
    _db_create_keys($ret, $table, $new_keys);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @} End of "ingroup schemaapi".
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,82 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					// $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file
 | 
				
			||||||
 | 
					 * Database interface code for MySQL database servers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup database
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DatabaseConnection_mysql extends DatabaseConnection {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected $transactionSupport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function __construct(Array $connection_options = array()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $connection_options += array(
 | 
				
			||||||
 | 
					      'transactions' => FALSE,
 | 
				
			||||||
 | 
					      'port' => 3306,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    $this->transactionSupport = $connection_options['transactions'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $dsn = 'mysql:host=' . $connection_options['host'] . ';port=' . $connection_options['port'] . ';dbname=' . $connection_options['database'];
 | 
				
			||||||
 | 
					    parent::__construct($dsn, $connection_options['username'], $connection_options['password'], array(
 | 
				
			||||||
 | 
					      // So we don't have to mess around with cursors and unbuffered queries by default.
 | 
				
			||||||
 | 
					      PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
 | 
				
			||||||
 | 
					      // Because MySQL's prepared statements skip the query cache, because it's dumb.
 | 
				
			||||||
 | 
					      PDO::ATTR_EMULATE_PREPARES => TRUE,
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function queryRange($query, Array $args, $from, $count, Array $options) {
 | 
				
			||||||
 | 
					    // Backward compatibility hack, temporary.
 | 
				
			||||||
 | 
					    $query = str_replace(array('%d' , '%f' , '%b' , "'%s'"), '?', $query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $this->query($query . ' LIMIT ' . $from . ', ' . $count, $args, $options);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function queryTemporary($query, Array $args, $tablename) {
 | 
				
			||||||
 | 
					    $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE ' . $tablename . ' Engine=HEAP SELECT', $this->prefixTables($query));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $this->query($query, $args, $options);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function driver() {
 | 
				
			||||||
 | 
					    return 'mysql';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function databaseType() {
 | 
				
			||||||
 | 
					    return 'mysql';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function supportsTransactions() {
 | 
				
			||||||
 | 
					    return $this->transactionSupport;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function escapeTable($table) {
 | 
				
			||||||
 | 
					    return preg_replace('/[^A-Za-z0-9_]+/', '', $table);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function mapConditionOperator($operator) {
 | 
				
			||||||
 | 
					    // We don't want to override any of the defaults.
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * @todo Remove this as soon as db_rewrite_sql() has been exterminated.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function distinctField($table, $field, $query) {
 | 
				
			||||||
 | 
					    $field_to_select = 'DISTINCT(' . $table . '.' . $field . ')';
 | 
				
			||||||
 | 
					    // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
 | 
				
			||||||
 | 
					    return preg_replace('/(SELECT.*)(?:' . $table . '\.|\s)(?<!DISTINCT\()(?<!DISTINCT\(' . $table . '\.)' . $field . '(.*FROM )/AUsi', '\1 ' . $field_to_select . '\2', $query);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @} End of "ingroup database".
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					// $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MySQL specific install functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DatabaseInstaller_mysql extends DatabaseInstaller {
 | 
				
			||||||
 | 
					  protected $pdoDriver = 'mysql';
 | 
				
			||||||
 | 
					  public function name() {
 | 
				
			||||||
 | 
					    return 'MySQL';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,172 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					// $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup database
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class InsertQuery_mysql extends InsertQuery {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function execute() {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Confirm that the user did not try to specify an identical
 | 
				
			||||||
 | 
					    //  field and default field.
 | 
				
			||||||
 | 
					    if (array_intersect($this->insertFields, $this->defaultFields)) {
 | 
				
			||||||
 | 
					      throw new PDOException('You may not specify the same field to have a value and a schema-default value.');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $last_insert_id = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $max_placeholder = 0;
 | 
				
			||||||
 | 
					    $values = array();
 | 
				
			||||||
 | 
					    foreach ($this->insertValues as $insert_values) {
 | 
				
			||||||
 | 
					      foreach ($insert_values as $value) {
 | 
				
			||||||
 | 
					        $values[':db_insert_placeholder_' . $max_placeholder++] = $value;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $last_insert_id = $this->connection->query((string)$this, $values, $this->queryOptions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Re-initialize the values array so that we can re-use this query.
 | 
				
			||||||
 | 
					    $this->insertValues = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $last_insert_id;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function __toString() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $delay = $this->queryOptions['delay'] ? 'DELAYED' : '';
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Default fields are always placed first for consistency.
 | 
				
			||||||
 | 
					    $insert_fields = array_merge($this->defaultFields, $this->insertFields);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $query = "INSERT $delay INTO {" . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES ';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $max_placeholder = 0;
 | 
				
			||||||
 | 
					    $values = array();
 | 
				
			||||||
 | 
					    if (count($this->insertValues)) {
 | 
				
			||||||
 | 
					      foreach ($this->insertValues as $insert_values) {
 | 
				
			||||||
 | 
					        $placeholders = array();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Default fields aren't really placeholders, but this is the most convenient
 | 
				
			||||||
 | 
					        // way to handle them.
 | 
				
			||||||
 | 
					        $placeholders = array_pad($placeholders, count($this->defaultFields), 'default');
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $new_placeholder = $max_placeholder + count($insert_values);
 | 
				
			||||||
 | 
					        for ($i = $max_placeholder; $i < $new_placeholder; ++$i) {
 | 
				
			||||||
 | 
					          $placeholders[] = ':db_insert_placeholder_'. $i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $max_placeholder = $new_placeholder;
 | 
				
			||||||
 | 
					        $values[] = '('. implode(', ', $placeholders) .')';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      // If there are no values, then this is a default-only query.  We still need to handle that.
 | 
				
			||||||
 | 
					      $placeholders = array_fill(0, count($this->defaultFields), 'default');
 | 
				
			||||||
 | 
					      $values[] = '(' . implode(', ', $placeholders) .')';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $query .= implode(', ', $values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $query;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MergeQuery_mysql extends MergeQuery {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function execute() {
 | 
				
			||||||
 | 
					    // Set defaults.
 | 
				
			||||||
 | 
					    if ($this->updateFields) {
 | 
				
			||||||
 | 
					      $update_fields = $this->updateFields;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      $update_fields = $this->insertFields;
 | 
				
			||||||
 | 
					      // If there are no exclude fields, this is a no-op.
 | 
				
			||||||
 | 
					      foreach ($this->excludeFields as $exclude_field) {
 | 
				
			||||||
 | 
					        unset($update_fields[$exclude_field]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $insert_fields = $this->insertFields + $this->keyFields;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $max_placeholder = 0;
 | 
				
			||||||
 | 
					    $values = array();
 | 
				
			||||||
 | 
					    // We assume that the order here is the same as in __toString().  If that's
 | 
				
			||||||
 | 
					    // not the case, then we have serious problems.
 | 
				
			||||||
 | 
					    foreach ($insert_fields as $value) {
 | 
				
			||||||
 | 
					      $values[':db_insert_placeholder_' . $max_placeholder++] = $value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Expressions take priority over literal fields, so we process those first
 | 
				
			||||||
 | 
					    // and remove any literal fields that conflict.
 | 
				
			||||||
 | 
					    foreach ($this->expressionFields as $field => $data) {
 | 
				
			||||||
 | 
					      if (!empty($data['arguments'])) {
 | 
				
			||||||
 | 
					        $values += $data['arguments'];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      unset($update_fields[$field]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Because we filter $fields the same way here and in __toString(), the
 | 
				
			||||||
 | 
					    // placeholders will all match up properly.
 | 
				
			||||||
 | 
					    $max_placeholder = 0;
 | 
				
			||||||
 | 
					    foreach ($update_fields as $field => $value) {
 | 
				
			||||||
 | 
					      $values[':db_update_placeholder_' . ($max_placeholder++)] = $value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $last_insert_id = $this->connection->query((string)$this, $values, $this->queryOptions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $last_insert_id;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function __toString() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Set defaults.
 | 
				
			||||||
 | 
					    $update_fields = array();
 | 
				
			||||||
 | 
					    if ($this->updateFields) {
 | 
				
			||||||
 | 
					      $update_fields = $this->updateFields;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      $update_fields = $this->insertFields;
 | 
				
			||||||
 | 
					      // If there are no exclude fields, this is a no-op.
 | 
				
			||||||
 | 
					      foreach ($this->excludeFields as $exclude_field) {
 | 
				
			||||||
 | 
					        unset($update_fields[$exclude_field]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $insert_fields = $this->insertFields + $this->keyFields;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $query = "INSERT INTO {" . $this->table . '} (' . implode(', ', array_keys($insert_fields)) . ') VALUES ';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $max_placeholder = 0;
 | 
				
			||||||
 | 
					    $values = array();
 | 
				
			||||||
 | 
					    // We don't need the $field, but this is a convenient way to count.
 | 
				
			||||||
 | 
					    foreach ($insert_fields as $field) {
 | 
				
			||||||
 | 
					      $values[] = ':db_insert_placeholder_' . $max_placeholder++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $query .= '(' . implode(', ', $values) . ') ON DUPLICATE KEY UPDATE ';
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Expressions take priority over literal fields, so we process those first
 | 
				
			||||||
 | 
					    // and remove any literal fields that conflict.
 | 
				
			||||||
 | 
					    $max_placeholder = 0;
 | 
				
			||||||
 | 
					    $update = array();
 | 
				
			||||||
 | 
					    foreach ($this->expressionFields as $field => $data) {
 | 
				
			||||||
 | 
					      $update[] = $field . '=' . $data['expression'];
 | 
				
			||||||
 | 
					      unset($update_fields[$field]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    foreach ($update_fields as $field => $value) {
 | 
				
			||||||
 | 
					      $update[] = ($field . '=:db_update_placeholder_' . $max_placeholder++);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $query .= implode(', ', $update);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $query;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @} End of "ingroup database".
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,313 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					// $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file
 | 
				
			||||||
 | 
					 * Database schema code for MySQL database servers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup schemaapi
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DatabaseSchema_mysql extends DatabaseSchema {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function tableExists($table) {
 | 
				
			||||||
 | 
					    return (bool) $this->connection->query("SHOW TABLES LIKE '{" . $table . "}'", array(), array())->fetchField();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function columnExists($table, $column) {
 | 
				
			||||||
 | 
					    return (bool) $this->connection->query("SHOW COLUMNS FROM {" . $this->escapeTable($table) . "} LIKE '" . $this->escapeTable($column) . "'", array(), array())->fetchField();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Generate SQL to create a new table from a Drupal schema definition.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $name
 | 
				
			||||||
 | 
					   *   The name of the table to create.
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   A Schema API table definition array.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   An array of SQL statements to create the table.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function createTableSql($name, $table) {
 | 
				
			||||||
 | 
					    if (empty($table['mysql_suffix'])) {
 | 
				
			||||||
 | 
					      $table['mysql_suffix'] = "/*!40100 DEFAULT CHARACTER SET UTF8 */";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    $sql = "CREATE TABLE {" . $name . "} (\n";
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    // Add the SQL statement for each field.
 | 
				
			||||||
 | 
					    foreach ($table['fields'] as $field_name => $field) {
 | 
				
			||||||
 | 
					      $sql .= $this->createFieldSql($field_name, $this->processField($field)) . ", \n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    // Process keys & indexes.
 | 
				
			||||||
 | 
					    $keys = $this->createKeysSql($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);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function createFieldSql($name, $spec) {
 | 
				
			||||||
 | 
					    $sql = "`" . $name . "` " . $spec['mysql_type'];
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    if (isset($spec['length'])) {
 | 
				
			||||||
 | 
					      $sql .= '(' . $spec['length'] . ')';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    elseif (isset($spec['precision']) && isset($spec['scale'])) {
 | 
				
			||||||
 | 
					      $sql .= '(' . $spec['precision'] . ', ' . $spec['scale'] . ')';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    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;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Set database-engine specific properties for a field.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $field
 | 
				
			||||||
 | 
					   *   A field description array, as specified in the schema documentation.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function processField($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;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function getFieldTypeMap() {
 | 
				
			||||||
 | 
					    // 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.
 | 
				
			||||||
 | 
					    static $map = array(
 | 
				
			||||||
 | 
					      'varchar:normal'  => 'VARCHAR',
 | 
				
			||||||
 | 
					      'char:normal'     => 'CHAR',
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					      'text:tiny'       => 'TINYTEXT',
 | 
				
			||||||
 | 
					      'text:small'      => 'TINYTEXT',
 | 
				
			||||||
 | 
					      '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'  => 'DECIMAL',
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					      'blob:big'        => 'LONGBLOB',
 | 
				
			||||||
 | 
					      'blob:normal'     => 'BLOB',
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					      'datetime:normal' => 'DATETIME',
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    return $map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function createKeysSql($spec) {
 | 
				
			||||||
 | 
					    $keys = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!empty($spec['primary key'])) {
 | 
				
			||||||
 | 
					      $keys[] = 'PRIMARY KEY (' . $this->createKeysSqlHelper($spec['primary key']) . ')';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!empty($spec['unique keys'])) {
 | 
				
			||||||
 | 
					      foreach ($spec['unique keys'] as $key => $fields) {
 | 
				
			||||||
 | 
					        $keys[] = 'UNIQUE KEY ' . $key .' ('. $this->createKeysSqlHelper($fields) . ')';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!empty($spec['indexes'])) {
 | 
				
			||||||
 | 
					      foreach ($spec['indexes'] as $index => $fields) {
 | 
				
			||||||
 | 
					        $keys[] = 'INDEX ' . $index . ' (' . $this->createKeysSqlHelper($fields) . ')';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $keys;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  protected function createKeySql($fields) {
 | 
				
			||||||
 | 
					    $ret = array();
 | 
				
			||||||
 | 
					    foreach ($fields as $field) {
 | 
				
			||||||
 | 
					      if (is_array($field)) {
 | 
				
			||||||
 | 
					        $ret[] = $field[0] . '(' . $field[1] . ')';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else {
 | 
				
			||||||
 | 
					        $ret[] = $field;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return implode(', ', $ret);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function createKeysSqlHelper($fields) {
 | 
				
			||||||
 | 
					    $ret = array();
 | 
				
			||||||
 | 
					    foreach ($fields as $field) {
 | 
				
			||||||
 | 
					      if (is_array($field)) {
 | 
				
			||||||
 | 
					        $ret[] = $field[0] . '(' . $field[1] . ')';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else {
 | 
				
			||||||
 | 
					        $ret[] = $field;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return implode(', ', $ret);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function renameTable(&$ret, $table, $new_name) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} RENAME TO {' . $new_name . '}');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function dropTable(&$ret, $table) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('DROP TABLE {' . $table . '}');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function addField(&$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 .= $this->createFieldSql($field, $this->processField($spec));
 | 
				
			||||||
 | 
					    if (count($keys_new)) {
 | 
				
			||||||
 | 
					      $query .= ', ADD ' . implode(', ADD ', $this->createKeysSql($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;
 | 
				
			||||||
 | 
					      $this->changeField($ret, $table, $field, $field, $spec);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function dropField(&$ret, $table, $field) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP ' . $field);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function fieldSetDefault(&$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);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function fieldSetNoDefault(&$ret, $table, $field) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} ALTER COLUMN ' . $field . ' DROP DEFAULT');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function addPrimaryKey(&$ret, $table, $fields) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . $this->createKeySql($fields) . ')');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function dropPrimaryKey(&$ret, $table) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP PRIMARY KEY');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function addUniqueKey(&$ret, $table, $name, $fields) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} ADD UNIQUE KEY ' . $name . ' (' . $this->createKeySql($fields) . ')');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function dropUniqueKey(&$ret, $table, $name) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP KEY ' . $name);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function addIndex(&$ret, $table, $name, $fields) {
 | 
				
			||||||
 | 
					    $query = 'ALTER TABLE {' . $table . '} ADD INDEX ' . $name . ' (' . $this->createKeySql($fields) . ')';
 | 
				
			||||||
 | 
					    $ret[] = update_sql($query);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function dropIndex(&$ret, $table, $name) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP INDEX ' . $name);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function changeField(&$ret, $table, $field, $field_new, $spec, $keys_new = array()) {
 | 
				
			||||||
 | 
					    $sql = 'ALTER TABLE {' . $table . '} CHANGE ' . $field . ' ' . $this->createFieldSql($field_new, $this->processField($spec));
 | 
				
			||||||
 | 
					    if (count($keys_new)) {
 | 
				
			||||||
 | 
					      $sql .= ', ADD ' . implode(', ADD ', $this->createKeysSql($keys_new));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $ret[] = update_sql($sql);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @} End of "ingroup schemaapi".
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,130 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					// $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file
 | 
				
			||||||
 | 
					 * Database interface code for PostgreSQL database servers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup database
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DatabaseConnection_pgsql extends DatabaseConnection {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected $transactionSupport;
 | 
				
			||||||
 | 
					  //protected $lastInsertInfo = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function __construct(Array $connection_options = array()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $connection_options += array(
 | 
				
			||||||
 | 
					      'transactions' => TRUE,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    $this->transactionSupport = $connection_options['transactions'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $dsn = 'pgsql:host=' . $connection_options['host'] . ' dbname=' . $connection_options['database'];
 | 
				
			||||||
 | 
					    if (!empty($connection_options['port'])) {
 | 
				
			||||||
 | 
					      $dsn .= ' port=' . $connection_options['port'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parent::__construct($dsn, $connection_options['username'], $connection_options['password'], array(PDO::ATTR_STRINGIFY_FETCHES => TRUE));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function query($query, Array $args = array(), $options = array()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $options += $this->defaultOptions();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      if ($query instanceof DatabaseStatement) {
 | 
				
			||||||
 | 
					        $stmt = $query;
 | 
				
			||||||
 | 
					        $stmt->execute(NULL, $options);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else {
 | 
				
			||||||
 | 
					        $stmt = $this->prepareQuery($query);
 | 
				
			||||||
 | 
					        $stmt->execute($args, $options);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      switch ($options['return']) {
 | 
				
			||||||
 | 
					        case Database::RETURN_STATEMENT:
 | 
				
			||||||
 | 
					          return $stmt;
 | 
				
			||||||
 | 
					        case Database::RETURN_AFFECTED:
 | 
				
			||||||
 | 
					          return $stmt->rowCount();
 | 
				
			||||||
 | 
					        case Database::RETURN_INSERT_ID:
 | 
				
			||||||
 | 
					          return $this->lastInsertId($options['sequence_name']);
 | 
				
			||||||
 | 
					        case Database::RETURN_NULL:
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					          throw new PDOException('Invalid return directive: ' . $options['return']);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    catch (PDOException $e) {
 | 
				
			||||||
 | 
					      if (!function_exists('module_implements')) {
 | 
				
			||||||
 | 
					        _db_need_install();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      //watchdog('database', var_export($e, TRUE) . $e->getMessage(), NULL, WATCHDOG_ERROR);
 | 
				
			||||||
 | 
					      if ($options['throw_exception']) {
 | 
				
			||||||
 | 
					        if ($query instanceof DatabaseStatement) {
 | 
				
			||||||
 | 
					          $query_string = $stmt->queryString;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					          $query_string = $query;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        throw new PDOException($query_string . " - \n" . print_r($args,1) . $e->getMessage());
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function queryRange($query, Array $args, $from, $count, Array $options) {
 | 
				
			||||||
 | 
					    // Backward compatibility hack, temporary.
 | 
				
			||||||
 | 
					    $query = str_replace(array('%d' , '%f' , '%b' , "'%s'"), '?', $query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $this->query($query . ' LIMIT ' . $count . ' OFFSET ' . $from, $args, $options);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function queryTemporary($query, Array $args, $tablename) {
 | 
				
			||||||
 | 
					    $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE ' . $tablename . ' Engine=HEAP SELECT', $this->prefixTables($query));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $this->query($query, $args, $options);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function driver() {
 | 
				
			||||||
 | 
					    return 'pgsql';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function databaseType() {
 | 
				
			||||||
 | 
					    return 'pgsql';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function supportsTransactions() {
 | 
				
			||||||
 | 
					    return $this->transactionSupport;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function escapeTable($table) {
 | 
				
			||||||
 | 
					    return preg_replace('/[^A-Za-z0-9_]+/', '', $table);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function mapConditionOperator($operator) {
 | 
				
			||||||
 | 
					    static $specials = array(
 | 
				
			||||||
 | 
					      // In PostgreSQL, 'LIKE' is case-sensitive.  For case-insensitive LIKE
 | 
				
			||||||
 | 
					      // statements, we need to use ILIKE instead.
 | 
				
			||||||
 | 
					      'LIKE' => array('operator' => 'ILIKE'),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return isset($specials[$operator]) ? $specials[$operator] : NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * @todo Remove this as soon as db_rewrite_sql() has been exterminated.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function distinctField($table, $field, $query) {
 | 
				
			||||||
 | 
					    $field_to_select = 'DISTINCT(' . $table . '.' . $field . ')';
 | 
				
			||||||
 | 
					    // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
 | 
				
			||||||
 | 
					    return preg_replace('/(SELECT.*)(?:' . $table . '\.|\s)(?<!DISTINCT\()(?<!DISTINCT\(' . $table . '\.)' . $field . '(.*FROM )/AUsi', '\1 ' . $field_to_select . '\2', $query);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @} End of "ingroup database".
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					// $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PostgreSQL specific install functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DatabaseInstaller_pgsql extends DatabaseInstaller {
 | 
				
			||||||
 | 
					  protected $pdoDriver = 'pgsql';
 | 
				
			||||||
 | 
					  public function name() {
 | 
				
			||||||
 | 
					    return 'PostgreSQL';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,167 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					// $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup database
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class InsertQuery_pgsql extends InsertQuery {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function __construct($connection, $table, Array $options = array()) {
 | 
				
			||||||
 | 
					    parent::__construct($connection, $table, $options);
 | 
				
			||||||
 | 
					    $this->queryOptions['return'] = Database::RETURN_NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function execute() {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Confirm that the user did not try to specify an identical
 | 
				
			||||||
 | 
					    //  field and default field.
 | 
				
			||||||
 | 
					    if (array_intersect($this->insertFields, $this->defaultFields)) {
 | 
				
			||||||
 | 
					      throw new PDOException('You may not specify the same field to have a value and a schema-default value.');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $schema = drupal_get_schema($this->table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $stmt = $this->connection->prepareQuery((string)$this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $max_placeholder = 0;
 | 
				
			||||||
 | 
					    $blobs = array();
 | 
				
			||||||
 | 
					    $blob_cnt = 0;
 | 
				
			||||||
 | 
					    foreach ($this->insertValues as &$insert_values) {
 | 
				
			||||||
 | 
					      foreach ($this->insertFields as $idx => $field) {
 | 
				
			||||||
 | 
					        switch ($schema['fields'][$field]['type']) {
 | 
				
			||||||
 | 
					          case 'blob':
 | 
				
			||||||
 | 
					            $blobs[$blob_cnt] = fopen('php://memory', 'a');
 | 
				
			||||||
 | 
					            fwrite($blobs[$blob_cnt], $insert_values[$idx]);
 | 
				
			||||||
 | 
					            rewind($blobs[$blob_cnt]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $stmt->bindParam(':db_insert_placeholder_' . $max_placeholder++, $blobs[$blob_cnt], PDO::PARAM_LOB);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ++$blob_cnt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          default:
 | 
				
			||||||
 | 
					            $stmt->bindParam(':db_insert_placeholder_'. $max_placeholder++, $insert_values[$idx]);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // PostgreSQL requires the table name to be specified explicitly
 | 
				
			||||||
 | 
					    // when requesting the last insert ID, so we pass that in via
 | 
				
			||||||
 | 
					    // the options array.
 | 
				
			||||||
 | 
					    $options = $this->queryOptions;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if ($schema['fields'][$schema['primary key'][0]]['type'] == 'serial') {
 | 
				
			||||||
 | 
					      $options['sequence_name'] = $this->connection->makeSequenceName($this->table, $schema['primary key'][0]);
 | 
				
			||||||
 | 
					      $options['return'] = Database::RETURN_INSERT_ID;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $last_insert_id = $this->connection->query($stmt, array(), $options);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Re-initialize the values array so that we can re-use this query.
 | 
				
			||||||
 | 
					    $this->insertValues = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $last_insert_id;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function __toString() {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Default fields are always placed first for consistency.
 | 
				
			||||||
 | 
					    $insert_fields = array_merge($this->defaultFields, $this->insertFields);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $query = "INSERT INTO {" . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES ';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $max_placeholder = 0;
 | 
				
			||||||
 | 
					    $values = array();
 | 
				
			||||||
 | 
					      if (count($this->insertValues)) {
 | 
				
			||||||
 | 
					      foreach ($this->insertValues as $insert_values) {
 | 
				
			||||||
 | 
					        $placeholders = array();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Default fields aren't really placeholders, but this is the most convenient
 | 
				
			||||||
 | 
					        // way to handle them.
 | 
				
			||||||
 | 
					        $placeholders = array_pad($placeholders, count($this->defaultFields), 'default');
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $new_placeholder = $max_placeholder + count($insert_values);
 | 
				
			||||||
 | 
					        for ($i = $max_placeholder; $i < $new_placeholder; ++$i) {
 | 
				
			||||||
 | 
					          $placeholders[] = ':db_insert_placeholder_' . $i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $max_placeholder = $new_placeholder;
 | 
				
			||||||
 | 
					        $values[] = '(' . implode(', ', $placeholders) . ')';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      // If there are no values, then this is a default-only query.  We still need to handle that.
 | 
				
			||||||
 | 
					      $placeholders = array_fill(0, count($this->defaultFields), 'default');
 | 
				
			||||||
 | 
					      $values[] = '(' . implode(', ', $placeholders) .')';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $query .= implode(', ', $values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $query;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateQuery_pgsql extends UpdateQuery { 
 | 
				
			||||||
 | 
					  public function execute() {
 | 
				
			||||||
 | 
					    $max_placeholder = 0;
 | 
				
			||||||
 | 
					    $blobs = array();
 | 
				
			||||||
 | 
					    $blob_count = 0;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $schema = drupal_get_schema($this->table);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Because we filter $fields the same way here and in __toString(), the
 | 
				
			||||||
 | 
					    // placeholders will all match up properly.
 | 
				
			||||||
 | 
					    $stmt = $this->connection->prepareQuery((string)$this);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Expressions take priority over literal fields, so we process those first
 | 
				
			||||||
 | 
					    // and remove any literal fields that conflict.
 | 
				
			||||||
 | 
					    $fields = $this->fields;
 | 
				
			||||||
 | 
					    $expression_fields = array();
 | 
				
			||||||
 | 
					    foreach ($this->expressionFields as $field => $data) {
 | 
				
			||||||
 | 
					      if (!empty($data['arguments'])) {
 | 
				
			||||||
 | 
					        foreach ($data['arguments'] as $placeholder => $argument) {
 | 
				
			||||||
 | 
					          // We assume that an expression will never happen on a BLOB field,
 | 
				
			||||||
 | 
					          // which is a fairly safe assumption to make since in most cases
 | 
				
			||||||
 | 
					          // it would be an invalid query anyway.
 | 
				
			||||||
 | 
					          $stmt->bindParam($placeholder, $argument);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      unset($fields[$field]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    foreach ($fields as $field => &$value) {
 | 
				
			||||||
 | 
					      $placeholder = ':db_update_placeholder_' . ($max_placeholder++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      switch ($schema['fields'][$field]['type']) {
 | 
				
			||||||
 | 
					        case 'blob':
 | 
				
			||||||
 | 
					          $blobs[$blob_count] = fopen('php://memory', 'a');
 | 
				
			||||||
 | 
					          fwrite($blobs[$blob_count], $value);
 | 
				
			||||||
 | 
					          rewind($blobs[$blob_count]);
 | 
				
			||||||
 | 
					          $stmt->bindParam($placeholder, $blobs[$blob_count], PDO::PARAM_LOB);
 | 
				
			||||||
 | 
					          ++$blob_count;
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					          $stmt->bindParam($placeholder, $value);
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (count($this->condition)) {
 | 
				
			||||||
 | 
					      $this->condition->compile($this->connection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $arguments = $this->condition->arguments();
 | 
				
			||||||
 | 
					      foreach ($arguments as $placeholder => &$value) {
 | 
				
			||||||
 | 
					        $stmt->bindParam($placeholder, $value);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $options = $this->queryOptions;
 | 
				
			||||||
 | 
					    $options['already_prepared'] = TRUE;
 | 
				
			||||||
 | 
					    $this->connection->query($stmt, $options);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    //$stmt->execute(NULL, $this->queryOptions);
 | 
				
			||||||
 | 
					    return $stmt->rowCount();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,509 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					// $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file
 | 
				
			||||||
 | 
					 * Database schema code for PostgreSQL database servers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup schemaapi
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DatabaseSchema_pgsql extends DatabaseSchema {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function tableExists($table) {
 | 
				
			||||||
 | 
					    return (bool) db_result(db_query("SELECT COUNT(*) FROM pg_class WHERE relname = '{" . db_escape_table($table) . "}'"));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function columnExists($table, $column) {
 | 
				
			||||||
 | 
					    return (bool) db_result(db_query("SELECT COUNT(pg_attribute.attname) FROM pg_class, pg_attribute WHERE pg_attribute.attrelid = pg_class.oid AND pg_class.relname = '{" . db_escape_table($table) . "}' AND attname = '" . db_escape_table($column) . "'"));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Generate SQL to create a new table from a Drupal schema definition.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $name
 | 
				
			||||||
 | 
					   *   The name of the table to create.
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   A Schema API table definition array.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   An array of SQL statements to create the table.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function createTableSql($name, $table) {
 | 
				
			||||||
 | 
					    $sql_fields = array();
 | 
				
			||||||
 | 
					    foreach ($table['fields'] as $field_name => $field) {
 | 
				
			||||||
 | 
					      $sql_fields[] = $this->createFieldSql($field_name, $this->processField($field));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $sql_keys = array();
 | 
				
			||||||
 | 
					    if (isset($table['primary key']) && is_array($table['primary key'])) {
 | 
				
			||||||
 | 
					      $sql_keys[] = 'PRIMARY KEY (' . implode(', ', $table['primary key']) . ')';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (isset($table['unique keys']) && is_array($table['unique keys'])) {
 | 
				
			||||||
 | 
					      foreach ($table['unique keys'] as $key_name => $key) {
 | 
				
			||||||
 | 
					        $sql_keys[] = 'CONSTRAINT {' . $name . '}_' . $key_name . '_key UNIQUE (' . implode(', ', $key) . ')';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $sql = "CREATE TABLE {" . $name . "} (\n\t";
 | 
				
			||||||
 | 
					    $sql .= implode(",\n\t", $sql_fields);
 | 
				
			||||||
 | 
					    if (count($sql_keys) > 0) {
 | 
				
			||||||
 | 
					      $sql .= ",\n\t";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $sql .= implode(",\n\t", $sql_keys);
 | 
				
			||||||
 | 
					    $sql .= "\n)";
 | 
				
			||||||
 | 
					    $statements[] = $sql;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (isset($table['indexes']) && is_array($table['indexes'])) {
 | 
				
			||||||
 | 
					      foreach ($table['indexes'] as $key_name => $key) {
 | 
				
			||||||
 | 
					        $statements[] = $this->_createIndexSql($name, $key_name, $key);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $statements;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function createFieldSql($name, $spec) {
 | 
				
			||||||
 | 
					    $sql = $name . ' ' . $spec['pgsql_type'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($spec['type'] == 'serial') {
 | 
				
			||||||
 | 
					      unset($spec['not null']);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!empty($spec['unsigned'])) {
 | 
				
			||||||
 | 
					      if ($spec['type'] == 'serial') {
 | 
				
			||||||
 | 
					        $sql .= " CHECK ($name >= 0)";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else {
 | 
				
			||||||
 | 
					        $sql .= '_unsigned';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!empty($spec['length'])) {
 | 
				
			||||||
 | 
					      $sql .= '(' . $spec['length'] . ')';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    elseif (isset($spec['precision']) && isset($spec['scale'])) {
 | 
				
			||||||
 | 
					      $sql .= '(' . $spec['precision'] . ', ' . $spec['scale'] . ')';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (isset($spec['not null']) && $spec['not null']) {
 | 
				
			||||||
 | 
					      $sql .= ' NOT NULL';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (isset($spec['default'])) {
 | 
				
			||||||
 | 
					      $default = is_string($spec['default']) ? "'" . $spec['default'] . "'" : $spec['default'];
 | 
				
			||||||
 | 
					      $sql .= " default $default";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $sql;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Set database-engine specific properties for a field.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $field
 | 
				
			||||||
 | 
					   *   A field description array, as specified in the schema documentation.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function processField($field) {
 | 
				
			||||||
 | 
					    if (!isset($field['size'])) {
 | 
				
			||||||
 | 
					      $field['size'] = 'normal';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // Set the correct database-engine specific datatype.
 | 
				
			||||||
 | 
					    if (!isset($field['pgsql_type'])) {
 | 
				
			||||||
 | 
					      $map = $this->getFieldTypeMap();
 | 
				
			||||||
 | 
					      $field['pgsql_type'] = $map[$field['type'] . ':' . $field['size']];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ($field['type'] == 'serial') {
 | 
				
			||||||
 | 
					      unset($field['not null']);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return $field;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * This maps a generic data type in combination with its data size
 | 
				
			||||||
 | 
					   * to the engine-specific data type.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  function getFieldTypeMap() {
 | 
				
			||||||
 | 
					    // 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',
 | 
				
			||||||
 | 
					      'char:normal' => 'character',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      'text:tiny' => 'text',
 | 
				
			||||||
 | 
					      'text:small' => 'text',
 | 
				
			||||||
 | 
					      'text:medium' => 'text',
 | 
				
			||||||
 | 
					      'text:big' => 'text',
 | 
				
			||||||
 | 
					      'text:normal' => 'text',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      'int:tiny' => 'smallint',
 | 
				
			||||||
 | 
					      'int:small' => 'smallint',
 | 
				
			||||||
 | 
					      'int:medium' => 'int',
 | 
				
			||||||
 | 
					      'int:big' => 'bigint',
 | 
				
			||||||
 | 
					      'int:normal' => 'int',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      'float:tiny' => 'real',
 | 
				
			||||||
 | 
					      'float:small' => 'real',
 | 
				
			||||||
 | 
					      'float:medium' => 'real',
 | 
				
			||||||
 | 
					      'float:big' => 'double precision',
 | 
				
			||||||
 | 
					      'float:normal' => 'real',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      'numeric:normal' => 'numeric',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      'blob:big' => 'bytea',
 | 
				
			||||||
 | 
					      'blob:normal' => 'bytea',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      'datetime:normal' => 'timestamp',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      'serial:tiny' => 'serial',
 | 
				
			||||||
 | 
					      'serial:small' => 'serial',
 | 
				
			||||||
 | 
					      'serial:medium' => 'serial',
 | 
				
			||||||
 | 
					      'serial:big' => 'bigserial',
 | 
				
			||||||
 | 
					      'serial:normal' => 'serial',
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    return $map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function _createKeySql($fields) {
 | 
				
			||||||
 | 
					    $ret = array();
 | 
				
			||||||
 | 
					    foreach ($fields as $field) {
 | 
				
			||||||
 | 
					      if (is_array($field)) {
 | 
				
			||||||
 | 
					        $ret[] = 'substr(' . $field[0] . ', 1, ' . $field[1] . ')';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else {
 | 
				
			||||||
 | 
					        $ret[] = $field;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return implode(', ', $ret);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 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 renameTable(&$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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function dropTable(&$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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function addField(&$ret, $table, $field, $spec, $new_keys = array()) {
 | 
				
			||||||
 | 
					    $fixnull = FALSE;
 | 
				
			||||||
 | 
					    if (!empty($spec['not null']) && !isset($spec['default'])) {
 | 
				
			||||||
 | 
					      $fixnull = TRUE;
 | 
				
			||||||
 | 
					      $spec['not null'] = FALSE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $query = 'ALTER TABLE {' . $table . '} ADD COLUMN ';
 | 
				
			||||||
 | 
					    $query .= $this->_createFieldSql($field, $this->_processField($spec));
 | 
				
			||||||
 | 
					    $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) {
 | 
				
			||||||
 | 
					      $ret[] = update_sql("ALTER TABLE {" . $table . "} ALTER $field SET NOT NULL");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (isset($new_keys)) {
 | 
				
			||||||
 | 
					      $this->_createKeys($ret, $table, $new_keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function dropField(&$ret, $table, $field) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP COLUMN ' . $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'.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function fieldSetDefault(&$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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function fieldSetNoDefault(&$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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function addPrimaryKey(&$ret, $table, $fields) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . implode(',', $fields) . ')');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Drop the primary key.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $ret
 | 
				
			||||||
 | 
					   *   Array to which query results will be added.
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   The table to be altered.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function dropPrimaryKey(&$ret, $table) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP CONSTRAINT {' . $table . '}_pkey');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 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 addUniqueKey(&$ret, $table, $name, $fields) {
 | 
				
			||||||
 | 
					    $name = '{' . $table . '}_' . $name . '_key';
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} ADD CONSTRAINT ' . $name . ' UNIQUE (' . implode(',', $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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function dropUniqueKey(&$ret, $table, $name) {
 | 
				
			||||||
 | 
					    $name = '{' . $table . '}_' . $name . '_key';
 | 
				
			||||||
 | 
					    $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function addIndex(&$ret, $table, $name, $fields) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql($this->_createIndexSql($table, $name, $fields));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Drop an index.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $ret
 | 
				
			||||||
 | 
					   *   Array to which query results will be added.
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   The table to be altered.
 | 
				
			||||||
 | 
					   * @param $name
 | 
				
			||||||
 | 
					   *   The name of the index.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function dropIndex(&$ret, $table, $name) {
 | 
				
			||||||
 | 
					    $name = '{' . $table . '}_' . $name . '_idx';
 | 
				
			||||||
 | 
					    $ret[] = update_sql('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 $new_keys 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
 | 
				
			||||||
 | 
					   * $new_keys 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 $new_keys 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 $new_keys
 | 
				
			||||||
 | 
					   *   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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function changeField(&$ret, $table, $field, $field_new, $spec, $new_keys = array()) {
 | 
				
			||||||
 | 
					    $ret[] = update_sql("ALTER TABLE {" . $table . "} RENAME $field TO " . $field . "_old");
 | 
				
			||||||
 | 
					    $not_null = isset($spec['not null']) ? $spec['not null'] : FALSE;
 | 
				
			||||||
 | 
					    unset($spec['not null']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $this->addField($ret, $table, "$field_new", $spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $ret[] = update_sql("UPDATE {" . $table . "} SET $field_new = " . $field . "_old");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($not_null) {
 | 
				
			||||||
 | 
					      $ret[] = update_sql("ALTER TABLE {" . $table . "} ALTER $field_new SET NOT NULL");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $this->dropField($ret, $table, $field . '_old');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (isset($new_keys)) {
 | 
				
			||||||
 | 
					      $this->_createKeys($ret, $table, $new_keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function _createIndexSql($table, $name, $fields) {
 | 
				
			||||||
 | 
					    $query = 'CREATE INDEX {' . $table . '}_' . $name . '_idx ON {' . $table . '} (';
 | 
				
			||||||
 | 
					    $query .= $this->_createKeySql($fields) . ')';
 | 
				
			||||||
 | 
					    return $query;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function _createKeys(&$ret, $table, $new_keys) {
 | 
				
			||||||
 | 
					    if (isset($new_keys['primary key'])) {
 | 
				
			||||||
 | 
					      $this->addPrimaryKey($ret, $table, $new_keys['primary key']);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (isset($new_keys['unique keys'])) {
 | 
				
			||||||
 | 
					      foreach ($new_keys['unique keys'] as $name => $fields) {
 | 
				
			||||||
 | 
					        $this->addUniqueKey($ret, $table, $name, $fields);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (isset($new_keys['indexes'])) {
 | 
				
			||||||
 | 
					      foreach ($new_keys['indexes'] as $name => $fields) {
 | 
				
			||||||
 | 
					        $this->addIndex($ret, $table, $name, $fields);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,413 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					// $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file
 | 
				
			||||||
 | 
					 * Generic Database schema code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @defgroup schemaapi Schema API
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A Drupal schema definition is an array structure representing one or
 | 
				
			||||||
 | 
					 * more tables and their related keys and indexes. A schema is defined by
 | 
				
			||||||
 | 
					 * hook_schema(), which usually lives in a modulename.install file.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * By implementing hook_schema() and specifying the tables your module
 | 
				
			||||||
 | 
					 * declares, you can easily create and drop these tables on all
 | 
				
			||||||
 | 
					 * supported database engines. You don't have to deal with the
 | 
				
			||||||
 | 
					 * different SQL dialects for table creation and alteration of the
 | 
				
			||||||
 | 
					 * supported database engines.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * hook_schema() should return an array with a key for each table that
 | 
				
			||||||
 | 
					 * the module defines.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The following keys are defined:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *   - 'description': A string describing this table and its purpose.
 | 
				
			||||||
 | 
					 *     References to other tables should be enclosed in
 | 
				
			||||||
 | 
					 *     curly-brackets.  For example, the node_revisions table
 | 
				
			||||||
 | 
					 *     description field might contain "Stores per-revision title and
 | 
				
			||||||
 | 
					 *     body data for each {node}."
 | 
				
			||||||
 | 
					 *   - 'fields': An associative array ('fieldname' => specification)
 | 
				
			||||||
 | 
					 *     that describes the table's database columns.  The specification
 | 
				
			||||||
 | 
					 *     is also an array.  The following specification parameters are defined:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     - 'description': A string describing this field and its purpose.
 | 
				
			||||||
 | 
					 *       References to other tables should be enclosed in
 | 
				
			||||||
 | 
					 *       curly-brackets.  For example, the node table vid field
 | 
				
			||||||
 | 
					 *       description might contain "Always holds the largest (most
 | 
				
			||||||
 | 
					 *       recent) {node_revisions}.vid value for this nid."
 | 
				
			||||||
 | 
					 *     - 'type': The generic datatype: 'varchar', 'int', 'serial'
 | 
				
			||||||
 | 
					 *       'float', 'numeric', 'text', 'blob' or 'datetime'.  Most types
 | 
				
			||||||
 | 
					 *       just map to the according database engine specific
 | 
				
			||||||
 | 
					 *       datatypes.  Use 'serial' for auto incrementing fields. This
 | 
				
			||||||
 | 
					 *       will expand to 'int auto_increment' on mysql.
 | 
				
			||||||
 | 
					 *     - 'size': The data size: 'tiny', 'small', 'medium', 'normal',
 | 
				
			||||||
 | 
					 *       'big'.  This is a hint about the largest value the field will
 | 
				
			||||||
 | 
					 *       store and determines which of the database engine specific
 | 
				
			||||||
 | 
					 *       datatypes will be used (e.g. on MySQL, TINYINT vs. INT vs. BIGINT).
 | 
				
			||||||
 | 
					 *       'normal', the default, selects the base type (e.g. on MySQL,
 | 
				
			||||||
 | 
					 *       INT, VARCHAR, BLOB, etc.).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *       Not all sizes are available for all data types. See
 | 
				
			||||||
 | 
					 *       db_type_map() for possible combinations.
 | 
				
			||||||
 | 
					 *     - 'not null': If true, no NULL values will be allowed in this
 | 
				
			||||||
 | 
					 *       database column.  Defaults to false.
 | 
				
			||||||
 | 
					 *     - 'default': The field's default value.  The PHP type of the
 | 
				
			||||||
 | 
					 *       value matters: '', '0', and 0 are all different.  If you
 | 
				
			||||||
 | 
					 *       specify '0' as the default value for a type 'int' field it
 | 
				
			||||||
 | 
					 *       will not work because '0' is a string containing the
 | 
				
			||||||
 | 
					 *       character "zero", not an integer.
 | 
				
			||||||
 | 
					 *     - 'length': The maximal length of a type 'varchar' or 'text'
 | 
				
			||||||
 | 
					 *       field.  Ignored for other field types.
 | 
				
			||||||
 | 
					 *     - 'unsigned': A boolean indicating whether a type 'int', 'float'
 | 
				
			||||||
 | 
					 *       and 'numeric' only is signed or unsigned.  Defaults to
 | 
				
			||||||
 | 
					 *       FALSE.  Ignored for other field types.
 | 
				
			||||||
 | 
					 *     - 'precision', 'scale': For type 'numeric' fields, indicates
 | 
				
			||||||
 | 
					 *       the precision (total number of significant digits) and scale
 | 
				
			||||||
 | 
					 *       (decimal digits right of the decimal point).  Both values are
 | 
				
			||||||
 | 
					 *       mandatory.  Ignored for other field types.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     All parameters apart from 'type' are optional except that type
 | 
				
			||||||
 | 
					 *     'numeric' columns must specify 'precision' and 'scale'.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  - 'primary key': An array of one or more key column specifiers (see below)
 | 
				
			||||||
 | 
					 *    that form the primary key.
 | 
				
			||||||
 | 
					 *  - 'unique key': An associative array of unique keys ('keyname' =>
 | 
				
			||||||
 | 
					 *    specification).  Each specification is an array of one or more
 | 
				
			||||||
 | 
					 *    key column specifiers (see below) that form a unique key on the table.
 | 
				
			||||||
 | 
					 *  - 'indexes':  An associative array of indexes ('indexame' =>
 | 
				
			||||||
 | 
					 *    specification).  Each specification is an array of one or more
 | 
				
			||||||
 | 
					 *    key column specifiers (see below) that form an index on the
 | 
				
			||||||
 | 
					 *    table.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A key column specifier is either a string naming a column or an
 | 
				
			||||||
 | 
					 * array of two elements, column name and length, specifying a prefix
 | 
				
			||||||
 | 
					 * of the named column.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * As an example, here is a SUBSET of the schema definition for
 | 
				
			||||||
 | 
					 * Drupal's 'node' table.  It show four fields (nid, vid, type, and
 | 
				
			||||||
 | 
					 * title), the primary key on field 'nid', a unique key named 'vid' on
 | 
				
			||||||
 | 
					 * field 'vid', and two indexes, one named 'nid' on field 'nid' and
 | 
				
			||||||
 | 
					 * one named 'node_title_type' on the field 'title' and the first four
 | 
				
			||||||
 | 
					 * bytes of the field 'type':
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 * $schema['node'] = array(
 | 
				
			||||||
 | 
					 *   'fields' => array(
 | 
				
			||||||
 | 
					 *     'nid'      => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
 | 
				
			||||||
 | 
					 *     'vid'      => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
 | 
				
			||||||
 | 
					 *     'type'     => array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => ''),
 | 
				
			||||||
 | 
					 *     'title'    => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''),
 | 
				
			||||||
 | 
					 *   ),
 | 
				
			||||||
 | 
					 *   'primary key' => array('nid'),
 | 
				
			||||||
 | 
					 *   'unique keys' => array(
 | 
				
			||||||
 | 
					 *     'vid'     => array('vid')
 | 
				
			||||||
 | 
					 *   ),
 | 
				
			||||||
 | 
					 *   'indexes' => array(
 | 
				
			||||||
 | 
					 *     'nid'                 => array('nid'),
 | 
				
			||||||
 | 
					 *     'node_title_type'     => array('title', array('type', 4)),
 | 
				
			||||||
 | 
					 *   ),
 | 
				
			||||||
 | 
					 * );
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see drupal_install_schema()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class DatabaseSchema {
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  protected $connection;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function __construct($connection) {
 | 
				
			||||||
 | 
					    $this->connection = $connection;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Check if a table exists.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function tableExists($table);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Check if a column exists in the given table.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function columnExists($table, $column);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * This maps a generic data type in combination with its data size
 | 
				
			||||||
 | 
					   * to the engine-specific data type.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function getFieldTypeMap();
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function renameTable(&$ret, $table, $new_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Drop a table.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $ret
 | 
				
			||||||
 | 
					   *   Array to which query results will be added.
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   The table to be dropped.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function dropTable(&$ret, $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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function addField(&$ret, $table, $field, $spec, $keys_new = array());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function dropField(&$ret, $table, $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'.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function fieldSetDefault(&$ret, $table, $field, $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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function fieldSetNoDefault(&$ret, $table, $field);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function addPrimaryKey(&$ret, $table, $fields);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Drop the primary key.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $ret
 | 
				
			||||||
 | 
					   *   Array to which query results will be added.
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   The table to be altered.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function dropPrimaryKey(&$ret, $table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function addUniqueKey(&$ret, $table, $name, $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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function dropUniqueKey(&$ret, $table, $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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function addIndex(&$ret, $table, $name, $fields);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Drop an index.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $ret
 | 
				
			||||||
 | 
					   *   Array to which query results will be added.
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   The table to be altered.
 | 
				
			||||||
 | 
					   * @param $name
 | 
				
			||||||
 | 
					   *   The name of the index.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function dropIndex(&$ret, $table, $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.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  abstract public function changeField(&$ret, $table, $field, $field_new, $spec, $keys_new = array());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Create a new table from a Drupal table definition.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $ret
 | 
				
			||||||
 | 
					   *   Array to which query results will be added.
 | 
				
			||||||
 | 
					   * @param $name
 | 
				
			||||||
 | 
					   *   The name of the table to create.
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   A Schema API table definition array.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function createTable(&$ret, $name, $table) {
 | 
				
			||||||
 | 
					    $statements = $this->createTableSql($name, $table);
 | 
				
			||||||
 | 
					    foreach ($statements as $statement) {
 | 
				
			||||||
 | 
					      $ret[] = update_sql($statement);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Return an array of field names from an array of key/index column specifiers.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * This is usually an identity function but if a key/index uses a column prefix
 | 
				
			||||||
 | 
					   * specification, this function extracts just the name.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $fields
 | 
				
			||||||
 | 
					   *   An array of key/index column specifiers.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   An array of field names.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function fieldNames($fields) {
 | 
				
			||||||
 | 
					    $ret = array();
 | 
				
			||||||
 | 
					    foreach ($fields as $field) {
 | 
				
			||||||
 | 
					      if (is_array($field)) {
 | 
				
			||||||
 | 
					        $ret[] = $field[0];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else {
 | 
				
			||||||
 | 
					        $ret[] = $field;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return $ret;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @} End of "defgroup schemaapi".
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,702 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					// $Id$
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @ingroup database
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Query builder for SELECT statements.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class SelectQuery extends Query implements QueryConditionInterface, QueryAlterableInterface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The fields to SELECT.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var array
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $fields = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The expressions to SELECT as virtual fields.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var array
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $expressions = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The tables against which to JOIN.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * This property is a nested array.  Each entry is an array representing
 | 
				
			||||||
 | 
					   * a single table against which to join.  The structure of each entry is:
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * array(
 | 
				
			||||||
 | 
					   *   'type' => $join_type (one of INNER, LEFT OUTER, RIGHT OUTER),
 | 
				
			||||||
 | 
					   *   'table' => $name_of_table,
 | 
				
			||||||
 | 
					   *   'alias' => $alias_of_the_table,
 | 
				
			||||||
 | 
					   *   'condition' => $condition_clause_on_which_to_join,
 | 
				
			||||||
 | 
					   *   'arguments' => $array_of_arguments_for_placeholders_in_the condition.
 | 
				
			||||||
 | 
					   * )
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var array
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $tables = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The values to insert into the prepared statement of this query.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var array
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  //protected $arguments = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The fields by which to order this query.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * This is an associative array.  The keys are the fields to order, and the value
 | 
				
			||||||
 | 
					   * is the direction to order, either ASC or DESC.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var array
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $order = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The fields by which to group.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var array
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $group = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The conditional object for the WHERE clause.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var DatabaseCondition
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $where;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The conditional object for the HAVING clause.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var DatabaseCondition
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $having;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Whether or not this query should be DISTINCT
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var boolean
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $distinct = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * The range limiters for this query.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @var array
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected $range;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function __construct($table, $alias = NULL, DatabaseConnection $connection, $options = array()) {
 | 
				
			||||||
 | 
					    $options['return'] = Database::RETURN_STATEMENT;
 | 
				
			||||||
 | 
					    parent::__construct($connection, $options);
 | 
				
			||||||
 | 
					    $this->where = new DatabaseCondition('AND');
 | 
				
			||||||
 | 
					    $this->having = new DatabaseCondition('AND');
 | 
				
			||||||
 | 
					    $this->addJoin(NULL, $table, $alias);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Implementations of QueryAlterableInterface. */
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function addTag($tag) {
 | 
				
			||||||
 | 
					    $this->alterTags[$tag] = 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function hasTag($tag) {
 | 
				
			||||||
 | 
					    return isset($this->alterTags[$tag]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function hasAllTags() {
 | 
				
			||||||
 | 
					    return !(boolean)array_diff(func_get_args(), array_keys($this->alterTags));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function hasAnyTag() {
 | 
				
			||||||
 | 
					    return (boolean)array_intersect(func_get_args(), array_keys($this->alterTags));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function addMetaData($key, $object) {
 | 
				
			||||||
 | 
					    $this->alterMetaData[$key] = $object;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function getMetaData($key) {
 | 
				
			||||||
 | 
					    return isset($this->alterMetaData[$key]) ? $this->alterMetaData[$key] : NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /* Implementations of QueryConditionInterface for the WHERE clause. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function condition($field, $value = NULL, $operator = '=') {
 | 
				
			||||||
 | 
					    if (!isset($num_args)) {
 | 
				
			||||||
 | 
					      $num_args = func_num_args();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $this->where->condition($field, $value, $operator, $num_args);
 | 
				
			||||||
 | 
					    return $this;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function &conditions() {
 | 
				
			||||||
 | 
					    return $this->where->conditions();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function arguments() {
 | 
				
			||||||
 | 
					    return $this->where->arguments();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function where($snippet, $args = array()) {
 | 
				
			||||||
 | 
					    $this->where->where($snippet, $args);
 | 
				
			||||||
 | 
					    return $this;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function compile(DatabaseConnection $connection) {
 | 
				
			||||||
 | 
					    return $this->where->compile($connection);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Implmeentations of QueryConditionInterface for the HAVING clause. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function havingCondition($field, $value = NULL, $operator = '=') {
 | 
				
			||||||
 | 
					    if (!isset($num_args)) {
 | 
				
			||||||
 | 
					      $num_args = func_num_args();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $this->having->condition($field, $value, $operator, $num_args);
 | 
				
			||||||
 | 
					    return $this;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function &havingConditions() {
 | 
				
			||||||
 | 
					    return $this->having->conditions();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function havingArguments() {
 | 
				
			||||||
 | 
					    return $this->having->arguments();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function having($snippet, $args = array()) {
 | 
				
			||||||
 | 
					    $this->having->where($snippet, $args);
 | 
				
			||||||
 | 
					    return $this;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function havingCompile(DatabaseConnection $connection) {
 | 
				
			||||||
 | 
					    return $this->having->compile($connection);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Alter accessors to expose the query data to alter hooks. */
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Returns a reference to the fields array for this query.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * Because this method returns by reference, alter hooks may edit the fields
 | 
				
			||||||
 | 
					   * array directly to make their changes.  If just adding fields, however, the
 | 
				
			||||||
 | 
					   * use of addField() is preferred.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * Note that this method must be called by reference as well:
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   * @code
 | 
				
			||||||
 | 
					   * $fields =& $query->getFields();
 | 
				
			||||||
 | 
					   * @endcode
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   A reference to the fields array structure.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function &getFields() {
 | 
				
			||||||
 | 
					    return $this->fields;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Returns a reference to the expressions array for this query.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * Because this method returns by reference, alter hooks may edit the expressions
 | 
				
			||||||
 | 
					   * array directly to make their changes.  If just adding expressions, however, the
 | 
				
			||||||
 | 
					   * use of addExpression() is preferred.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * Note that this method must be called by reference as well:
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   * @code
 | 
				
			||||||
 | 
					   * $fields =& $query->getExpressions();
 | 
				
			||||||
 | 
					   * @endcode
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   A reference to the expression array structure.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function &getExpressions() {
 | 
				
			||||||
 | 
					    return $this->expressions;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Returns a reference to the order by array for this query.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * Because this method returns by reference, alter hooks may edit the order-by
 | 
				
			||||||
 | 
					   * array directly to make their changes.  If just adding additional ordering
 | 
				
			||||||
 | 
					   * fields, however, the use of orderBy() is preferred.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * Note that this method must be called by reference as well:
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   * @code
 | 
				
			||||||
 | 
					   * $fields =& $query->getOrderBy();
 | 
				
			||||||
 | 
					   * @endcode
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   A reference to the expression array structure.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function &getOrderBy() {
 | 
				
			||||||
 | 
					    return $this->order;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Returns a reference to the tables array for this query.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * Because this method returns by reference, alter hooks may edit the tables
 | 
				
			||||||
 | 
					   * array directly to make their changes.  If just adding tables, however, the
 | 
				
			||||||
 | 
					   * use of the join() methods is preferred.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * Note that this method must be called by reference as well:
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   * @code
 | 
				
			||||||
 | 
					   * $fields =& $query->getTables();
 | 
				
			||||||
 | 
					   * @endcode
 | 
				
			||||||
 | 
					   * 
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   A reference to the tables array structure.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function &getTables() {
 | 
				
			||||||
 | 
					    return $this->tables;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Compiles and returns an associative array of the arguments for this prepared statement.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return array
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function getArguments() {
 | 
				
			||||||
 | 
					    $this->where->compile($this->connection);
 | 
				
			||||||
 | 
					    $this->having->compile($this->connection);
 | 
				
			||||||
 | 
					    $args = $this->where->arguments() + $this->having->arguments();
 | 
				
			||||||
 | 
					    foreach ($this->tables as $table) {
 | 
				
			||||||
 | 
					      if ($table['arguments']) {
 | 
				
			||||||
 | 
					        $args += $table['arguments'];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    foreach ($this->expressions as $expression) {
 | 
				
			||||||
 | 
					      if ($expression['arguments']) {
 | 
				
			||||||
 | 
					        $args += $expression['arguments'];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return $args;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function execute() {
 | 
				
			||||||
 | 
					    drupal_alter('query', $this);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $this->where->compile($this->connection);
 | 
				
			||||||
 | 
					    $this->having->compile($this->connection);
 | 
				
			||||||
 | 
					    $args = $this->where->arguments() + $this->having->arguments();
 | 
				
			||||||
 | 
					    foreach ($this->tables as $table) {
 | 
				
			||||||
 | 
					      if ($table['arguments']) {
 | 
				
			||||||
 | 
					        $args += $table['arguments'];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    foreach ($this->expressions as $expression) {
 | 
				
			||||||
 | 
					      if ($expression['arguments']) {
 | 
				
			||||||
 | 
					        $args += $expression['arguments'];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (!empty($this->range)) {
 | 
				
			||||||
 | 
					      return $this->connection->queryRange((string)$this, $args, $this->range['start'], $this->range['length'], $this->queryOptions);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return $this->connection->query((string)$this, $args, $this->queryOptions);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Sets this query to be DISTINCT.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $distinct
 | 
				
			||||||
 | 
					   *   TRUE to flag this query DISTINCT, FALSE to disable it.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   The called object.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function distinct($distinct = TRUE) {
 | 
				
			||||||
 | 
					    $this->distinct = $distinct;
 | 
				
			||||||
 | 
					    return $this;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Adds a field to the list to be SELECTed.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $table_alias
 | 
				
			||||||
 | 
					   *   The name of the table from which the field comes, as an alias.  Generally
 | 
				
			||||||
 | 
					   *   you will want to use the return value of join() here to ensure that it is
 | 
				
			||||||
 | 
					   *   valid.
 | 
				
			||||||
 | 
					   * @param $field
 | 
				
			||||||
 | 
					   *   The name of the field.
 | 
				
			||||||
 | 
					   * @param $alias
 | 
				
			||||||
 | 
					   *   The alias for this field.  If not specified, one will be generated
 | 
				
			||||||
 | 
					   *   automatically based on the $table_alias and $field.  The alias will be
 | 
				
			||||||
 | 
					   *   checked for uniqueness, so the requested alias may not be the alias
 | 
				
			||||||
 | 
					   *   that is assigned in all cases.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   The unique alias that was assigned for this field.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function addField($table_alias, $field, $alias = NULL) {
 | 
				
			||||||
 | 
					    if (empty($alias)) {
 | 
				
			||||||
 | 
					      $alias = $table_alias . '_' . $field;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $alias_candidate = $alias;
 | 
				
			||||||
 | 
					    $count = 2;
 | 
				
			||||||
 | 
					    while (!empty($this->tables[$alias_candidate])) {
 | 
				
			||||||
 | 
					      $alias_candidate = $alias . '_' . $count++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $alias = $alias_candidate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $this->fields[$alias] = array(
 | 
				
			||||||
 | 
					      'field' => $field,
 | 
				
			||||||
 | 
					      'table' => $table_alias,
 | 
				
			||||||
 | 
					      'alias' => $alias,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $alias;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Adds an expression to the list of "fields" to be SELECTed.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * An expression can be any arbitrary string that is valid SQL.  That includes
 | 
				
			||||||
 | 
					   * various functions, which may in some cases be database-dependant.  This
 | 
				
			||||||
 | 
					   * method makes no effort to correct for database-specific functions.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $expression
 | 
				
			||||||
 | 
					   *   The expression string.  May contain placeholders.
 | 
				
			||||||
 | 
					   * @param $alias
 | 
				
			||||||
 | 
					   *   The alias for this expression.  If not specified, one will be generated
 | 
				
			||||||
 | 
					   *   automatically in the form "expression_#".  The alias will be checked for
 | 
				
			||||||
 | 
					   *   uniqueness, so the requested alias may not be the alias that is asigned
 | 
				
			||||||
 | 
					   *   in all cases.
 | 
				
			||||||
 | 
					   * @param $arguments
 | 
				
			||||||
 | 
					   *   Any placeholder arguments needed for this expression.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   The unique alias that was assigned for this expression.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function addExpression($expression, $alias = NULL, $arguments = array()) {
 | 
				
			||||||
 | 
					    static $alaises = array();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (empty($alias)) {
 | 
				
			||||||
 | 
					      $alias = 'expression';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (empty($aliases[$alias])) {
 | 
				
			||||||
 | 
					      $aliases[$alias] = 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (!empty($this->expressions[$alias])) {
 | 
				
			||||||
 | 
					      $alias = $alias . '_' . $aliases[$alias]++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $this->expressions[$alias] = array(
 | 
				
			||||||
 | 
					      'expression' => $expression,
 | 
				
			||||||
 | 
					      'alias' => $alias,
 | 
				
			||||||
 | 
					      'arguments' => $arguments,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $alias;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Default Join against another table in the database.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * This method is a convenience method for innerJoin().
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   The table against which to join.
 | 
				
			||||||
 | 
					   * @param $alias
 | 
				
			||||||
 | 
					   *   The alias for the table.  In most cases this should be the first letter
 | 
				
			||||||
 | 
					   *   of the table, or the first letter of each "word" in the table.
 | 
				
			||||||
 | 
					   * @param $condition
 | 
				
			||||||
 | 
					   *   The condition on which to join this table.  If the join requires values,
 | 
				
			||||||
 | 
					   *   this clause should use a named placeholder and the value or values to
 | 
				
			||||||
 | 
					   *   insert should be passed in the 4th parameter.  For the first table joined
 | 
				
			||||||
 | 
					   *   on a query, this value is ignored as the first table is taken as the base
 | 
				
			||||||
 | 
					   *   table.
 | 
				
			||||||
 | 
					   * @param $arguments
 | 
				
			||||||
 | 
					   *   An array of arguments to replace into the $condition of this join.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   The unique alias that was assigned for this table.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function join($table, $alias = NULL, $condition = NULL, $arguments = array()) {
 | 
				
			||||||
 | 
					    return $this->addJoin('INNER', $table, $alias, $condition, $arguments);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Inner Join against another table in the database.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   The table against which to join.
 | 
				
			||||||
 | 
					   * @param $alias
 | 
				
			||||||
 | 
					   *   The alias for the table.  In most cases this should be the first letter
 | 
				
			||||||
 | 
					   *   of the table, or the first letter of each "word" in the table.
 | 
				
			||||||
 | 
					   * @param $condition
 | 
				
			||||||
 | 
					   *   The condition on which to join this table.  If the join requires values,
 | 
				
			||||||
 | 
					   *   this clause should use a named placeholder and the value or values to
 | 
				
			||||||
 | 
					   *   insert should be passed in the 4th parameter.  For the first table joined
 | 
				
			||||||
 | 
					   *   on a query, this value is ignored as the first table is taken as the base
 | 
				
			||||||
 | 
					   *   table.
 | 
				
			||||||
 | 
					   * @param $arguments
 | 
				
			||||||
 | 
					   *   An array of arguments to replace into the $condition of this join.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   The unique alias that was assigned for this table.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
 | 
				
			||||||
 | 
					    return $this->addJoin('INNER', $table, $alias, $condition, $arguments);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Left Outer Join against another table in the database.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   The table against which to join.
 | 
				
			||||||
 | 
					   * @param $alias
 | 
				
			||||||
 | 
					   *   The alias for the table.  In most cases this should be the first letter
 | 
				
			||||||
 | 
					   *   of the table, or the first letter of each "word" in the table.
 | 
				
			||||||
 | 
					   * @param $condition
 | 
				
			||||||
 | 
					   *   The condition on which to join this table.  If the join requires values,
 | 
				
			||||||
 | 
					   *   this clause should use a named placeholder and the value or values to
 | 
				
			||||||
 | 
					   *   insert should be passed in the 4th parameter.  For the first table joined
 | 
				
			||||||
 | 
					   *   on a query, this value is ignored as the first table is taken as the base
 | 
				
			||||||
 | 
					   *   table.
 | 
				
			||||||
 | 
					   * @param $arguments
 | 
				
			||||||
 | 
					   *   An array of arguments to replace into the $condition of this join.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   The unique alias that was assigned for this table.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
 | 
				
			||||||
 | 
					    return $this->addJoin('LEFT OUTER', $table, $alias, $condition, $arguments);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Right Outer Join against another table in the database.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   The table against which to join.
 | 
				
			||||||
 | 
					   * @param $alias
 | 
				
			||||||
 | 
					   *   The alias for the table.  In most cases this should be the first letter
 | 
				
			||||||
 | 
					   *   of the table, or the first letter of each "word" in the table.
 | 
				
			||||||
 | 
					   * @param $condition
 | 
				
			||||||
 | 
					   *   The condition on which to join this table.  If the join requires values,
 | 
				
			||||||
 | 
					   *   this clause should use a named placeholder and the value or values to
 | 
				
			||||||
 | 
					   *   insert should be passed in the 4th parameter.  For the first table joined
 | 
				
			||||||
 | 
					   *   on a query, this value is ignored as the first table is taken as the base
 | 
				
			||||||
 | 
					   *   table.
 | 
				
			||||||
 | 
					   * @param $arguments
 | 
				
			||||||
 | 
					   *   An array of arguments to replace into the $condition of this join.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   The unique alias that was assigned for this table.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = array()) {
 | 
				
			||||||
 | 
					    return $this->addJoin('RIGHT OUTER', $table, $alias, $condition, $arguments);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Join against another table in the database.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * This method does the "hard" work of queuing up a table to be joined against.
 | 
				
			||||||
 | 
					   * In some cases, that may include dipping into the Schema API to find the necessary
 | 
				
			||||||
 | 
					   * fields on which to join.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $table
 | 
				
			||||||
 | 
					   *   The table against which to join.
 | 
				
			||||||
 | 
					   * @param $alias
 | 
				
			||||||
 | 
					   *   The alias for the table.  In most cases this should be the first letter
 | 
				
			||||||
 | 
					   *   of the table, or the first letter of each "word" in the table.  If omitted,
 | 
				
			||||||
 | 
					   *   one will be dynamically generated.
 | 
				
			||||||
 | 
					   * @param $condition
 | 
				
			||||||
 | 
					   *   The condition on which to join this table.  If the join requires values,
 | 
				
			||||||
 | 
					   *   this clause should use a named placeholder and the value or values to
 | 
				
			||||||
 | 
					   *   insert should be passed in the 4th parameter.  For the first table joined
 | 
				
			||||||
 | 
					   *   on a query, this value is ignored as the first table is taken as the base
 | 
				
			||||||
 | 
					   *   table.
 | 
				
			||||||
 | 
					   * @param $argments
 | 
				
			||||||
 | 
					   *   An array of arguments to replace into the $condition of this join.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   The unique alias that was assigned for this table.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = array()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (empty($alias)) {
 | 
				
			||||||
 | 
					      $alias = $table;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $alias_candidate = $alias;
 | 
				
			||||||
 | 
					    $count = 2;
 | 
				
			||||||
 | 
					    while (!empty($this->tables[$alias_candidate])) {
 | 
				
			||||||
 | 
					      $alias_candidate = $alias . '_' . $count++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $alias = $alias_candidate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $this->tables[$alias] = array(
 | 
				
			||||||
 | 
					      'join type' => $type,
 | 
				
			||||||
 | 
					      'table' => $table,
 | 
				
			||||||
 | 
					      'alias' => $alias,
 | 
				
			||||||
 | 
					      'condition' => $condition,
 | 
				
			||||||
 | 
					      'arguments' => $arguments,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $alias;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Orders the result set by a given field.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * If called multiple times, the query will order by each specified field in the
 | 
				
			||||||
 | 
					   * order this method is called.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $field
 | 
				
			||||||
 | 
					   *   The field on which to order.
 | 
				
			||||||
 | 
					   * @param $direction
 | 
				
			||||||
 | 
					   *   The direction to sort.  Legal values are "ASC" and "DESC".
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   The called object.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function orderBy($field, $direction = 'ASC') {
 | 
				
			||||||
 | 
					    $this->order[$field] = $direction;
 | 
				
			||||||
 | 
					    return $this;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Restricts a query to a given range in the result set.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * If this method is called with no parameters, will remove any range
 | 
				
			||||||
 | 
					   * directives that have been set.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $start
 | 
				
			||||||
 | 
					   *   The first record from the result set to return.  If NULL, removes any
 | 
				
			||||||
 | 
					   *   range directives that are set.
 | 
				
			||||||
 | 
					   * @param $limit
 | 
				
			||||||
 | 
					   *   The number of records to return from the result set.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   The called object.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function range($start = NULL, $length = NULL) {
 | 
				
			||||||
 | 
					    $this->range = func_num_args() ? array('start' => $start, 'length' => $length) : array();
 | 
				
			||||||
 | 
					    return $this;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Groups the result set by the specified field.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param $field
 | 
				
			||||||
 | 
					   *   The field on which to group.  This should be the field as aliased.
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   The called object.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function groupBy($field) {
 | 
				
			||||||
 | 
					    $this->group[] = $field;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Get the equivalent COUNT query of this query as a new query object.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *   A new SelectQuery object with no fields or expressions besides COUNT(*).
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function countQuery() {
 | 
				
			||||||
 | 
					    // Shallow-clone this query.  We don't want to duplicate any of the
 | 
				
			||||||
 | 
					    // referenced objects, so a shallow query is all we need.
 | 
				
			||||||
 | 
					    $count = clone($this);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Zero-out existing fields and expressions.
 | 
				
			||||||
 | 
					    $fields =& $count->getFields();
 | 
				
			||||||
 | 
					    $fields = array();
 | 
				
			||||||
 | 
					    $expressions =& $count->getExpressions();
 | 
				
			||||||
 | 
					    $expressions = array();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Ordering a count query is a waste of cycles, and breaks on some
 | 
				
			||||||
 | 
					    // databases anyway.
 | 
				
			||||||
 | 
					    $orders = &$count->getOrderBy();
 | 
				
			||||||
 | 
					    $orders = array();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // COUNT() is an expression, so we add that back in.
 | 
				
			||||||
 | 
					    $count->addExpression('COUNT(*)');
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return $count;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function __toString() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // SELECT
 | 
				
			||||||
 | 
					    $query = 'SELECT ';
 | 
				
			||||||
 | 
					    if ($this->distinct) {
 | 
				
			||||||
 | 
					      $query .= 'DISTINCT ';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // FIELDS and EXPRESSIONS
 | 
				
			||||||
 | 
					    $fields = array();
 | 
				
			||||||
 | 
					    foreach ($this->fields as $alias => $field) {
 | 
				
			||||||
 | 
					      $fields[] = (isset($field['table']) ? $field['table'] . '.' : '') . $field['field'] . ' AS ' . $field['alias'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    foreach ($this->expressions as $alias => $expression) {
 | 
				
			||||||
 | 
					      $fields[] = $expression['expression'] . ' AS ' . $expression['alias'];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $query .= implode(', ', $fields);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // FROM - We presume all queries have a FROM, as any query that doesn't won't need the query builder anyway.
 | 
				
			||||||
 | 
					    $query .= "\nFROM ";
 | 
				
			||||||
 | 
					    foreach ($this->tables as $alias => $table) {
 | 
				
			||||||
 | 
					      $query .= "\n";
 | 
				
			||||||
 | 
					      if (isset($table['join type'])) {
 | 
				
			||||||
 | 
					        $query .= $table['join type'] . ' JOIN ';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      $query .= '{' . $this->connection->escapeTable($table['table']) . '} AS ' . $table['alias'];
 | 
				
			||||||
 | 
					      if (!empty($table['condition'])) {
 | 
				
			||||||
 | 
					        $query .= ' ON ' . $table['condition'];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // WHERE
 | 
				
			||||||
 | 
					    if (count($this->where)) {
 | 
				
			||||||
 | 
					      $this->where->compile($this->connection);
 | 
				
			||||||
 | 
					      // There is an implicit string cast on $this->condition.
 | 
				
			||||||
 | 
					      $query .= "\nWHERE " . $this->where;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // GROUP BY
 | 
				
			||||||
 | 
					    if ($this->group) {
 | 
				
			||||||
 | 
					      $query .= "\nGROUP BY " . implode(', ', $this->group);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // HAVING
 | 
				
			||||||
 | 
					    if (count($this->having)) {
 | 
				
			||||||
 | 
					      $this->having->compile($this->connection);
 | 
				
			||||||
 | 
					      // There is an implicit string cast on $this->having.
 | 
				
			||||||
 | 
					      $query .= "\nHAVING " . $this->having;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ORDER BY
 | 
				
			||||||
 | 
					    if ($this->order) {
 | 
				
			||||||
 | 
					      $query .= "\nORDER BY ";
 | 
				
			||||||
 | 
					      foreach ($this->order as $field => $direction) {
 | 
				
			||||||
 | 
					        $query .= $field . ' ' . $direction . ' ';
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // RANGE is database specific, so we can't do it here.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $query;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  public function __clone() {
 | 
				
			||||||
 | 
					    // On cloning, also clone the conditional objects.  However, we do not
 | 
				
			||||||
 | 
					    // want to clone the database connection object as that would duplicate the
 | 
				
			||||||
 | 
					    // connection itself.
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $this->where = clone($this->where);
 | 
				
			||||||
 | 
					    $this->having = clone($this->having);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @} End of "ingroup database".
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -208,17 +208,114 @@ function drupal_detect_baseurl($file = 'install.php') {
 | 
				
			||||||
function drupal_detect_database_types() {
 | 
					function drupal_detect_database_types() {
 | 
				
			||||||
  $databases = array();
 | 
					  $databases = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  foreach (array('mysql', 'mysqli', 'pgsql') as $type) {
 | 
					  foreach (scandir('./includes/database') as $driver) {
 | 
				
			||||||
    if (file_exists('./includes/install.' . $type . '.inc')) {
 | 
					    $driver_dir = './includes/database/' . $driver;
 | 
				
			||||||
      include_once './includes/install.' . $type . '.inc';
 | 
					    if (!is_dir($driver_dir) || strpos($driver, '.') === 0) {
 | 
				
			||||||
      $function = $type . '_is_available';
 | 
					      continue;
 | 
				
			||||||
      if ($function()) {
 | 
					    }
 | 
				
			||||||
        $databases[$type] = $type;
 | 
					    
 | 
				
			||||||
 | 
					    $drivers[] = $driver;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // We of course cannot rely on the registry at this point.
 | 
				
			||||||
 | 
					    include_once($driver_dir . '/database.inc');
 | 
				
			||||||
 | 
					    include_once($install_file = $driver_dir . '/install.inc');
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    $class = 'DatabaseInstaller_' . $driver;
 | 
				
			||||||
 | 
					    $installer = new $class();
 | 
				
			||||||
 | 
					    if ($installer->installable()) {
 | 
				
			||||||
 | 
					      $databases[$driver] = $installer->name();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return $databases;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class DatabaseInstaller {
 | 
				
			||||||
 | 
					  protected $success = array();
 | 
				
			||||||
 | 
					  protected $tests = array(
 | 
				
			||||||
 | 
					    'testCreate' => array(
 | 
				
			||||||
 | 
					      'query' => 'CREATE TABLE drupal_install_test (id int NULL)',
 | 
				
			||||||
 | 
					      'success' => 'CREATE',
 | 
				
			||||||
 | 
					      'message' => 'Failed to create a test table on your %name database server with the command %query. %name reports the following message: %error.<ul><li>Are you sure the configured username has the necessary %name permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.',
 | 
				
			||||||
 | 
					      'fatal' => TRUE,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    'testInsert' => array(
 | 
				
			||||||
 | 
					      'query' => 'INSERT INTO drupal_install_test (id) VALUES (1)',
 | 
				
			||||||
 | 
					      'success' => 'INSERT',
 | 
				
			||||||
 | 
					      'message' => 'Failed to insert a value into a test table on your %name database server. We tried inserting a value with the command %query and %name reported the following error: %error.',
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    'testUpdate' => array(
 | 
				
			||||||
 | 
					      'query' => 'UPDATE drupal_install_test SET id = 2',
 | 
				
			||||||
 | 
					      'success' => 'UPDATE',
 | 
				
			||||||
 | 
					      'message' => 'Failed to update a value in a test table on your %name database server. We tried updating a value with the command %query and %name reported the following error: %error.',
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    'testDelete' => array(
 | 
				
			||||||
 | 
					      'query' => 'DELETE FROM drupal_install_test',
 | 
				
			||||||
 | 
					      'success' => 'DELETE',
 | 
				
			||||||
 | 
					      'message' => 'Failed to delete a value from a test table on your %name database server. We tried deleting a value with the command %query and %name reported the following error: %error.',
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    'testDrop' => array(
 | 
				
			||||||
 | 
					      'query' => 'DROP TABLE drupal_install_test',
 | 
				
			||||||
 | 
					      'success' => 'DELETE',
 | 
				
			||||||
 | 
					      'message' => 'Failed to drop a test table from your %name database server. We tried dropping a table with the command %query and %name reported the following error %error.',
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  public $error = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected function hasPdoDriver() {
 | 
				
			||||||
 | 
					    return in_array($this->pdoDriver, PDO::getAvailableDrivers());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function installable() {
 | 
				
			||||||
 | 
					    return $this->hasPdoDriver();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  abstract public function name();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function test() {
 | 
				
			||||||
 | 
					    $return = $this->testConnect();
 | 
				
			||||||
 | 
					    if ($return === FALSE) {
 | 
				
			||||||
 | 
					      return FALSE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    foreach ($this->tests as $test) {
 | 
				
			||||||
 | 
					      $return = $this->runTestQuery($test['query'], $test['success'], $test['message'], !empty($tests['fatal']));
 | 
				
			||||||
 | 
					      if ($return === FALSE) {
 | 
				
			||||||
 | 
					        return FALSE;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    return $this->success;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Check if we can connect to the database.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return
 | 
				
			||||||
 | 
					   *  FALSE on failure.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function testConnect() {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      db_set_active();
 | 
				
			||||||
 | 
					      $this->success[] = 'CONNECT';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    catch (Exception $e) {
 | 
				
			||||||
 | 
					      drupal_set_message(st('Failed to connect to your %name database server. %name reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => $e->getMessage(), 'name' => $this->name())), 'error');
 | 
				
			||||||
 | 
					      return FALSE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return $databases;
 | 
					  protected function runTestQuery($query, $success, $message, $fatal = FALSE) {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      db_query($query);
 | 
				
			||||||
 | 
					      $this->success[] = $success;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    catch (Exception $e) {
 | 
				
			||||||
 | 
					      drupal_set_message(st($message, array('%query' => $query, '%error' => $e->getMessage(), '%name' => $this->name())), 'error');
 | 
				
			||||||
 | 
					      $this->error = TRUE;
 | 
				
			||||||
 | 
					      if ($fatal) {
 | 
				
			||||||
 | 
					        return FALSE;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -269,7 +366,7 @@ function drupal_rewrite_settings($settings = array(), $prefix = '') {
 | 
				
			||||||
          // Write new value to settings.php in the following format:
 | 
					          // Write new value to settings.php in the following format:
 | 
				
			||||||
          //    $'setting' = 'value'; // 'comment'
 | 
					          //    $'setting' = 'value'; // 'comment'
 | 
				
			||||||
          $setting = $settings[$variable[1]];
 | 
					          $setting = $settings[$variable[1]];
 | 
				
			||||||
          $buffer .= '$' . $variable[1] . " = '" . $setting['value'] . "';" . (!empty($setting['comment']) ? ' // ' . $setting['comment'] . "\n" : "\n");
 | 
					          $buffer .= '$' . $variable[1] . " = " . var_export($setting['value'], TRUE) . ";" . (!empty($setting['comment']) ? ' // ' . $setting['comment'] . "\n" : "\n");
 | 
				
			||||||
          unset($settings[$variable[1]]);
 | 
					          unset($settings[$variable[1]]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
| 
						 | 
					@ -285,7 +382,7 @@ function drupal_rewrite_settings($settings = array(), $prefix = '') {
 | 
				
			||||||
    // Add required settings that were missing from settings.php.
 | 
					    // Add required settings that were missing from settings.php.
 | 
				
			||||||
    foreach ($settings as $setting => $data) {
 | 
					    foreach ($settings as $setting => $data) {
 | 
				
			||||||
      if ($data['required']) {
 | 
					      if ($data['required']) {
 | 
				
			||||||
        $buffer .= "\$$setting = '" . $data['value'] . "';\n";
 | 
					        $buffer .= "\$$setting = " . var_export($data['value'], TRUE) . ";\n";
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -404,6 +501,27 @@ function _drupal_install_module($module) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Manually include all files for the active database.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Because we have no registry yet, we need to manually include the
 | 
				
			||||||
 | 
					 * necessary database include files.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function drupal_install_init_database() {
 | 
				
			||||||
 | 
					  static $included = FALSE;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (!$included) {
 | 
				
			||||||
 | 
					    $connection_info = Database::getConnectionInfo();
 | 
				
			||||||
 | 
					    $driver = $connection_info['default']['driver'];
 | 
				
			||||||
 | 
					    require_once('./includes/database/query.inc');
 | 
				
			||||||
 | 
					    require_once('./includes/database/select.inc');
 | 
				
			||||||
 | 
					    require_once('./includes/database/schema.inc');
 | 
				
			||||||
 | 
					    foreach (glob('./includes/database/' . $driver . '/*.inc') as $include_file) {
 | 
				
			||||||
 | 
					      require_once($include_file);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Callback to install the system module.
 | 
					 * Callback to install the system module.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -413,11 +531,14 @@ function _drupal_install_module($module) {
 | 
				
			||||||
function drupal_install_system() {
 | 
					function drupal_install_system() {
 | 
				
			||||||
  $system_path = dirname(drupal_get_filename('module', 'system', NULL));
 | 
					  $system_path = dirname(drupal_get_filename('module', 'system', NULL));
 | 
				
			||||||
  require_once './' . $system_path . '/system.install';
 | 
					  require_once './' . $system_path . '/system.install';
 | 
				
			||||||
 | 
					  drupal_install_init_database();
 | 
				
			||||||
  module_invoke('system', 'install');
 | 
					  module_invoke('system', 'install');
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
  $system_versions = drupal_get_schema_versions('system');
 | 
					  $system_versions = drupal_get_schema_versions('system');
 | 
				
			||||||
  $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED;
 | 
					  $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED;
 | 
				
			||||||
  db_query("INSERT INTO {system} (filename, name, type, owner, status, bootstrap, schema_version) VALUES('%s', '%s', '%s', '%s', %d, %d, %d)", $system_path . '/system.module', 'system', 'module', '', 1, 0, $system_version);
 | 
					  db_query("INSERT INTO {system} (filename, name, type, owner, status, bootstrap, schema_version) VALUES('%s', '%s', '%s', '%s', %d, %d, %d)", $system_path . '/system.module', 'system', 'module', '', 1, 0, $system_version);
 | 
				
			||||||
  // Now that we've installed things properly, bootstrap the full Drupal environment
 | 
					  // Now that we've installed things properly, bootstrap the full Drupal environment
 | 
				
			||||||
 | 
					  drupal_install_init_database();
 | 
				
			||||||
  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 | 
					  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 | 
				
			||||||
  module_rebuild_cache();
 | 
					  module_rebuild_cache();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,117 +0,0 @@
 | 
				
			||||||
<?php
 | 
					 | 
				
			||||||
// $Id$
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MySQL specific install functions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Check if MySQL is available.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  TRUE/FALSE
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function mysql_is_available() {
 | 
					 | 
				
			||||||
  return function_exists('mysql_connect');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Check if we can connect to MySQL.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  TRUE/FALSE
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function drupal_test_mysql($url, &$success) {
 | 
					 | 
				
			||||||
  if (!mysql_is_available()) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('PHP MySQL support not enabled.'), 'error');
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $url = parse_url($url);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Decode url-encoded information in the db connection string.
 | 
					 | 
				
			||||||
  $url['user'] = urldecode($url['user']);
 | 
					 | 
				
			||||||
  $url['pass'] = isset($url['pass']) ? urldecode($url['pass']) : '';
 | 
					 | 
				
			||||||
  $url['host'] = urldecode($url['host']);
 | 
					 | 
				
			||||||
  $url['path'] = urldecode($url['path']);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Allow for non-standard MySQL port.
 | 
					 | 
				
			||||||
  if (isset($url['port'])) {
 | 
					 | 
				
			||||||
    $url['host'] = $url['host'] . ':' . $url['port'];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test connecting to the database.
 | 
					 | 
				
			||||||
  $connection = @mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2);
 | 
					 | 
				
			||||||
  if (!$connection) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to connect to your MySQL database server. MySQL reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => mysql_error())), 'error');
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test selecting the database.
 | 
					 | 
				
			||||||
  if (!mysql_select_db(substr($url['path'], 1))) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to select your database on your MySQL database server, which means the connection username and password are valid, but there is a problem accessing your data. MySQL reports the following message: %error.<ul><li>Are you sure you have the correct database name?</li><li>Are you sure the database exists?</li><li>Are you sure the username has permission to access the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => mysql_error())), 'error');
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $success = array('CONNECT');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test CREATE.
 | 
					 | 
				
			||||||
  $query = 'CREATE TABLE drupal_install_test (id int NULL)';
 | 
					 | 
				
			||||||
  $result = mysql_query($query);
 | 
					 | 
				
			||||||
  if ($error = mysql_error()) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to create a test table on your MySQL database server with the command %query. MySQL reports the following message: %error.<ul><li>Are you sure the configured username has the necessary MySQL permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  $err = FALSE;
 | 
					 | 
				
			||||||
  $success[] = 'SELECT';
 | 
					 | 
				
			||||||
  $success[] = 'CREATE';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test INSERT.
 | 
					 | 
				
			||||||
  $query = 'INSERT INTO drupal_install_test (id) VALUES (1)';
 | 
					 | 
				
			||||||
  $result = mysql_query($query);
 | 
					 | 
				
			||||||
  if ($error = mysql_error()) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to insert a value into a test table on your MySQL database server. We tried inserting a value with the command %query and MySQL reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'INSERT';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test UPDATE.
 | 
					 | 
				
			||||||
  $query = 'UPDATE drupal_install_test SET id = 2';
 | 
					 | 
				
			||||||
  $result = mysql_query($query);
 | 
					 | 
				
			||||||
  if ($error = mysql_error()) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to update a value in a test table on your MySQL database server. We tried updating a value with the command %query and MySQL reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'UPDATE';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test DELETE.
 | 
					 | 
				
			||||||
  $query = 'DELETE FROM drupal_install_test';
 | 
					 | 
				
			||||||
  $result = mysql_query($query);
 | 
					 | 
				
			||||||
  if ($error = mysql_error()) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to delete a value from a test table on your MySQL database server. We tried deleting a value with the command %query and MySQL reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'DELETE';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test DROP.
 | 
					 | 
				
			||||||
  $query = 'DROP TABLE drupal_install_test';
 | 
					 | 
				
			||||||
  $result = mysql_query($query);
 | 
					 | 
				
			||||||
  if ($error = mysql_error()) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to drop a test table from your MySQL database server. We tried dropping a table with the command %query and MySQL reported the following error %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'DROP';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ($err) {
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  mysql_close($connection);
 | 
					 | 
				
			||||||
  return TRUE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,112 +0,0 @@
 | 
				
			||||||
<?php
 | 
					 | 
				
			||||||
// $Id$
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MySQLi specific install functions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Check if MySQLi is available.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  TRUE/FALSE
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function mysqli_is_available() {
 | 
					 | 
				
			||||||
  return function_exists('mysqli_connect');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Check if we can connect to MySQL.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  TRUE/FALSE
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function drupal_test_mysqli($url, &$success) {
 | 
					 | 
				
			||||||
  if (!mysqli_is_available()) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('PHP MySQLi support not enabled.'), 'error');
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $url = parse_url($url);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Decode url-encoded information in the db connection string.
 | 
					 | 
				
			||||||
  $url['user'] = urldecode($url['user']);
 | 
					 | 
				
			||||||
  $url['pass'] = isset($url['pass']) ? urldecode($url['pass']) : '';
 | 
					 | 
				
			||||||
  $url['host'] = urldecode($url['host']);
 | 
					 | 
				
			||||||
  $url['path'] = urldecode($url['path']);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $connection = mysqli_init();
 | 
					 | 
				
			||||||
  @mysqli_real_connect($connection, $url['host'], $url['user'], $url['pass'], substr($url['path'], 1), $url['port'], NULL, MYSQLI_CLIENT_FOUND_ROWS);
 | 
					 | 
				
			||||||
  if (mysqli_connect_errno() >= 2000 || mysqli_connect_errno() == 1045) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to connect to your MySQL database server. MySQL reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => mysqli_connect_error())), 'error');
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test selecting the database.
 | 
					 | 
				
			||||||
  if (mysqli_connect_errno() > 0) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to select your database on your MySQL database server, which means the connection username and password are valid, but there is a problem accessing your data. MySQL reports the following message: %error.<ul><li>Are you sure you have the correct database name?</li><li>Are you sure the database exists?</li><li>Are you sure the username has permission to access the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => mysqli_connect_error())), 'error');
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $success = array('CONNECT');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test CREATE.
 | 
					 | 
				
			||||||
  $query = 'CREATE TABLE drupal_install_test (id int NULL)';
 | 
					 | 
				
			||||||
  $result = mysqli_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = mysqli_error($connection)) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to create a test table on your MySQL database server with the command %query. MySQL reports the following message: %error.<ul><li>Are you sure the configured username has the necessary MySQL permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  $err = FALSE;
 | 
					 | 
				
			||||||
  $success[] = 'SELECT';
 | 
					 | 
				
			||||||
  $success[] = 'CREATE';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test INSERT.
 | 
					 | 
				
			||||||
  $query = 'INSERT INTO drupal_install_test (id) VALUES (1)';
 | 
					 | 
				
			||||||
  $result = mysqli_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = mysqli_error($connection)) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to insert a value into a test table on your MySQL database server. We tried inserting a value with the command %query and MySQL reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'INSERT';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test UPDATE.
 | 
					 | 
				
			||||||
  $query = 'UPDATE drupal_install_test SET id = 2';
 | 
					 | 
				
			||||||
  $result = mysqli_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = mysqli_error($connection)) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to update a value in a test table on your MySQL database server. We tried updating a value with the command %query and MySQL reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'UPDATE';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test DELETE.
 | 
					 | 
				
			||||||
  $query = 'DELETE FROM drupal_install_test';
 | 
					 | 
				
			||||||
  $result = mysqli_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = mysqli_error($connection)) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to delete a value from a test table on your MySQL database server. We tried deleting a value with the command %query and MySQL reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'DELETE';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test DROP.
 | 
					 | 
				
			||||||
  $query = 'DROP TABLE drupal_install_test';
 | 
					 | 
				
			||||||
  $result = mysqli_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = mysqli_error($connection)) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to drop a test table from your MySQL database server. We tried dropping a table with the command %query and MySQL reported the following error %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'DROP';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ($err) {
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  mysqli_close($connection);
 | 
					 | 
				
			||||||
  return TRUE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,140 +0,0 @@
 | 
				
			||||||
<?php
 | 
					 | 
				
			||||||
// $Id$
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PostgreSQL specific install functions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Check if PostgreSQL is available.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  TRUE/FALSE
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function pgsql_is_available() {
 | 
					 | 
				
			||||||
  return function_exists('pg_connect');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Check if we can connect to PostgreSQL.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return
 | 
					 | 
				
			||||||
 *  TRUE/FALSE
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function drupal_test_pgsql($url, &$success) {
 | 
					 | 
				
			||||||
  if (!pgsql_is_available()) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('PHP PostgreSQL support not enabled.'), 'error');
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $url = parse_url($url);
 | 
					 | 
				
			||||||
  $conn_string = '';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Decode url-encoded information in the db connection string
 | 
					 | 
				
			||||||
  if (isset($url['user'])) {
 | 
					 | 
				
			||||||
    $conn_string .= ' user=' . urldecode($url['user']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($url['pass'])) {
 | 
					 | 
				
			||||||
    $conn_string .= ' password=' . urldecode($url['pass']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($url['host'])) {
 | 
					 | 
				
			||||||
    $conn_string .= ' host=' . urldecode($url['host']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($url['path'])) {
 | 
					 | 
				
			||||||
    $conn_string .= ' dbname=' . substr(urldecode($url['path']), 1);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (isset($url['port'])) {
 | 
					 | 
				
			||||||
    $conn_string .= ' port=' . urldecode($url['port']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test connecting to the database.
 | 
					 | 
				
			||||||
  $connection = @pg_connect($conn_string);
 | 
					 | 
				
			||||||
  if (!$connection) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to connect to your PostgreSQL database server. PostgreSQL reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li><li>Are you sure you typed the correct database name?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => 'Connection failed. See log file for failure reason')), 'error');
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $success = array('CONNECT');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test CREATE.
 | 
					 | 
				
			||||||
  $query = 'CREATE TABLE drupal_install_test (id integer NOT NULL)';
 | 
					 | 
				
			||||||
  $result = pg_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = pg_result_error($result)) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to create a test table on your PostgreSQL database server with the command %query. PostgreSQL reports the following message: %error.<ul><li>Are you sure the configured username has the necessary PostgreSQL permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  $err = FALSE;
 | 
					 | 
				
			||||||
  $success[] = 'SELECT';
 | 
					 | 
				
			||||||
  $success[] = 'CREATE';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test INSERT.
 | 
					 | 
				
			||||||
  $query = 'INSERT INTO drupal_install_test (id) VALUES (1)';
 | 
					 | 
				
			||||||
  $result = pg_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = pg_result_error($result)) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to insert a value into a test table on your PostgreSQL database server. We tried inserting a value with the command %query and PostgreSQL reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'INSERT';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test UPDATE.
 | 
					 | 
				
			||||||
  $query = 'UPDATE drupal_install_test SET id = 2';
 | 
					 | 
				
			||||||
  $result = pg_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = pg_result_error($result)) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to update a value in a test table on your PostgreSQL database server. We tried updating a value with the command %query and PostgreSQL reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'UPDATE';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test LOCK.
 | 
					 | 
				
			||||||
  $query = 'BEGIN; LOCK drupal_install_test IN SHARE ROW EXCLUSIVE MODE';
 | 
					 | 
				
			||||||
  $result = pg_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = pg_result_error($result)) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to lock a test table on your PostgreSQL database server. We tried locking a table with the command %query and PostgreSQL reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'LOCK';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test UNLOCK, which is done automatically upon transaction end in PostgreSQL
 | 
					 | 
				
			||||||
  $query = 'COMMIT';
 | 
					 | 
				
			||||||
  $result = pg_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = pg_result_error()) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to unlock a test table on your PostgreSQL database server. We tried unlocking a table with the command %query and PostgreSQL reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'UNLOCK';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test DELETE.
 | 
					 | 
				
			||||||
  $query = 'DELETE FROM drupal_install_test';
 | 
					 | 
				
			||||||
  $result = pg_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = pg_result_error()) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to delete a value from a test table on your PostgreSQL database server. We tried deleting a value with the command %query and PostgreSQL reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'DELETE';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Test DROP.
 | 
					 | 
				
			||||||
  $query = 'DROP TABLE drupal_install_test';
 | 
					 | 
				
			||||||
  $result = pg_query($connection, $query);
 | 
					 | 
				
			||||||
  if ($error = pg_result_error()) {
 | 
					 | 
				
			||||||
    drupal_set_message(st('Failed to drop a test table from your PostgreSQL database server. We tried dropping a table with the command %query and PostgreSQL reported the following error %error.', array('%query' => $query, '%error' => $error)), 'error');
 | 
					 | 
				
			||||||
    $err = TRUE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    $success[] = 'DROP';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ($err) {
 | 
					 | 
				
			||||||
    return FALSE;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  pg_close($connection);
 | 
					 | 
				
			||||||
  return TRUE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1943,34 +1943,34 @@ function _locale_translate_seek() {
 | 
				
			||||||
    // Compute LIKE section
 | 
					    // Compute LIKE section
 | 
				
			||||||
    switch ($query['translation']) {
 | 
					    switch ($query['translation']) {
 | 
				
			||||||
      case 'translated':
 | 
					      case 'translated':
 | 
				
			||||||
        $where = "WHERE (t.translation LIKE '%%%s%%')";
 | 
					        $where = "WHERE (t.translation LIKE ?)";
 | 
				
			||||||
        $orderby = "ORDER BY t.translation";
 | 
					        $orderby = "ORDER BY t.translation";
 | 
				
			||||||
        $arguments[] = $query['string'];
 | 
					        $arguments[] = '%'. $query['string'] .'%';
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case 'untranslated':
 | 
					      case 'untranslated':
 | 
				
			||||||
        $where = "WHERE (s.source LIKE '%%%s%%' AND t.translation IS NULL)";
 | 
					        $where = "WHERE (s.source LIKE ? AND t.translation IS NULL)";
 | 
				
			||||||
        $orderby = "ORDER BY s.source";
 | 
					        $orderby = "ORDER BY s.source";
 | 
				
			||||||
        $arguments[] = $query['string'];
 | 
					        $arguments[] = '%'. $query['string'] .'%';
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case 'all' :
 | 
					      case 'all' :
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        $where = "WHERE (s.source LIKE '%%%s%%' OR t.translation LIKE '%%%s%%')";
 | 
					        $where = "WHERE (s.source LIKE ? OR t.translation LIKE ?)";
 | 
				
			||||||
        $orderby = '';
 | 
					        $orderby = '';
 | 
				
			||||||
        $arguments[] = $query['string'];
 | 
					        $arguments[] = '%'. $query['string'] .'%';
 | 
				
			||||||
        $arguments[] = $query['string'];
 | 
					        $arguments[] = '%'. $query['string'] .'%';
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    $grouplimit = '';
 | 
					    $grouplimit = '';
 | 
				
			||||||
    if (!empty($query['group']) && $query['group'] != 'all') {
 | 
					    if (!empty($query['group']) && $query['group'] != 'all') {
 | 
				
			||||||
      $grouplimit = " AND s.textgroup = '%s'";
 | 
					      $grouplimit = " AND s.textgroup = ?";
 | 
				
			||||||
      $arguments[] = $query['group'];
 | 
					      $arguments[] = $query['group'];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch ($query['language']) {
 | 
					    switch ($query['language']) {
 | 
				
			||||||
      // Force search in source strings
 | 
					      // Force search in source strings
 | 
				
			||||||
      case "en":
 | 
					      case "en":
 | 
				
			||||||
        $sql = $join . " WHERE s.source LIKE '%%%s%%' $grouplimit ORDER BY s.source";
 | 
					        $sql = $join . " WHERE s.source LIKE ? $grouplimit ORDER BY s.source";
 | 
				
			||||||
        $arguments = array($query['string']); // $where is not used, discard its arguments
 | 
					        $arguments = array('%' . $query['string'] . '%'); // $where is not used, discard its arguments
 | 
				
			||||||
        if (!empty($grouplimit)) {
 | 
					        if (!empty($grouplimit)) {
 | 
				
			||||||
          $arguments[] = $query['group'];
 | 
					          $arguments[] = $query['group'];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1981,7 +1981,7 @@ function _locale_translate_seek() {
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      // Some different language
 | 
					      // Some different language
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        $sql = "$join AND t.language = '%s' $where $grouplimit $orderby";
 | 
					        $sql = "$join AND t.language = ? $where $grouplimit $orderby";
 | 
				
			||||||
        array_unshift($arguments, $query['language']);
 | 
					        array_unshift($arguments, $query['language']);
 | 
				
			||||||
        // Don't show translation flags for other languages, we can't see them with this search.
 | 
					        // Don't show translation flags for other languages, we can't see them with this search.
 | 
				
			||||||
        $limit_language = $query['language'];
 | 
					        $limit_language = $query['language'];
 | 
				
			||||||
| 
						 | 
					@ -2091,7 +2091,12 @@ function _locale_rebuild_js($langcode = NULL) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Construct the array for JavaScript translations.
 | 
					  // Construct the array for JavaScript translations.
 | 
				
			||||||
  // We sort on plural so that we have all plural forms before singular forms.
 | 
					  // We sort on plural so that we have all plural forms before singular forms.
 | 
				
			||||||
  $result = db_query("SELECT s.lid, s.source, t.plid, t.plural, t.translation FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.location LIKE '%%.js%%' AND s.textgroup = 'default' ORDER BY t.plural DESC", $language->language);
 | 
					  $result = db_query("SELECT s.lid, s.source, t.plid, t.plural, t.translation 
 | 
				
			||||||
 | 
					    FROM {locales_source} s 
 | 
				
			||||||
 | 
					      LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language 
 | 
				
			||||||
 | 
					    WHERE s.location LIKE '%.js%' 
 | 
				
			||||||
 | 
					      AND s.textgroup = 'default' 
 | 
				
			||||||
 | 
					    ORDER BY t.plural DESC", array(':language' => $language->language));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $translations = $plurals = array();
 | 
					  $translations = $plurals = array();
 | 
				
			||||||
  while ($data = db_fetch_object($result)) {
 | 
					  while ($data = db_fetch_object($result)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1719,7 +1719,7 @@ function menu_router_build($reset = FALSE) {
 | 
				
			||||||
  static $menu;
 | 
					  static $menu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!isset($menu) || $reset) {
 | 
					  if (!isset($menu) || $reset) {
 | 
				
			||||||
    if (!$reset && ($cache = cache_get('router:', 'cache_menu')) && isset($cache->data)) {
 | 
					    if (FALSE && !$reset && ($cache = cache_get('router:', 'cache_menu')) && isset($cache->data)) {
 | 
				
			||||||
      $menu = $cache->data;
 | 
					      $menu = $cache->data;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
| 
						 | 
					@ -1810,7 +1810,7 @@ function _menu_navigation_links_rebuild($menu) {
 | 
				
			||||||
      db_query("UPDATE {menu_links} SET router_path = '%s', updated = %d WHERE mlid = %d", $router_path, $updated, $item['mlid']);
 | 
					      db_query("UPDATE {menu_links} SET router_path = '%s', updated = %d WHERE mlid = %d", $router_path, $updated, $item['mlid']);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  // Find any item whose router path does not exist any more.
 | 
					  // Find any items where their router path does not exist any more.
 | 
				
			||||||
  $result = db_query("SELECT * FROM {menu_links} WHERE router_path NOT IN ($placeholders) AND external = 0 AND updated = 0 AND customized = 0 ORDER BY depth DESC", $paths);
 | 
					  $result = db_query("SELECT * FROM {menu_links} WHERE router_path NOT IN ($placeholders) AND external = 0 AND updated = 0 AND customized = 0 ORDER BY depth DESC", $paths);
 | 
				
			||||||
  // Remove all such items. Starting from those with the greatest depth will
 | 
					  // Remove all such items. Starting from those with the greatest depth will
 | 
				
			||||||
  // minimize the amount of re-parenting done by menu_link_delete().
 | 
					  // minimize the amount of re-parenting done by menu_link_delete().
 | 
				
			||||||
| 
						 | 
					@ -1888,7 +1888,7 @@ function menu_link_save(&$item) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // This is the easiest way to handle the unique internal path '<front>',
 | 
					  // This is the easiest way to handle the unique internal path '<front>',
 | 
				
			||||||
  // since a path marked as external does not need to match a router path.
 | 
					  // since a path marked as external does not need to match a router path.
 | 
				
			||||||
  $item['_external'] = menu_path_is_external($item['link_path'])  || $item['link_path'] == '<front>';
 | 
					  $item['_external'] = (menu_path_is_external($item['link_path'])  || $item['link_path'] == '<front>') ? 1 : 0;
 | 
				
			||||||
  // Load defaults.
 | 
					  // Load defaults.
 | 
				
			||||||
  $item += array(
 | 
					  $item += array(
 | 
				
			||||||
    'menu_name' => 'navigation',
 | 
					    'menu_name' => 'navigation',
 | 
				
			||||||
| 
						 | 
					@ -2212,10 +2212,22 @@ function _menu_update_parental_status($item, $exclude = FALSE) {
 | 
				
			||||||
  // If plid == 0, there is nothing to update.
 | 
					  // If plid == 0, there is nothing to update.
 | 
				
			||||||
  if ($item['plid']) {
 | 
					  if ($item['plid']) {
 | 
				
			||||||
    // We may want to exclude the passed link as a possible child.
 | 
					    // We may want to exclude the passed link as a possible child.
 | 
				
			||||||
    $where = $exclude ? " AND mlid != %d" : '';
 | 
					    //$where = $exclude ? " AND mlid != %d" : '';
 | 
				
			||||||
    // Check if at least one visible child exists in the table.
 | 
					    // Check if at least one visible child exists in the table.
 | 
				
			||||||
    $parent_has_children = (bool)db_result(db_query_range("SELECT mlid FROM {menu_links} WHERE menu_name = '%s' AND plid = %d AND hidden = 0" . $where, $item['menu_name'], $item['plid'], $item['mlid'], 0, 1));
 | 
					     $query = db_select('menu_links', 'm');
 | 
				
			||||||
 | 
					    $query->addField('m', 'mlid');
 | 
				
			||||||
 | 
					    $query->condition('menu_name', $item['menu_name']);
 | 
				
			||||||
 | 
					    $query->condition('plid', $item['plid']);
 | 
				
			||||||
 | 
					    $query->range(0, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($exclude) {
 | 
				
			||||||
 | 
					      $query->condition('mlid', $item['mlid'], '!=');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $parent_has_children = ((bool) $query->execute()->fetchField()) ? 1 : 0;
 | 
				
			||||||
 | 
					    //$parent_has_children = (bool)db_result(db_query_range("SELECT mlid FROM {menu_links} WHERE menu_name = '%s' AND plid = %d AND hidden = 0" . $where, $item['menu_name'], $item['plid'], $item['mlid'], 0, 1));
 | 
				
			||||||
    db_query("UPDATE {menu_links} SET has_children = %d WHERE mlid = %d", $parent_has_children, $item['plid']);
 | 
					    db_query("UPDATE {menu_links} SET has_children = %d WHERE mlid = %d", $parent_has_children, $item['plid']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,9 +36,9 @@ function module_load_all() {
 | 
				
			||||||
 *   modules.
 | 
					 *   modules.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function module_list($refresh = FALSE, $bootstrap = TRUE, $sort = FALSE, $fixed_list = NULL) {
 | 
					function module_list($refresh = FALSE, $bootstrap = TRUE, $sort = FALSE, $fixed_list = NULL) {
 | 
				
			||||||
  static $list, $sorted_list;
 | 
					  static $list = array(), $sorted_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ($refresh || $fixed_list) {
 | 
					  if (empty($list) || $refresh || $fixed_list) {
 | 
				
			||||||
    unset($sorted_list);
 | 
					    unset($sorted_list);
 | 
				
			||||||
    $list = array();
 | 
					    $list = array();
 | 
				
			||||||
    if ($fixed_list) {
 | 
					    if ($fixed_list) {
 | 
				
			||||||
| 
						 | 
					@ -240,7 +240,9 @@ function module_load_include($type, $module, $name = NULL) {
 | 
				
			||||||
    $name = $module;
 | 
					    $name = $module;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $file = './' . drupal_get_path('module', $module) . "/$name.$type";
 | 
					  if (drupal_function_exists('drupal_get_path')) {
 | 
				
			||||||
 | 
					    $file = './' . drupal_get_path('module', $module) . "/$name.$type";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (is_file($file)) {
 | 
					  if (is_file($file)) {
 | 
				
			||||||
    require_once $file;
 | 
					    require_once $file;
 | 
				
			||||||
| 
						 | 
					@ -388,31 +390,38 @@ function module_hook($module, $hook) {
 | 
				
			||||||
 * @param $refresh
 | 
					 * @param $refresh
 | 
				
			||||||
 *   For internal use only: Whether to force the stored list of hook
 | 
					 *   For internal use only: Whether to force the stored list of hook
 | 
				
			||||||
 *   implementations to be regenerated (such as after enabling a new module,
 | 
					 *   implementations to be regenerated (such as after enabling a new module,
 | 
				
			||||||
 *   before processing hook_enable).
 | 
					 *   before processing hook_enable).  Note that if $refresh is TRUE this function
 | 
				
			||||||
 | 
					 *   will always return NULL.
 | 
				
			||||||
 * @return
 | 
					 * @return
 | 
				
			||||||
 *   An array with the names of the modules which are implementing this hook.
 | 
					 *   An array with the names of the modules which are implementing this hook.
 | 
				
			||||||
 | 
					 *   If $hook is NULL then it will return the implementation cache.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function module_implements($hook, $sort = FALSE, $refresh = FALSE) {
 | 
					function module_implements($hook = NULL, $sort = FALSE, $refresh = FALSE) {
 | 
				
			||||||
  static $implementations = array();
 | 
					  static $implementations = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!isset($hook)) {
 | 
				
			||||||
 | 
					    return $implementations;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  if ($refresh) {
 | 
					  if ($refresh) {
 | 
				
			||||||
    $implementations = array();
 | 
					    $implementations = array();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (!defined('MAINTENANCE_MODE') && empty($implementations)) {
 | 
					  if (!defined('MAINTENANCE_MODE') && empty($implementations) && ($cache = cache_get('hooks', 'cache_registry'))) {
 | 
				
			||||||
    $implementations = registry_get_hook_implementations_cache();
 | 
					    $implementations = $cache->data;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!isset($implementations[$hook])) {
 | 
					  if ($hook) {
 | 
				
			||||||
    $implementations[$hook] = array();
 | 
					    if (!isset($implementations[$hook])) {
 | 
				
			||||||
    foreach (module_list() as $module) {
 | 
					      $implementations[$hook] = array();
 | 
				
			||||||
      if (module_hook($module, $hook)) {
 | 
					      foreach (module_list() as $module) {
 | 
				
			||||||
        $implementations[$hook][] = $module;
 | 
					        if (module_hook($module, $hook)) {
 | 
				
			||||||
 | 
					          $implementations[$hook][] = $module;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					    registry_cache_hook_implementations(array('hook' => $hook, 'modules' => $implementations[$hook]));
 | 
				
			||||||
  registry_cache_hook_implementations(array('hook' => $hook, 'modules' => $implementations[$hook]));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return $implementations[$hook];
 | 
					    return $implementations[$hook];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,20 @@
 | 
				
			||||||
 * @see registry_rebuild.
 | 
					 * @see registry_rebuild.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function _registry_rebuild() {
 | 
					function _registry_rebuild() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // The registry serves as a central autoloader for all classes, including
 | 
				
			||||||
 | 
					  // the database query builders.  However, the registry rebuild process
 | 
				
			||||||
 | 
					  // requires write ability to the database, which means having access to the
 | 
				
			||||||
 | 
					  // query builders that require the registry in order to be loaded.  That
 | 
				
			||||||
 | 
					  // causes a fatal race condition.  Therefore we manually include the
 | 
				
			||||||
 | 
					  // appropriate query builders for the currently active database before the
 | 
				
			||||||
 | 
					  // registry rebuild process runs.
 | 
				
			||||||
 | 
					  $connection_info = Database::getConnectionInfo();
 | 
				
			||||||
 | 
					  $driver = $connection_info['default']['driver'];
 | 
				
			||||||
 | 
					  require_once('./includes/database/query.inc');
 | 
				
			||||||
 | 
					  require_once('./includes/database/select.inc');
 | 
				
			||||||
 | 
					  require_once('./includes/database/' . $driver . '/query.inc');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Reset the resources cache.
 | 
					  // Reset the resources cache.
 | 
				
			||||||
  _registry_get_resource_name();
 | 
					  _registry_get_resource_name();
 | 
				
			||||||
  // Get the list of files we are going to parse.
 | 
					  // Get the list of files we are going to parse.
 | 
				
			||||||
| 
						 | 
					@ -47,13 +61,13 @@ function _registry_rebuild() {
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
      // Flush the registry of resources in files that are no longer on disc
 | 
					      // Flush the registry of resources in files that are no longer on disc
 | 
				
			||||||
      // or don't belong to installed modules.
 | 
					      // or don't belong to installed modules.
 | 
				
			||||||
      db_query("DELETE FROM {registry} WHERE filename = '%s'", $filename);
 | 
					      db_delete('registry')->condition('filename', $filename)->execute();
 | 
				
			||||||
      db_query("DELETE FROM {registry_file} WHERE filename = '%s'", $filename);
 | 
					      db_delete('registry_file')->condition('filename', $filename)->execute();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _registry_parse_files($files);
 | 
					  _registry_parse_files($files);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cache_clear_all('*', 'cache_registry');
 | 
					  cache_clear_all('*', 'cache_registry', TRUE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -61,10 +75,8 @@ function _registry_rebuild() {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function registry_get_parsed_files() {
 | 
					function registry_get_parsed_files() {
 | 
				
			||||||
  $files = array();
 | 
					  $files = array();
 | 
				
			||||||
  $res = db_query("SELECT * FROM {registry_file}");
 | 
					  // We want the result as a keyed array.
 | 
				
			||||||
  while ($file = db_fetch_array($res)) {
 | 
					  $files = db_query("SELECT * FROM {registry_file}")->fetchAllAssoc('filename', PDO::FETCH_ASSOC);
 | 
				
			||||||
    $files[$file['filename']] = $file;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return $files;
 | 
					  return $files;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -85,12 +97,10 @@ function _registry_parse_files($files) {
 | 
				
			||||||
      // don't make it through this rebuild, the next run will reparse the file.
 | 
					      // don't make it through this rebuild, the next run will reparse the file.
 | 
				
			||||||
      _registry_parse_file($filename, $contents);
 | 
					      _registry_parse_file($filename, $contents);
 | 
				
			||||||
      $file['md5'] = $md5;
 | 
					      $file['md5'] = $md5;
 | 
				
			||||||
      if ($new_file) {
 | 
					      db_merge('registry_file')
 | 
				
			||||||
        db_query("INSERT INTO {registry_file} (md5, filename) VALUES ('%s', '%s')", $md5, $filename);
 | 
					        ->key(array('filename' => $filename))
 | 
				
			||||||
      }
 | 
					        ->fields(array('md5' => $md5))
 | 
				
			||||||
      else {
 | 
					        ->execute();
 | 
				
			||||||
        db_query("UPDATE {registry_file} SET md5 = '%s' WHERE filename = '%s'", $md5, $filename);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -106,14 +116,24 @@ function _registry_parse_files($files) {
 | 
				
			||||||
function _registry_parse_file($filename, $contents) {
 | 
					function _registry_parse_file($filename, $contents) {
 | 
				
			||||||
  static $map = array(T_FUNCTION => 'function', T_CLASS => 'class', T_INTERFACE => 'interface');
 | 
					  static $map = array(T_FUNCTION => 'function', T_CLASS => 'class', T_INTERFACE => 'interface');
 | 
				
			||||||
  // Delete registry entries for this file, so we can insert the new resources.
 | 
					  // Delete registry entries for this file, so we can insert the new resources.
 | 
				
			||||||
  db_query("DELETE FROM {registry} WHERE filename = '%s'", $filename);
 | 
					  db_delete('registry')->condition('filename', $filename)->execute();
 | 
				
			||||||
  $tokens = token_get_all($contents);
 | 
					  $tokens = token_get_all($contents);
 | 
				
			||||||
  while ($token = next($tokens)) {
 | 
					  while ($token = next($tokens)) {
 | 
				
			||||||
    // Ignore all tokens except for those we are specifically saving.
 | 
					    // Ignore all tokens except for those we are specifically saving.
 | 
				
			||||||
    if (is_array($token) && isset($map[$token[0]])) {
 | 
					    if (is_array($token) && isset($map[$token[0]])) {
 | 
				
			||||||
      $type = $map[$token[0]];
 | 
					      $type = $map[$token[0]];
 | 
				
			||||||
      if ($resource_name = _registry_get_resource_name($tokens, $type)) {
 | 
					      if ($resource_name = _registry_get_resource_name($tokens, $type)) {
 | 
				
			||||||
        db_query("INSERT INTO {registry} (name, type, filename) VALUES ('%s', '%s', '%s')", $resource_name, $type, $filename);
 | 
					        // Because some systems, such as cache, currently use duplicate function
 | 
				
			||||||
 | 
					        // names in separate files an insert query cannot be used here as it
 | 
				
			||||||
 | 
					        // would cause a key constraint violation.  Instead we use a merge query.
 | 
				
			||||||
 | 
					        // In practice this should not be an issue as those systems all initialize
 | 
				
			||||||
 | 
					        // pre-registry and therefore are never loaded by the registry so it
 | 
				
			||||||
 | 
					        // doesn't matter if those records in the registry table point to one
 | 
				
			||||||
 | 
					        // filename instead of another.
 | 
				
			||||||
 | 
					        // TODO: Convert this back to an insert query after all duplicate
 | 
				
			||||||
 | 
					        // function names have been purged from Drupal.
 | 
				
			||||||
 | 
					        db_merge('registry')->key(array('name' => $resource_name, 'type' => $type))->fields(array('filename' => $filename))->execute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // We skip the body because classes may contain functions.
 | 
					        // We skip the body because classes may contain functions.
 | 
				
			||||||
        _registry_skip_body($tokens);
 | 
					        _registry_skip_body($tokens);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,18 +65,27 @@ function sess_write($key, $value) {
 | 
				
			||||||
    return TRUE;
 | 
					    return TRUE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  db_query("UPDATE {sessions} SET uid = %d, cache = %d, hostname = '%s', session = '%s', timestamp = %d WHERE sid = '%s'", $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time(), $key);
 | 
					  $result = db_result(db_query("SELECT COUNT(*) FROM {sessions} WHERE sid = '%s'", $key));
 | 
				
			||||||
  if (db_affected_rows()) {
 | 
					
 | 
				
			||||||
    // Last access time is updated no more frequently than once every 180 seconds.
 | 
					  if (!$result) {
 | 
				
			||||||
    // This reduces contention in the users table.
 | 
					    // Only save session data when when the browser sends a cookie. This keeps
 | 
				
			||||||
    if ($user->uid && time() - $user->access > variable_get('session_write_interval', 180)) {
 | 
					    // crawlers out of session table. This reduces memory and server load,
 | 
				
			||||||
      db_query("UPDATE {users} SET access = %d WHERE uid = %d", time(), $user->uid);
 | 
					    // and gives more useful statistics. We can't eliminate anonymous session
 | 
				
			||||||
 | 
					    // table rows without breaking "Who's Online" block.
 | 
				
			||||||
 | 
					    if ($user->uid || $value || count($_COOKIE)) {
 | 
				
			||||||
 | 
					      db_query("INSERT INTO {sessions} (sid, uid, cache, hostname, session, timestamp) VALUES ('%s', %d, %d, '%s', '%s', %d)", $key, $user->uid, isset($user->cache) ? $user->cache : 0, ip_address(), $value, time());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else {
 | 
					  else {
 | 
				
			||||||
    // If this query fails, another parallel request probably got here first.
 | 
					    db_query("UPDATE {sessions} SET uid = %d, cache = %d, hostname = '%s', session = '%s', timestamp = %d WHERE sid = '%s'", $user->uid, isset($user->cache) ? $user->cache : 0, ip_address(), $value, time(), $key);
 | 
				
			||||||
    // In that case, any session data generated in this request is discarded.
 | 
					
 | 
				
			||||||
    @db_query("INSERT INTO {sessions} (sid, uid, cache, hostname, session, timestamp) VALUES ('%s', %d, %d, '%s', '%s', %d)", $key, $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time());
 | 
					    if (db_affected_rows()) {
 | 
				
			||||||
 | 
					      // Last access time is updated no more frequently than once every 180 seconds.
 | 
				
			||||||
 | 
					      // This reduces contention in the users table.
 | 
				
			||||||
 | 
					      if ($user->uid && time() - $user->access > variable_get('session_write_interval', 180)) {
 | 
				
			||||||
 | 
					        db_query("UPDATE {users} SET access = %d WHERE uid = %d", time(), $user->uid);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return TRUE;
 | 
					  return TRUE;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ function _drupal_maintenance_theme() {
 | 
				
			||||||
  require_once './includes/unicode.inc';
 | 
					  require_once './includes/unicode.inc';
 | 
				
			||||||
  require_once './includes/file.inc';
 | 
					  require_once './includes/file.inc';
 | 
				
			||||||
  require_once './includes/module.inc';
 | 
					  require_once './includes/module.inc';
 | 
				
			||||||
  require_once './includes/database.inc';
 | 
					  require_once './includes/database/database.inc';
 | 
				
			||||||
  unicode_check();
 | 
					  unicode_check();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Install and update pages are treated differently to prevent theming overrides.
 | 
					  // Install and update pages are treated differently to prevent theming overrides.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require_once './includes/bootstrap.inc';
 | 
					require_once './includes/bootstrap.inc';
 | 
				
			||||||
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 | 
					drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 | 
				
			||||||
 | 
					 | 
				
			||||||
$return = menu_execute_active_handler();
 | 
					$return = menu_execute_active_handler();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Menu status constants are integers; page content is a string.
 | 
					// Menu status constants are integers; page content is a string.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										178
									
								
								install.php
								
								
								
								
							
							
						
						
									
										178
									
								
								install.php
								
								
								
								
							| 
						 | 
					@ -64,9 +64,9 @@ function install_main() {
 | 
				
			||||||
    require_once './includes/cache.inc';
 | 
					    require_once './includes/cache.inc';
 | 
				
			||||||
    $conf['cache_inc'] = './includes/cache.inc';
 | 
					    $conf['cache_inc'] = './includes/cache.inc';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Establish a connection to the database.
 | 
					    // Initialize the database system.  Note that the connection
 | 
				
			||||||
    require_once './includes/database.inc';
 | 
					    // won't be initialized until it is actually requested.
 | 
				
			||||||
    db_set_active();
 | 
					    require_once './includes/database/database.inc';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check if Drupal is installed.
 | 
					    // Check if Drupal is installed.
 | 
				
			||||||
    $task = install_verify_drupal();
 | 
					    $task = install_verify_drupal();
 | 
				
			||||||
| 
						 | 
					@ -154,9 +154,12 @@ function install_main() {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function install_verify_drupal() {
 | 
					function install_verify_drupal() {
 | 
				
			||||||
  // Read the variable manually using the @ so we don't trigger an error if it fails.
 | 
					  // 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');
 | 
					  try {
 | 
				
			||||||
  if ($result) {
 | 
					    if ($result = db_query("SELECT value FROM {variable} WHERE name = '%s'", 'install_task')) {
 | 
				
			||||||
    return unserialize(db_result($result));
 | 
					      return unserialize(db_result($result));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  catch (Exception $e) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -164,23 +167,18 @@ function install_verify_drupal() {
 | 
				
			||||||
 * Verify existing settings.php
 | 
					 * Verify existing settings.php
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function install_verify_settings() {
 | 
					function install_verify_settings() {
 | 
				
			||||||
  global $db_prefix, $db_type, $db_url;
 | 
					  global $db_prefix, $databases;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Verify existing settings (if any).
 | 
					  // Verify existing settings (if any).
 | 
				
			||||||
  if (!empty($db_url)) {
 | 
					  if (!empty($databases)) {
 | 
				
			||||||
    // We need this because we want to run form_get_errors.
 | 
					    // We need this because we want to run form_get_errors.
 | 
				
			||||||
    include_once './includes/form.inc';
 | 
					    include_once './includes/form.inc';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url);
 | 
					    $database = $databases['default']['default'];
 | 
				
			||||||
    $db_user = urldecode($url['user']);
 | 
					 | 
				
			||||||
    $db_pass = isset($url['pass']) ? urldecode($url['pass']) : NULL;
 | 
					 | 
				
			||||||
    $db_host = urldecode($url['host']);
 | 
					 | 
				
			||||||
    $db_port = isset($url['port']) ? urldecode($url['port']) : '';
 | 
					 | 
				
			||||||
    $db_path = ltrim(urldecode($url['path']), '/');
 | 
					 | 
				
			||||||
    $settings_file = './' . conf_path(FALSE, TRUE) . '/settings.php';
 | 
					    $settings_file = './' . conf_path(FALSE, TRUE) . '/settings.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $form_state = array();
 | 
					    $form_state = array();
 | 
				
			||||||
    _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, $form_state);
 | 
					    _install_settings_form_validate($database, $settings_file, $form_state);
 | 
				
			||||||
    if (!form_get_errors()) {
 | 
					    if (!form_get_errors()) {
 | 
				
			||||||
      return TRUE;
 | 
					      return TRUE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -192,22 +190,16 @@ function install_verify_settings() {
 | 
				
			||||||
 * Configure and rewrite settings.php.
 | 
					 * Configure and rewrite settings.php.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function install_change_settings($profile = 'default', $install_locale = '') {
 | 
					function install_change_settings($profile = 'default', $install_locale = '') {
 | 
				
			||||||
  global $db_url, $db_type, $db_prefix;
 | 
					  global $databases, $db_prefix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url);
 | 
					 | 
				
			||||||
  $db_user = isset($url['user']) ? urldecode($url['user']) : '';
 | 
					 | 
				
			||||||
  $db_pass = isset($url['pass']) ? urldecode($url['pass']) : '';
 | 
					 | 
				
			||||||
  $db_host = isset($url['host']) ? urldecode($url['host']) : '';
 | 
					 | 
				
			||||||
  $db_port = isset($url['port']) ? urldecode($url['port']) : '';
 | 
					 | 
				
			||||||
  $db_path = ltrim(urldecode($url['path']), '/');
 | 
					 | 
				
			||||||
  $conf_path = './' . conf_path(FALSE, TRUE);
 | 
					  $conf_path = './' . conf_path(FALSE, TRUE);
 | 
				
			||||||
  $settings_file = $conf_path . '/settings.php';
 | 
					  $settings_file = $conf_path . '/settings.php';
 | 
				
			||||||
 | 
					  $database = $databases['default']['default'];
 | 
				
			||||||
  // We always need this because we want to run form_get_errors.
 | 
					  // We always need this because we want to run form_get_errors.
 | 
				
			||||||
  include_once './includes/form.inc';
 | 
					  include_once './includes/form.inc';
 | 
				
			||||||
  install_task_list('database');
 | 
					  install_task_list('database');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $output = drupal_get_form('install_settings_form', $profile, $install_locale, $settings_file, $db_url, $db_type, $db_prefix, $db_user, $db_pass, $db_host, $db_port, $db_path);
 | 
					  $output = drupal_get_form('install_settings_form', $profile, $install_locale, $settings_file, $database);
 | 
				
			||||||
  drupal_set_title(st('Database configuration'));
 | 
					  drupal_set_title(st('Database configuration'));
 | 
				
			||||||
  print theme('install_page', $output);
 | 
					  print theme('install_page', $output);
 | 
				
			||||||
  exit;
 | 
					  exit;
 | 
				
			||||||
| 
						 | 
					@ -217,19 +209,11 @@ function install_change_settings($profile = 'default', $install_locale = '') {
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Form API array definition for install_settings.
 | 
					 * Form API array definition for install_settings.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function install_settings_form(&$form_state, $profile, $install_locale, $settings_file, $db_url, $db_type, $db_prefix, $db_user, $db_pass, $db_host, $db_port, $db_path) {
 | 
					function install_settings_form(&$form_state, $profile, $install_locale, $settings_file, $database) {
 | 
				
			||||||
  if (empty($db_host)) {
 | 
					  $drivers = drupal_detect_database_types();
 | 
				
			||||||
    $db_host = 'localhost';
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  $db_types = drupal_detect_database_types();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If both 'mysql' and 'mysqli' are available, we disable 'mysql':
 | 
					  if (!$drivers) {
 | 
				
			||||||
  if (isset($db_types['mysqli'])) {
 | 
					    $form['no_drivers'] = array(
 | 
				
			||||||
    unset($db_types['mysql']);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (count($db_types) == 0) {
 | 
					 | 
				
			||||||
    $form['no_db_types'] = array(
 | 
					 | 
				
			||||||
      '#markup' => st('Your web server does not appear to support any common database types. Check with your hosting provider to see if they offer any databases that <a href="@drupal-databases">Drupal supports</a>.', array('@drupal-databases' => 'http://drupal.org/node/270#database')),
 | 
					      '#markup' => st('Your web server does not appear to support any common database types. Check with your hosting provider to see if they offer any databases that <a href="@drupal-databases">Drupal supports</a>.', array('@drupal-databases' => 'http://drupal.org/node/270#database')),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -240,54 +224,51 @@ function install_settings_form(&$form_state, $profile, $install_locale, $setting
 | 
				
			||||||
      '#description' => '<p>' . st('To set up your @drupal database, enter the following information.', array('@drupal' => drupal_install_profile_name())) . '</p>',
 | 
					      '#description' => '<p>' . st('To set up your @drupal database, enter the following information.', array('@drupal' => drupal_install_profile_name())) . '</p>',
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (count($db_types) > 1) {
 | 
					    if (count($drivers) == 1) {
 | 
				
			||||||
      $form['basic_options']['db_type'] = array(
 | 
					      $form['basic_options']['driver'] = array(
 | 
				
			||||||
 | 
					        '#type' => 'hidden',
 | 
				
			||||||
 | 
					        '#value' => current(array_keys($drivers)),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      $database_description = st('The name of the %driver database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('%driver' => current($drivers), '@drupal' => drupal_install_profile_name()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else  {
 | 
				
			||||||
 | 
					      $form['basic_options']['driver'] = array(
 | 
				
			||||||
        '#type' => 'radios',
 | 
					        '#type' => 'radios',
 | 
				
			||||||
        '#title' => st('Database type'),
 | 
					        '#title' => st('Database driver'),
 | 
				
			||||||
        '#required' => TRUE,
 | 
					        '#required' => TRUE,
 | 
				
			||||||
        '#options' => $db_types,
 | 
					        '#options' => $drivers,
 | 
				
			||||||
        '#default_value' => ($db_type ? $db_type : current($db_types)),
 | 
					        '#default_value' => !empty($database['driver']) ? $database['driver'] : current($drivers),
 | 
				
			||||||
        '#description' => st('The type of database your @drupal data will be stored in.', array('@drupal' => drupal_install_profile_name())),
 | 
					        '#description' => st('The type of database your @drupal data will be stored in.', array('@drupal' => drupal_install_profile_name())),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
      $db_path_description = st('The name of the database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('@drupal' => drupal_install_profile_name()));
 | 
					      $database_description  = st('The name of the database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('@drupal' => drupal_install_profile_name()));
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      if (count($db_types) == 1) {
 | 
					 | 
				
			||||||
        $db_types = array_values($db_types);
 | 
					 | 
				
			||||||
        $form['basic_options']['db_type'] = array(
 | 
					 | 
				
			||||||
          '#type' => 'hidden',
 | 
					 | 
				
			||||||
          '#value' => $db_types[0],
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        $db_path_description = st('The name of the %db_type database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('%db_type' => $db_types[0], '@drupal' => drupal_install_profile_name()));
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Database name
 | 
					    // Database name
 | 
				
			||||||
    $form['basic_options']['db_path'] = array(
 | 
					    $form['basic_options']['database'] = array(
 | 
				
			||||||
      '#type' => 'textfield',
 | 
					      '#type' => 'textfield',
 | 
				
			||||||
      '#title' => st('Database name'),
 | 
					      '#title' => st('Database name'),
 | 
				
			||||||
      '#default_value' => $db_path,
 | 
					      '#default_value' => empty($database['database']) ? '' : $database['database'],
 | 
				
			||||||
      '#size' => 45,
 | 
					      '#size' => 45,
 | 
				
			||||||
      '#maxlength' => 45,
 | 
					      '#maxlength' => 45,
 | 
				
			||||||
      '#required' => TRUE,
 | 
					      '#required' => TRUE,
 | 
				
			||||||
      '#description' => $db_path_description
 | 
					      '#description' => $database_description,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Database username
 | 
					    // Database username
 | 
				
			||||||
    $form['basic_options']['db_user'] = array(
 | 
					    $form['basic_options']['username'] = array(
 | 
				
			||||||
      '#type' => 'textfield',
 | 
					      '#type' => 'textfield',
 | 
				
			||||||
      '#title' => st('Database username'),
 | 
					      '#title' => st('Database username'),
 | 
				
			||||||
      '#default_value' => $db_user,
 | 
					      '#default_value' => empty($database['username']) ? '' : $database['username'],
 | 
				
			||||||
      '#size' => 45,
 | 
					      '#size' => 45,
 | 
				
			||||||
      '#maxlength' => 45,
 | 
					      '#maxlength' => 45,
 | 
				
			||||||
      '#required' => TRUE,
 | 
					      '#required' => TRUE,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Database username
 | 
					    // Database username
 | 
				
			||||||
    $form['basic_options']['db_pass'] = array(
 | 
					    $form['basic_options']['password'] = array(
 | 
				
			||||||
      '#type' => 'password',
 | 
					      '#type' => 'password',
 | 
				
			||||||
      '#title' => st('Database password'),
 | 
					      '#title' => st('Database password'),
 | 
				
			||||||
      '#default_value' => $db_pass,
 | 
					      '#default_value' => empty($database['password']) ? '' : $database['password'],
 | 
				
			||||||
      '#size' => 45,
 | 
					      '#size' => 45,
 | 
				
			||||||
      '#maxlength' => 45,
 | 
					      '#maxlength' => 45,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
| 
						 | 
					@ -301,10 +282,10 @@ function install_settings_form(&$form_state, $profile, $install_locale, $setting
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Database host
 | 
					    // Database host
 | 
				
			||||||
    $form['advanced_options']['db_host'] = array(
 | 
					    $form['advanced_options']['host'] = array(
 | 
				
			||||||
      '#type' => 'textfield',
 | 
					      '#type' => 'textfield',
 | 
				
			||||||
      '#title' => st('Database host'),
 | 
					      '#title' => st('Database host'),
 | 
				
			||||||
      '#default_value' => $db_host,
 | 
					      '#default_value' => empty($database['host']) ? 'localhost' : $database['host'],
 | 
				
			||||||
      '#size' => 45,
 | 
					      '#size' => 45,
 | 
				
			||||||
      '#maxlength' => 45,
 | 
					      '#maxlength' => 45,
 | 
				
			||||||
      '#required' => TRUE,
 | 
					      '#required' => TRUE,
 | 
				
			||||||
| 
						 | 
					@ -312,24 +293,24 @@ function install_settings_form(&$form_state, $profile, $install_locale, $setting
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Database port
 | 
					    // Database port
 | 
				
			||||||
    $form['advanced_options']['db_port'] = array(
 | 
					    $form['advanced_options']['port'] = array(
 | 
				
			||||||
      '#type' => 'textfield',
 | 
					      '#type' => 'textfield',
 | 
				
			||||||
      '#title' => st('Database port'),
 | 
					      '#title' => st('Database port'),
 | 
				
			||||||
      '#default_value' => $db_port,
 | 
					      '#default_value' => empty($database['port']) ? '' : $database['port'],
 | 
				
			||||||
      '#size' => 45,
 | 
					      '#size' => 45,
 | 
				
			||||||
      '#maxlength' => 45,
 | 
					      '#maxlength' => 45,
 | 
				
			||||||
      '#description' => st('If your database server is listening to a non-standard port, enter its number.'),
 | 
					      '#description' => st('If your database server is listening to a non-standard port, enter its number.'),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Table prefix
 | 
					    // Table prefix
 | 
				
			||||||
    $prefix = ($profile == 'default') ? 'drupal_' : $profile . '_';
 | 
					    $db_prefix = ($profile == 'default') ? 'drupal_' : $profile . '_';
 | 
				
			||||||
    $form['advanced_options']['db_prefix'] = array(
 | 
					    $form['advanced_options']['db_prefix'] = array(
 | 
				
			||||||
      '#type' => 'textfield',
 | 
					      '#type' => 'textfield',
 | 
				
			||||||
      '#title' => st('Table prefix'),
 | 
					      '#title' => st('Table prefix'),
 | 
				
			||||||
      '#default_value' => $db_prefix,
 | 
					      '#default_value' => '',
 | 
				
			||||||
      '#size' => 45,
 | 
					      '#size' => 45,
 | 
				
			||||||
      '#maxlength' => 45,
 | 
					      '#maxlength' => 45,
 | 
				
			||||||
      '#description' => st('If more than one application will be sharing this database, enter a table prefix such as %prefix for your @drupal site here.', array('@drupal' => drupal_install_profile_name(), '%prefix' => $prefix)),
 | 
					      '#description' => st('If more than one application will be sharing this database, enter a table prefix such as %prefix for your @drupal site here.', array('@drupal' => drupal_install_profile_name(), '%prefix' => $db_prefix)),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $form['save'] = array(
 | 
					    $form['save'] = array(
 | 
				
			||||||
| 
						 | 
					@ -339,7 +320,7 @@ function install_settings_form(&$form_state, $profile, $install_locale, $setting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $form['errors'] = array();
 | 
					    $form['errors'] = array();
 | 
				
			||||||
    $form['settings_file'] = array('#type' => 'value', '#value' => $settings_file);
 | 
					    $form['settings_file'] = array('#type' => 'value', '#value' => $settings_file);
 | 
				
			||||||
    $form['_db_url'] = array('#type' => 'value');
 | 
					    $form['_database'] = array('#type' => 'value');
 | 
				
			||||||
    $form['#action'] = "install.php?profile=$profile" . ($install_locale ? "&locale=$install_locale" : '');
 | 
					    $form['#action'] = "install.php?profile=$profile" . ($install_locale ? "&locale=$install_locale" : '');
 | 
				
			||||||
    $form['#redirect'] = FALSE;
 | 
					    $form['#redirect'] = FALSE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -351,48 +332,43 @@ function install_settings_form(&$form_state, $profile, $install_locale, $setting
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function install_settings_form_validate($form, &$form_state) {
 | 
					function install_settings_form_validate($form, &$form_state) {
 | 
				
			||||||
  global $db_url;
 | 
					  global $db_url;
 | 
				
			||||||
  _install_settings_form_validate($form_state['values']['db_prefix'], $form_state['values']['db_type'], $form_state['values']['db_user'], $form_state['values']['db_pass'], $form_state['values']['db_host'], $form_state['values']['db_port'], $form_state['values']['db_path'], $form_state['values']['settings_file'], $form_state, $form);
 | 
					  _install_settings_form_validate($form_state['values'], $form_state['values']['settings_file'], $form_state, $form);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Helper function for install_settings_validate.
 | 
					 * Helper function for install_settings_validate.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, &$form_state, $form = NULL) {
 | 
					function _install_settings_form_validate($database, $settings_file, &$form_state, $form = NULL) {
 | 
				
			||||||
  global $db_url;
 | 
					  global $databases;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Verify the table prefix
 | 
					  // Verify the table prefix
 | 
				
			||||||
  if (!empty($db_prefix) && is_string($db_prefix) && !preg_match('/^[A-Za-z0-9_.]+$/', $db_prefix)) {
 | 
					  if (!empty($database['prefix']) && is_string($database['prefix']) && !preg_match('/^[A-Za-z0-9_.]+$/', $database['dprefix'])) {
 | 
				
			||||||
    form_set_error('db_prefix', st('The database table prefix you have entered, %db_prefix, is invalid. The table prefix can only contain alphanumeric characters, periods, or underscores.', array('%db_prefix' => $db_prefix)), 'error');
 | 
					    form_set_error('db_prefix', st('The database table prefix you have entered, %db_prefix, is invalid. The table prefix can only contain alphanumeric characters, periods, or underscores.', array('%db_prefix' => $db_prefix)), 'error');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!empty($db_port) && !is_numeric($db_port)) {
 | 
					  if (!empty($database['port']) && !is_numeric($database['port'])) {
 | 
				
			||||||
    form_set_error('db_port', st('Database port must be a number.'));
 | 
					    form_set_error('db_port', st('Database port must be a number.'));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Check database type
 | 
					  // Check database type
 | 
				
			||||||
  if (!isset($form)) {
 | 
					  $database_types = drupal_detect_database_types();
 | 
				
			||||||
    $_db_url = is_array($db_url) ? $db_url['default'] : $db_url;
 | 
					  $driver = $database['driver'];
 | 
				
			||||||
    $db_type = substr($_db_url, 0, strpos($_db_url, '://'));
 | 
					  if (!isset($database_types[$driver])) {
 | 
				
			||||||
  }
 | 
					    form_set_error('driver', st("In your %settings_file file you have configured @drupal to use a %driver server, however your PHP installation currently does not support this database type.", array('%settings_file' => $settings_file, '@drupal' => drupal_install_profile_name(), '%driver' => $database['driver'])));
 | 
				
			||||||
  $databases = drupal_detect_database_types();
 | 
					 | 
				
			||||||
  if (!in_array($db_type, $databases)) {
 | 
					 | 
				
			||||||
    form_set_error('db_type', st("In your %settings_file file you have configured @drupal to use a %db_type server, however your PHP installation currently does not support this database type.", array('%settings_file' => $settings_file, '@drupal' => drupal_install_profile_name(), '%db_type' => $db_type)));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else {
 | 
					  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);
 | 
					 | 
				
			||||||
    if (isset($form)) {
 | 
					    if (isset($form)) {
 | 
				
			||||||
      form_set_value($form['_db_url'], $db_url, $form_state);
 | 
					      form_set_value($form['_database'], $database, $form_state);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    $success = array();
 | 
					    $class = "DatabaseInstaller_$driver";
 | 
				
			||||||
 | 
					    $test = new $class;
 | 
				
			||||||
    $function = 'drupal_test_' . $db_type;
 | 
					    $databases = array('default' => array('default' => $database));
 | 
				
			||||||
    if (!$function($db_url, $success)) {
 | 
					    $return = $test->test();
 | 
				
			||||||
      if (isset($success['CONNECT'])) {
 | 
					    if (!$return || $test->error) {
 | 
				
			||||||
        form_set_error('db_type', st('In order for Drupal to work, and to continue with the installation process, you must resolve all permission issues reported above. We were able to verify that we have permission for the following commands: %commands. For more help with configuring your database server, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.', array('%commands' => implode($success, ', '))));
 | 
					      if (!empty($test->success)) {
 | 
				
			||||||
 | 
					        form_set_error('db_type', st('In order for Drupal to work, and to continue with the installation process, you must resolve all permission issues reported above. We were able to verify that we have permission for the following commands: %commands. For more help with configuring your database server, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.', array('%commands' => implode($test->success, ', '))));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      else {
 | 
					      else {
 | 
				
			||||||
        form_set_error('db_type', '');
 | 
					        form_set_error('driver', '');
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -404,9 +380,10 @@ function _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pas
 | 
				
			||||||
function install_settings_form_submit($form, &$form_state) {
 | 
					function install_settings_form_submit($form, &$form_state) {
 | 
				
			||||||
  global $profile, $install_locale;
 | 
					  global $profile, $install_locale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $database = array_intersect_key($form_state['values']['_database'], array_flip(array('driver', 'database', 'username', 'password', 'host', 'port')));
 | 
				
			||||||
  // Update global settings array and save
 | 
					  // Update global settings array and save
 | 
				
			||||||
  $settings['db_url'] = array(
 | 
					  $settings['databases'] = array(
 | 
				
			||||||
    'value'    => $form_state['values']['_db_url'],
 | 
					    'value'    => array('default' => array('default' => $database)),
 | 
				
			||||||
    'required' => TRUE,
 | 
					    'required' => TRUE,
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
  $settings['db_prefix'] = array(
 | 
					  $settings['db_prefix'] = array(
 | 
				
			||||||
| 
						 | 
					@ -639,6 +616,8 @@ function install_tasks($profile, $task) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Bootstrap newly installed Drupal, while preserving existing messages.
 | 
					  // Bootstrap newly installed Drupal, while preserving existing messages.
 | 
				
			||||||
  $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : '';
 | 
					  $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : '';
 | 
				
			||||||
 | 
					  drupal_install_init_database();
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 | 
					  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 | 
				
			||||||
  $_SESSION['messages'] = $messages;
 | 
					  $_SESSION['messages'] = $messages;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -751,6 +730,17 @@ if (Drupal.jsEnabled) {
 | 
				
			||||||
}', 'inline');
 | 
					}', 'inline');
 | 
				
			||||||
      // Build menu to allow clean URL check.
 | 
					      // Build menu to allow clean URL check.
 | 
				
			||||||
      menu_rebuild();
 | 
					      menu_rebuild();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Cache a fully-built schema.  This is necessary for any
 | 
				
			||||||
 | 
					      // invocation of index.php because: (1) setting cache table
 | 
				
			||||||
 | 
					      // entries requires schema information, (2) that occurs during
 | 
				
			||||||
 | 
					      // bootstrap before any module are loaded, so (3) if there is no
 | 
				
			||||||
 | 
					      // cached schema, drupal_get_schema() will try to generate one
 | 
				
			||||||
 | 
					      // but with no loaded modules will return nothing.
 | 
				
			||||||
 | 
					      //
 | 
				
			||||||
 | 
					      // This logically could be done during task 'done' but the clean
 | 
				
			||||||
 | 
					      // URL check requires it now.
 | 
				
			||||||
 | 
					      drupal_get_schema(NULL, TRUE);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
| 
						 | 
					@ -826,6 +816,9 @@ if (Drupal.jsEnabled) {
 | 
				
			||||||
    _drupal_flush_css_js();
 | 
					    _drupal_flush_css_js();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    variable_set('install_profile', $profile);
 | 
					    variable_set('install_profile', $profile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Cache a fully-built schema.
 | 
				
			||||||
 | 
					    drupal_get_schema(NULL, TRUE);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Set task for user, and remember the task in the database.
 | 
					  // Set task for user, and remember the task in the database.
 | 
				
			||||||
| 
						 | 
					@ -1185,3 +1178,4 @@ function install_configure_form_submit($form, &$form_state) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Start the installer.
 | 
					// Start the installer.
 | 
				
			||||||
install_main();
 | 
					install_main();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -290,7 +290,7 @@ function _block_rehash() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function block_box_get($bid) {
 | 
					function block_box_get($bid) {
 | 
				
			||||||
  return db_fetch_array(db_query("SELECT bx.*, bl.title FROM {boxes} bx INNER JOIN {blocks} bl ON bx.bid = bl.delta WHERE bl.module = 'block' AND bx.bid = %d", $bid));
 | 
					  return db_fetch_array(db_query("SELECT * FROM {boxes} WHERE bid = %d", $bid));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -693,7 +693,7 @@ function comment_save($edit) {
 | 
				
			||||||
          // Strip the "/" from the end of the parent thread.
 | 
					          // Strip the "/" from the end of the parent thread.
 | 
				
			||||||
          $parent->thread = (string) rtrim((string) $parent->thread, '/');
 | 
					          $parent->thread = (string) rtrim((string) $parent->thread, '/');
 | 
				
			||||||
          // Get the max value in *this* thread.
 | 
					          // Get the max value in *this* thread.
 | 
				
			||||||
          $max = db_result(db_query("SELECT MAX(thread) FROM {comments} WHERE thread LIKE '%s.%%' AND nid = %d", $parent->thread, $edit['nid']));
 | 
					          $max = db_query("SELECT MAX(thread) FROM {comments} WHERE thread LIKE :thread AND nid = :nid", array(':thread' => $parent->thread .'%', ':nid' => $edit['nid']))->fetchField();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          if ($max == '') {
 | 
					          if ($max == '') {
 | 
				
			||||||
            // First child of this parent.
 | 
					            // First child of this parent.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,7 @@ function dblog_schema() {
 | 
				
			||||||
      'link' => array(
 | 
					      'link' => array(
 | 
				
			||||||
        'type' => 'varchar',
 | 
					        'type' => 'varchar',
 | 
				
			||||||
        'length' => 255,
 | 
					        'length' => 255,
 | 
				
			||||||
        'not null' => TRUE,
 | 
					        'not null' => FALSE,
 | 
				
			||||||
        'default' => '',
 | 
					        'default' => '',
 | 
				
			||||||
        'description' => t('Link to view the result of the event.'),
 | 
					        'description' => t('Link to view the result of the event.'),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,7 @@ function dblog_schema() {
 | 
				
			||||||
      'referer' => array(
 | 
					      'referer' => array(
 | 
				
			||||||
        'type' => 'varchar',
 | 
					        'type' => 'varchar',
 | 
				
			||||||
        'length' => 128,
 | 
					        'length' => 128,
 | 
				
			||||||
        'not null' => TRUE,
 | 
					        'not null' => FALSE,
 | 
				
			||||||
        'default' => '',
 | 
					        'default' => '',
 | 
				
			||||||
        'description' => t('URL of referring page.'),
 | 
					        'description' => t('URL of referring page.'),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
| 
						 | 
					@ -103,3 +103,13 @@ function dblog_schema() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return $schema;
 | 
					  return $schema;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Allow NULL values for links.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function dblog_update_7001() {
 | 
				
			||||||
 | 
					  $ret = array();
 | 
				
			||||||
 | 
					  db_change_field($ret, 'watchdog', 'link', 'link', array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''));
 | 
				
			||||||
 | 
					  db_change_field($ret, 'watchdog', 'referer', 'referer', array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''));
 | 
				
			||||||
 | 
					  return $ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,7 +135,8 @@ function dblog_watchdog($log = array()) {
 | 
				
			||||||
    $log['request_uri'],
 | 
					    $log['request_uri'],
 | 
				
			||||||
    $log['referer'],
 | 
					    $log['referer'],
 | 
				
			||||||
    $log['ip'],
 | 
					    $log['ip'],
 | 
				
			||||||
    $log['timestamp']);
 | 
					    $log['timestamp']
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ($current_db) {
 | 
					  if ($current_db) {
 | 
				
			||||||
    db_set_active($current_db);
 | 
					    db_set_active($current_db);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -210,11 +210,18 @@ class DBLogTestCase extends DrupalWebTestCase {
 | 
				
			||||||
    // Count rows that have uids for the user.
 | 
					    // Count rows that have uids for the user.
 | 
				
			||||||
    $count = db_result(db_query('SELECT COUNT(wid) FROM {watchdog} WHERE uid = %d', $user->uid));
 | 
					    $count = db_result(db_query('SELECT COUNT(wid) FROM {watchdog} WHERE uid = %d', $user->uid));
 | 
				
			||||||
    $this->assertTrue($count == 0, t('DBLog contains @count records for @name', array('@count' => $count, '@name' => $user->name)));
 | 
					    $this->assertTrue($count == 0, t('DBLog contains @count records for @name', array('@count' => $count, '@name' => $user->name)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Fetch row ids in watchdog that previously related to the deleted user.
 | 
					    // Fetch row ids in watchdog that previously related to the deleted user.
 | 
				
			||||||
    $result = db_query('SELECT wid FROM {watchdog} WHERE uid = 0 AND wid IN (%s)', implode(', ', $ids));
 | 
					    $select = db_select('watchdog');
 | 
				
			||||||
 | 
					    $select->addField('watchdog', 'wid');
 | 
				
			||||||
 | 
					    $select->condition('uid', 0);
 | 
				
			||||||
 | 
					    if ($ids) {
 | 
				
			||||||
 | 
					      $select->condition('wid', $ids, 'IN');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $result = $select->execute();
 | 
				
			||||||
    unset($ids);
 | 
					    unset($ids);
 | 
				
			||||||
    while ($row = db_fetch_array($result)) {
 | 
					    foreach ($result as $row) {
 | 
				
			||||||
      $ids[] = $row['wid'];
 | 
					      $ids[] = $row->wid;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    $count_after = (isset($ids)) ? count($ids) : 0;
 | 
					    $count_after = (isset($ids)) ? count($ids) : 0;
 | 
				
			||||||
    $this->assertTrue($count_after == $count_before, t('DBLog contains @count records for @name that now have uid = 0', array('@count' => $count_before, '@name' => $user->name)));
 | 
					    $this->assertTrue($count_after == $count_before, t('DBLog contains @count records for @name that now have uid = 0', array('@count' => $count_before, '@name' => $user->name)));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -292,24 +292,24 @@ function filter_formats($index = NULL) {
 | 
				
			||||||
  if (!isset($formats)) {
 | 
					  if (!isset($formats)) {
 | 
				
			||||||
    $formats = array();
 | 
					    $formats = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $query = 'SELECT * FROM {filter_formats}';
 | 
					    $query = db_select('filter_formats', 'f');
 | 
				
			||||||
 | 
					    $query->addField('f', 'format', 'format');
 | 
				
			||||||
 | 
					    $query->addField('f', 'name', 'name');
 | 
				
			||||||
 | 
					    $query->addField('f', 'roles', 'roles');
 | 
				
			||||||
 | 
					    $query->addField('f', 'cache', 'cache');
 | 
				
			||||||
 | 
					    $query->addField('f', 'weight', 'weight');
 | 
				
			||||||
 | 
					    $query->orderBy('weight');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Build query for selecting the format(s) based on the user's roles.
 | 
					    // Build query for selecting the format(s) based on the user's roles.
 | 
				
			||||||
    $args = array();
 | 
					 | 
				
			||||||
    if (!$all) {
 | 
					    if (!$all) {
 | 
				
			||||||
      $where = array();
 | 
					      $or = db_or()->condition('format', variable_get('filter_default_format', 1));
 | 
				
			||||||
      foreach ($user->roles as $rid => $role) {
 | 
					      foreach ($user->roles as $rid => $role) {
 | 
				
			||||||
        $where[] = "roles LIKE '%%,%d,%%'";
 | 
					        $or->condition('roles', '%'. (int)$rid .'%', 'LIKE');
 | 
				
			||||||
        $args[] = $rid;
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      $query .= ' WHERE ' . implode(' OR ', $where) . ' OR format = %d';
 | 
					      $query->condition($or);
 | 
				
			||||||
      $args[] = variable_get('filter_default_format', 1);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $result = db_query($query . ' ORDER by weight', $args);
 | 
					    $formats = $query->execute()->fetchAllAssoc('format');
 | 
				
			||||||
    while ($format = db_fetch_object($result)) {
 | 
					 | 
				
			||||||
      $formats[$format->format] = $format;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (isset($index)) {
 | 
					  if (isset($index)) {
 | 
				
			||||||
    return isset($formats[$index]) ? $formats[$index] : FALSE;
 | 
					    return isset($formats[$index]) ? $formats[$index] : FALSE;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -302,7 +302,7 @@ function menu_nodeapi(&$node, $op) {
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    case 'delete':
 | 
					    case 'delete':
 | 
				
			||||||
      // Delete all menu module links that point to this node.
 | 
					      // Delete all menu module links that point to this node.
 | 
				
			||||||
      $result = db_query("SELECT mlid FROM {menu_links} WHERE link_path = 'node/%d' AND module = 'menu'", $node->nid);
 | 
					      $result = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = 'menu'", array(':path' => 'node/'. $node->nid));
 | 
				
			||||||
      while ($m = db_fetch_array($result)) {
 | 
					      while ($m = db_fetch_array($result)) {
 | 
				
			||||||
        menu_link_delete($m['mlid']);
 | 
					        menu_link_delete($m['mlid']);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -314,10 +314,15 @@ function menu_nodeapi(&$node, $op) {
 | 
				
			||||||
        $item = array();
 | 
					        $item = array();
 | 
				
			||||||
        if (isset($node->nid)) {
 | 
					        if (isset($node->nid)) {
 | 
				
			||||||
          // Give priority to the default menu
 | 
					          // Give priority to the default menu
 | 
				
			||||||
          $mlid = db_result(db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = 'node/%d' AND menu_name = '%s' AND module = 'menu' ORDER BY mlid ASC", $node->nid, $menu_name, 0, 1));
 | 
					          $mlid = db_result(db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND menu_name = :menu_name AND module = 'menu' ORDER BY mlid ASC", array(
 | 
				
			||||||
 | 
					            ':path' => 'node/'. $node->nid, 
 | 
				
			||||||
 | 
					            ':menu_name' => $menu_name,
 | 
				
			||||||
 | 
					          ), 0, 1));
 | 
				
			||||||
          // Check all menus if a link does not exist in the default menu.
 | 
					          // Check all menus if a link does not exist in the default menu.
 | 
				
			||||||
          if (!$mlid) {
 | 
					          if (!$mlid) {
 | 
				
			||||||
            $mlid = db_result(db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = 'node/%d' AND module = 'menu' ORDER BY mlid ASC", $node->nid, 0, 1));
 | 
					            $mlid = db_result(db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = 'menu' ORDER BY mlid ASC", array(
 | 
				
			||||||
 | 
					              ':path' => 'node/'. $node->nid, 
 | 
				
			||||||
 | 
					            ), 0, 1));
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          if ($mlid) {
 | 
					          if ($mlid) {
 | 
				
			||||||
            $item = menu_link_load($mlid);
 | 
					            $item = menu_link_load($mlid);
 | 
				
			||||||
| 
						 | 
					@ -428,15 +433,13 @@ function menu_node_form_submit($form, &$form_state) {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function menu_get_menus($all = TRUE) {
 | 
					function menu_get_menus($all = TRUE) {
 | 
				
			||||||
  $system_menus = menu_list_system_menus();
 | 
					  $system_menus = menu_list_system_menus();
 | 
				
			||||||
  $sql = 'SELECT * FROM {menu_custom}';
 | 
					  $query = db_select('menu_custom');
 | 
				
			||||||
 | 
					  $query->addField('menu_custom', 'menu_name', 'menu_name');
 | 
				
			||||||
 | 
					  $query->addField('menu_custom', 'title', 'title');
 | 
				
			||||||
  if (!$all) {
 | 
					  if (!$all) {
 | 
				
			||||||
    $sql .= ' WHERE menu_name NOT IN (' . implode(',', array_fill(0, count($system_menus), "'%s'")) . ')';
 | 
					    $query->condition('menu_name', $system_menus, 'NOT IN');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  $sql .= ' ORDER BY title';
 | 
					  $query->orderBy('title');
 | 
				
			||||||
  $result = db_query($sql, $system_menus);
 | 
					
 | 
				
			||||||
  $rows = array();
 | 
					  return $query->execute()->fetchAllKeyed();
 | 
				
			||||||
  while ($r = db_fetch_array($result)) {
 | 
					 | 
				
			||||||
    $rows[$r['menu_name']] = $r['title'];
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return $rows;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -511,12 +511,18 @@ function node_type_save($info) {
 | 
				
			||||||
  if (!isset($info->help)) {
 | 
					  if (!isset($info->help)) {
 | 
				
			||||||
    $info->help = '';
 | 
					    $info->help = '';
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (!isset($info->min_word_count)) {
 | 
					  if (empty($info->min_word_count)) {
 | 
				
			||||||
    $info->min_word_count = 0;
 | 
					    $info->min_word_count = 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (!isset($info->body_label)) {
 | 
					  if (!isset($info->body_label)) {
 | 
				
			||||||
    $info->body_label = '';
 | 
					    $info->body_label = '';
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  if (empty($info->custom)) {
 | 
				
			||||||
 | 
					    $info->custom = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (empty($info->locked)) {
 | 
				
			||||||
 | 
					    $info->locked = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ($is_existing) {
 | 
					  if ($is_existing) {
 | 
				
			||||||
    db_query("UPDATE {node_type} SET type = '%s', name = '%s', module = '%s', has_title = %d, title_label = '%s', has_body = %d, body_label = '%s', description = '%s', help = '%s', min_word_count = %d, custom = %d, modified = %d, locked = %d WHERE type = '%s'", $info->type, $info->name, $info->module, $info->has_title, $info->title_label, $info->has_body, $info->body_label, $info->description, $info->help, $info->min_word_count, $info->custom, $info->modified, $info->locked, $existing_type);
 | 
					    db_query("UPDATE {node_type} SET type = '%s', name = '%s', module = '%s', has_title = %d, title_label = '%s', has_body = %d, body_label = '%s', description = '%s', help = '%s', min_word_count = %d, custom = %d, modified = %d, locked = %d WHERE type = '%s'", $info->type, $info->name, $info->module, $info->has_title, $info->title_label, $info->has_body, $info->body_label, $info->description, $info->help, $info->min_word_count, $info->custom, $info->modified, $info->locked, $existing_type);
 | 
				
			||||||
| 
						 | 
					@ -2236,6 +2242,37 @@ function node_db_rewrite_sql($query, $primary_table, $primary_field) {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Implementation of hook_query_alter().
 | 
				
			||||||
 | 
					 * @todo This doesn't quite work yet.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function DISABLED_node_query_alter(Query $query) {
 | 
				
			||||||
 | 
					  if ($query->hasTag('node_access')) {
 | 
				
			||||||
 | 
					    if (! user_access('administer nodes')) {
 | 
				
			||||||
 | 
					      $query->distinct();
 | 
				
			||||||
 | 
					      $access_alias = $query->join('node_access', 'na', 'na.nid = n.nid');
 | 
				
			||||||
 | 
					      dsm('hello');
 | 
				
			||||||
 | 
					      _node_query_alter_where($query, 'view', $access_alias);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function _node_query_alter_where($query, $op = 'view', $node_access_alias = 'na', $account = NULL) {
 | 
				
			||||||
 | 
					  $or = db_or();
 | 
				
			||||||
 | 
					  foreach (node_access_grants($op, $account) as $realm => $gids) {
 | 
				
			||||||
 | 
					    foreach ($gids as $gid) {
 | 
				
			||||||
 | 
					      $or->condition("{$node_access_alias}.gid = :gid AND {$node_access_alias}.realm = :realm", array(':gid' => $gid, ':realm' => $realm));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (count($or->conditions())) {
 | 
				
			||||||
 | 
					    $query->condition($or);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $query->condition("$node_access_alias.grant_$op", '>=', 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This function will call module invoke to get a list of grants and then
 | 
					 * This function will call module invoke to get a list of grants and then
 | 
				
			||||||
 * write them to the database. It is called at node save, and should be
 | 
					 * write them to the database. It is called at node save, and should be
 | 
				
			||||||
| 
						 | 
					@ -2290,11 +2327,11 @@ function node_access_acquire_grants($node) {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function node_access_write_grants($node, $grants, $realm = NULL, $delete = TRUE) {
 | 
					function node_access_write_grants($node, $grants, $realm = NULL, $delete = TRUE) {
 | 
				
			||||||
  if ($delete) {
 | 
					  if ($delete) {
 | 
				
			||||||
    $query = 'DELETE FROM {node_access} WHERE nid = %d';
 | 
					    $query = db_delete('node_access')->condition('nid', $node->nid);
 | 
				
			||||||
    if ($realm) {
 | 
					    if ($realm) {
 | 
				
			||||||
      $query .= " AND realm in ('%s', 'all')";
 | 
					      $query->condition('realm', array($realm, 'all'), 'IN');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    db_query($query, $node->nid, $realm);
 | 
					    $query->execute();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Only perform work when node_access modules are active.
 | 
					  // Only perform work when node_access modules are active.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,12 +19,14 @@ function path_admin_overview($keys = NULL) {
 | 
				
			||||||
  $multilanguage = (module_exists('locale') || $count);
 | 
					  $multilanguage = (module_exists('locale') || $count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ($keys) {
 | 
					  if ($keys) {
 | 
				
			||||||
    // Replace wildcards with MySQL/PostgreSQL wildcards.
 | 
					    // Replace wildcards with PDO wildcards.
 | 
				
			||||||
    $keys = preg_replace('!\*+!', '%', $keys);
 | 
					    $keys = preg_replace('!\*+!', '%', $keys);
 | 
				
			||||||
    $sql = "SELECT * FROM {url_alias} WHERE dst LIKE '%%%s%%'";
 | 
					    $sql = "SELECT * FROM {url_alias} WHERE dst LIKE :keys";
 | 
				
			||||||
 | 
					    $args = array(':keys' => '%'. $keys .'%');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else {
 | 
					  else {
 | 
				
			||||||
    $sql = 'SELECT * FROM {url_alias}';
 | 
					    $sql = 'SELECT * FROM {url_alias}';
 | 
				
			||||||
 | 
					    $args = array();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  $header = array(
 | 
					  $header = array(
 | 
				
			||||||
    array('data' => t('Alias'), 'field' => 'dst', 'sort' => 'asc'),
 | 
					    array('data' => t('Alias'), 'field' => 'dst', 'sort' => 'asc'),
 | 
				
			||||||
| 
						 | 
					@ -36,7 +38,7 @@ function path_admin_overview($keys = NULL) {
 | 
				
			||||||
    $header[2] = array('data' => t('Language'), 'field' => 'language');
 | 
					    $header[2] = array('data' => t('Language'), 'field' => 'language');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  $sql .= tablesort_sql($header);
 | 
					  $sql .= tablesort_sql($header);
 | 
				
			||||||
  $result = pager_query($sql, 50, 0 , NULL, $keys);
 | 
					  $result = pager_query($sql, 50, 0 , NULL, $args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $rows = array();
 | 
					  $rows = array();
 | 
				
			||||||
  $destination = drupal_get_destination();
 | 
					  $destination = drupal_get_destination();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,6 +132,7 @@ class PathTestCase extends DrupalWebTestCase {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check to make sure the node was created.
 | 
					    // Check to make sure the node was created.
 | 
				
			||||||
    $node = node_load(array('title' => $edit['title']));
 | 
					    $node = node_load(array('title' => $edit['title']));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $this->assertNotNull(($node === FALSE ? NULL : $node), 'Node found in database. %s');
 | 
					    $this->assertNotNull(($node === FALSE ? NULL : $node), 'Node found in database. %s');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return $node;
 | 
					    return $node;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -396,7 +396,7 @@ function profile_field_delete_submit($form, &$form_state) {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function profile_admin_settings_autocomplete($string) {
 | 
					function profile_admin_settings_autocomplete($string) {
 | 
				
			||||||
  $matches = array();
 | 
					  $matches = array();
 | 
				
			||||||
  $result = db_query_range("SELECT category FROM {profile_fields} WHERE LOWER(category) LIKE LOWER('%s%%')", $string, 0, 10);
 | 
					  $result = db_query_range("SELECT category FROM {profile_fields} WHERE LOWER(category) LIKE LOWER(:category)", array(':category' => $string .'%'), 0, 10);
 | 
				
			||||||
  while ($data = db_fetch_object($result)) {
 | 
					  while ($data = db_fetch_object($result)) {
 | 
				
			||||||
    $matches[$data->category] = check_plain($data->category);
 | 
					    $matches[$data->category] = check_plain($data->category);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,7 +110,10 @@ function profile_browse() {
 | 
				
			||||||
function profile_autocomplete($field, $string) {
 | 
					function profile_autocomplete($field, $string) {
 | 
				
			||||||
  $matches = array();
 | 
					  $matches = array();
 | 
				
			||||||
  if (db_result(db_query("SELECT COUNT(*) FROM {profile_fields} WHERE fid = %d AND autocomplete = 1", $field))) {
 | 
					  if (db_result(db_query("SELECT COUNT(*) FROM {profile_fields} WHERE fid = %d AND autocomplete = 1", $field))) {
 | 
				
			||||||
    $result = db_query_range("SELECT value FROM {profile_values} WHERE fid = %d AND LOWER(value) LIKE LOWER('%s%%') GROUP BY value ORDER BY value ASC", $field, $string, 0, 10);
 | 
					    $result = db_query_range("SELECT value FROM {profile_values} WHERE fid = :fid AND LOWER(value) LIKE LOWER(:value) GROUP BY value ORDER BY value ASC", array(
 | 
				
			||||||
 | 
					      ':fid' => $field, 
 | 
				
			||||||
 | 
					      ':value' => $string .'%',
 | 
				
			||||||
 | 
					    ), 0, 10);
 | 
				
			||||||
    while ($data = db_fetch_object($result)) {
 | 
					    while ($data = db_fetch_object($result)) {
 | 
				
			||||||
      $matches[$data->value] = check_plain($data->value);
 | 
					      $matches[$data->value] = check_plain($data->value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -284,10 +284,7 @@ function search_update_totals() {
 | 
				
			||||||
    $total = db_result(db_query("SELECT SUM(score) FROM {search_index} WHERE word = '%s'", $word));
 | 
					    $total = db_result(db_query("SELECT SUM(score) FROM {search_index} WHERE word = '%s'", $word));
 | 
				
			||||||
    // Apply Zipf's law to equalize the probability distribution
 | 
					    // Apply Zipf's law to equalize the probability distribution
 | 
				
			||||||
    $total = log10(1 + 1/(max(1, $total)));
 | 
					    $total = log10(1 + 1/(max(1, $total)));
 | 
				
			||||||
    db_query("UPDATE {search_total} SET count = %f WHERE word = '%s'", $total, $word);
 | 
					    db_merge('search_total')->key(array('word' => $word))->fields(array('count' => $total))->execute();
 | 
				
			||||||
    if (!db_affected_rows()) {
 | 
					 | 
				
			||||||
      db_query("INSERT INTO {search_total} (word, count) VALUES ('%s', %f)", $word, $total);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  // Find words that were deleted from search_index, but are still in
 | 
					  // Find words that were deleted from search_index, but are still in
 | 
				
			||||||
  // search_total. We use a LEFT JOIN between the two tables and keep only the
 | 
					  // search_total. We use a LEFT JOIN between the two tables and keep only the
 | 
				
			||||||
| 
						 | 
					@ -573,13 +570,15 @@ function search_index($sid, $type, $text) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Insert results into search index
 | 
					  // Insert results into search index
 | 
				
			||||||
  foreach ($results[0] as $word => $score) {
 | 
					  foreach ($results[0] as $word => $score) {
 | 
				
			||||||
    // Try inserting first because this will succeed most times, but because
 | 
					    // If a word already exists in the database, its score gets increased 
 | 
				
			||||||
    // the database collates similar words (accented and non-accented), the
 | 
					    // appropriately.  If not, we create a new record with the appropriate 
 | 
				
			||||||
    // insert can fail, in which case we need to add the word scores together.
 | 
					    // starting score.
 | 
				
			||||||
    @db_query("INSERT INTO {search_index} (word, sid, type, score) VALUES ('%s', %d, '%s', %f)", $word, $sid, $type, $score);
 | 
					    db_merge('search_index')->key(array(
 | 
				
			||||||
    if (!db_affected_rows()) {
 | 
					      'word' => $word,
 | 
				
			||||||
      db_query("UPDATE {search_index} SET score = score + %f WHERE word = '%s' AND sid = %d AND type = '%s'", $score, $word, $sid, $type);
 | 
					      'sid' => $sid,
 | 
				
			||||||
    }
 | 
					      'type' => $type,
 | 
				
			||||||
 | 
					    ))->fields(array('score' => $score))->expression('score', 'score + :score', array(':score' => $score))
 | 
				
			||||||
 | 
					    ->execute();
 | 
				
			||||||
    search_dirty($word);
 | 
					    search_dirty($word);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  unset($results[0]);
 | 
					  unset($results[0]);
 | 
				
			||||||
| 
						 | 
					@ -790,7 +789,7 @@ function search_parse_query($text) {
 | 
				
			||||||
        $any |= $num_new_scores;
 | 
					        $any |= $num_new_scores;
 | 
				
			||||||
        if ($q) {
 | 
					        if ($q) {
 | 
				
			||||||
          $queryor[] = $q;
 | 
					          $queryor[] = $q;
 | 
				
			||||||
          $arguments[] = $or;
 | 
					          $arguments[] = "% $or %";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (count($queryor)) {
 | 
					      if (count($queryor)) {
 | 
				
			||||||
| 
						 | 
					@ -805,7 +804,7 @@ function search_parse_query($text) {
 | 
				
			||||||
      list($q, $num_new_scores, $num_valid_words) = _search_parse_query($key, $arguments2);
 | 
					      list($q, $num_new_scores, $num_valid_words) = _search_parse_query($key, $arguments2);
 | 
				
			||||||
      if ($q) {
 | 
					      if ($q) {
 | 
				
			||||||
        $query[] = $q;
 | 
					        $query[] = $q;
 | 
				
			||||||
        $arguments[] = $key;
 | 
					        $arguments[] = "% $key %";
 | 
				
			||||||
        if (!$num_valid_words) {
 | 
					        if (!$num_valid_words) {
 | 
				
			||||||
          $simple = FALSE;
 | 
					          $simple = FALSE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -822,7 +821,7 @@ function search_parse_query($text) {
 | 
				
			||||||
    list($q) = _search_parse_query($key, $arguments2, TRUE);
 | 
					    list($q) = _search_parse_query($key, $arguments2, TRUE);
 | 
				
			||||||
    if ($q) {
 | 
					    if ($q) {
 | 
				
			||||||
      $query[] = $q;
 | 
					      $query[] = $q;
 | 
				
			||||||
      $arguments[] = $key;
 | 
					      $arguments[] = "% $key %";
 | 
				
			||||||
      $simple = FALSE;
 | 
					      $simple = FALSE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -856,7 +855,7 @@ function _search_parse_query(&$word, &$scores, $not = FALSE) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  // Return matching snippet and number of added words
 | 
					  // Return matching snippet and number of added words
 | 
				
			||||||
  return array("d.data " . ($not ? 'NOT ' : '') . "LIKE '%% %s %%'", $num_new_scores, $num_valid_words);
 | 
					  return array("d.data " . ($not ? 'NOT ' : '') . "LIKE '%s'", $num_new_scores, $num_valid_words);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,7 +70,16 @@ class DrupalWebTestCase {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    $current_db_prefix = $db_prefix;
 | 
					    $current_db_prefix = $db_prefix;
 | 
				
			||||||
    $db_prefix = $this->db_prefix_original;
 | 
					    $db_prefix = $this->db_prefix_original;
 | 
				
			||||||
    db_query("INSERT INTO {simpletest} (test_id, test_class, status, message, message_group, caller, line, file) VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s')", $this->test_id, get_class($this), $status, $message, $group, $function['function'], $function['line'], $function['file']);
 | 
					    db_insert('simpletest')->fields(array(
 | 
				
			||||||
 | 
					      'test_id' => $this->test_id,
 | 
				
			||||||
 | 
					    'test_class' => get_class($this), 
 | 
				
			||||||
 | 
					    'status' => $status, 
 | 
				
			||||||
 | 
					    'message' => substr($message, 0, 255),  // Some messages are too long for the database.
 | 
				
			||||||
 | 
					    'message_group' => $group, 
 | 
				
			||||||
 | 
					    'caller' => $function['function'], 
 | 
				
			||||||
 | 
					    'line' => $function['line'], 
 | 
				
			||||||
 | 
					    'file' => $function['file'],
 | 
				
			||||||
 | 
					    ))->execute();
 | 
				
			||||||
    $this->_assertions[] = array(
 | 
					    $this->_assertions[] = array(
 | 
				
			||||||
      'status' => $status,
 | 
					      'status' => $status,
 | 
				
			||||||
      'message' => $message,
 | 
					      'message' => $message,
 | 
				
			||||||
| 
						 | 
					@ -631,6 +640,7 @@ class DrupalWebTestCase {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Generate temporary prefixed database to ensure that tests have a clean starting point.
 | 
					    // Generate temporary prefixed database to ensure that tests have a clean starting point.
 | 
				
			||||||
    $db_prefix = 'simpletest' . mt_rand(1000, 1000000);
 | 
					    $db_prefix = 'simpletest' . mt_rand(1000, 1000000);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    include_once './includes/install.inc';
 | 
					    include_once './includes/install.inc';
 | 
				
			||||||
    drupal_install_system();
 | 
					    drupal_install_system();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -639,6 +649,12 @@ class DrupalWebTestCase {
 | 
				
			||||||
    $modules = array_unique(array_merge(drupal_verify_profile('default', 'en'), $args));
 | 
					    $modules = array_unique(array_merge(drupal_verify_profile('default', 'en'), $args));
 | 
				
			||||||
    drupal_install_modules($modules);
 | 
					    drupal_install_modules($modules);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Because the schema is static cached, we need to flush
 | 
				
			||||||
 | 
					    // it between each run.  If we don't, then it will contain
 | 
				
			||||||
 | 
					    // stale data for the previous run's database prefix and all
 | 
				
			||||||
 | 
					    // calls to it will fail.
 | 
				
			||||||
 | 
					    drupal_get_schema(NULL, TRUE);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    // Run default profile tasks.
 | 
					    // Run default profile tasks.
 | 
				
			||||||
    $task = 'profile';
 | 
					    $task = 'profile';
 | 
				
			||||||
    default_profile_tasks($task, '');
 | 
					    default_profile_tasks($task, '');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -312,8 +312,7 @@ function simpletest_test_form_submit($form, &$form_state) {
 | 
				
			||||||
function simpletest_run_tests($test_list, $reporter = 'drupal', $batch_mode = FALSE) {
 | 
					function simpletest_run_tests($test_list, $reporter = 'drupal', $batch_mode = FALSE) {
 | 
				
			||||||
  global $db_prefix, $db_prefix_original;
 | 
					  global $db_prefix, $db_prefix_original;
 | 
				
			||||||
  cache_clear_all();
 | 
					  cache_clear_all();
 | 
				
			||||||
  db_query('INSERT INTO {simpletest_test_id} VALUES (default)');
 | 
					  $test_id = db_insert('simpletest_test_id')->useDefaults(array('test_id'))->execute();
 | 
				
			||||||
  $test_id = db_last_insert_id('simpletest_test_id', 'test_id');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ($batch_mode) {
 | 
					  if ($batch_mode) {
 | 
				
			||||||
    $batch = array(
 | 
					    $batch = array(
 | 
				
			||||||
| 
						 | 
					@ -501,11 +500,14 @@ function simpletest_clean_database() {
 | 
				
			||||||
 * @return mixed Array of matching tables or count of tables.
 | 
					 * @return mixed Array of matching tables or count of tables.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function simpletest_get_like_tables($base_table = 'simpletest', $count = FALSE) {
 | 
					function simpletest_get_like_tables($base_table = 'simpletest', $count = FALSE) {
 | 
				
			||||||
  global $db_url, $db_prefix;
 | 
					  global $db_prefix, $database;
 | 
				
			||||||
  $url = parse_url($db_url);
 | 
					  $connection_info = Database::getConnectionInfo();
 | 
				
			||||||
  $database = substr($url['path'], 1);
 | 
					  $database_name = $connection_info['default']['database'];
 | 
				
			||||||
  $select = $count ? 'COUNT(table_name)' : 'table_name';
 | 
					  $select = $count ? 'COUNT(table_name)' : 'table_name';
 | 
				
			||||||
  $result = db_query("SELECT $select FROM information_schema.tables WHERE table_schema = '$database' AND table_name LIKE '$db_prefix$base_table%'");
 | 
					  $result = db_query("SELECT $select FROM information_schema.tables WHERE table_schema = :database AND table_name LIKE :table_name", array(
 | 
				
			||||||
 | 
					    ':database' => $database_name,
 | 
				
			||||||
 | 
					    ':table_name' => $db_prefix . $base_table . '%',
 | 
				
			||||||
 | 
					  ));
 | 
				
			||||||
  $schema = drupal_get_schema_unprocessed('simpletest');
 | 
					  $schema = drupal_get_schema_unprocessed('simpletest');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ($count) {
 | 
					  if ($count) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,17 +130,10 @@ class DrupalHTTPRequestTestCase extends DrupalWebTestCase {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function testDrupalHTTPRequest() {
 | 
					  function testDrupalHTTPRequest() {
 | 
				
			||||||
    // Parse URL schema.
 | 
					 | 
				
			||||||
    $missing_scheme = drupal_http_request('example.com/path');
 | 
					    $missing_scheme = drupal_http_request('example.com/path');
 | 
				
			||||||
    $this->assertEqual($missing_scheme->error, 'missing schema', t('Returned with missing scheme error.'));
 | 
					    $this->assertEqual($missing_scheme->error, 'missing schema', t('Returned with missing scheme error.'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $unable_to_parse = drupal_http_request('http:///path');
 | 
					    $unable_to_parse = drupal_http_request('http:///path');
 | 
				
			||||||
    $this->assertEqual($unable_to_parse->error, 'unable to parse URL', t('Returned with unable to parse URL error.'));
 | 
					    $this->assertEqual($unable_to_parse->error, 'unable to parse URL', t('Returned with unable to parse URL error.'));
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Fetch page.
 | 
					 | 
				
			||||||
    $result = drupal_http_request(url('node', array('absolute' => TRUE)));
 | 
					 | 
				
			||||||
    $this->assertEqual($result->code, 200, t('Fetched page successfully.'));
 | 
					 | 
				
			||||||
    $this->drupalSetContent($result->data);
 | 
					 | 
				
			||||||
    $this->assertTitle(variable_get('site_name', 'Drupal'), t('Site title matches.'));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,182 +0,0 @@
 | 
				
			||||||
<?php
 | 
					 | 
				
			||||||
// $Id$
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class DatabaseSecurityTestCase extends DrupalWebTestCase {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Implementation of getInfo().
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  function getInfo() {
 | 
					 | 
				
			||||||
    return array(
 | 
					 | 
				
			||||||
      'name' => t('Database placeholders'),
 | 
					 | 
				
			||||||
      'description' => t('Make sure that invalid values do not get passed through the %n, %d, or %f placeholders.'),
 | 
					 | 
				
			||||||
      'group' => t('System')
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  function testPlaceholders() {
 | 
					 | 
				
			||||||
    // First test the numeric type
 | 
					 | 
				
			||||||
    $valid = array(
 | 
					 | 
				
			||||||
      '0' => 0,
 | 
					 | 
				
			||||||
      '1' => 1,
 | 
					 | 
				
			||||||
      '543.21' => 543.21,
 | 
					 | 
				
			||||||
      '123.456' => 123.46,
 | 
					 | 
				
			||||||
      '+0.1e3' => 0.1e3,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    $not_valid = array(
 | 
					 | 
				
			||||||
      '1x' => 0,
 | 
					 | 
				
			||||||
      '4.4 OR 1=1' => 0,
 | 
					 | 
				
			||||||
      '9 9' => 0,
 | 
					 | 
				
			||||||
      '0xff' => 0,
 | 
					 | 
				
			||||||
      'XXX' => 0,
 | 
					 | 
				
			||||||
      '0Xaa' => 0,
 | 
					 | 
				
			||||||
      'e' => 0,
 | 
					 | 
				
			||||||
      '--1' => 0,
 | 
					 | 
				
			||||||
      'DROP TABLE' => 0,
 | 
					 | 
				
			||||||
      '44-66' => 0,
 | 
					 | 
				
			||||||
      '' => 0,
 | 
					 | 
				
			||||||
      '.' => 0,
 | 
					 | 
				
			||||||
      '%88' => 0,
 | 
					 | 
				
			||||||
     );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $schema = array(
 | 
					 | 
				
			||||||
      'fields' => array(
 | 
					 | 
				
			||||||
        'n' => array(
 | 
					 | 
				
			||||||
          'type' => 'numeric',
 | 
					 | 
				
			||||||
          'precision' => 5,
 | 
					 | 
				
			||||||
          'scale' => 2,
 | 
					 | 
				
			||||||
          'not null' => TRUE,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $ret = array();
 | 
					 | 
				
			||||||
    db_create_table($ret, 'test_numeric', $schema);
 | 
					 | 
				
			||||||
    $insert_query = 'INSERT INTO {test_numeric} (n) VALUES (' . db_type_placeholder('numeric') . ')';
 | 
					 | 
				
			||||||
    foreach ($valid as $insert => $select) {
 | 
					 | 
				
			||||||
      db_query('DELETE FROM {test_numeric}');
 | 
					 | 
				
			||||||
      db_query($insert_query, $insert);
 | 
					 | 
				
			||||||
      $count = db_result(db_query('SELECT COUNT(*) FROM {test_numeric}'));
 | 
					 | 
				
			||||||
      $this->assertEqual(1, $count, "[numeric] One row ($count) after inserting $insert");
 | 
					 | 
				
			||||||
      $test = db_result(db_query('SELECT n FROM {test_numeric}'));
 | 
					 | 
				
			||||||
      $this->assertEqual($select, $test, "[numeric] Got $select ($test) after inserting valid value $insert");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    foreach ($not_valid as $insert => $select) {
 | 
					 | 
				
			||||||
      db_query('DELETE FROM {test_numeric}');
 | 
					 | 
				
			||||||
      db_query($insert_query, $insert);
 | 
					 | 
				
			||||||
      $count = db_result(db_query('SELECT COUNT(*) FROM {test_numeric}'));
 | 
					 | 
				
			||||||
      $this->assertEqual(1, $count, "[numeric] One row ($count) after inserting $insert");
 | 
					 | 
				
			||||||
      $test = db_result(db_query('SELECT n FROM {test_numeric}'));
 | 
					 | 
				
			||||||
      $this->assertEqual(0, $test, "[numeric] Got $select ($test) after inserting invalid value $insert");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Test ints
 | 
					 | 
				
			||||||
    $valid = array(
 | 
					 | 
				
			||||||
      '0' => 0,
 | 
					 | 
				
			||||||
      '1' => 1,
 | 
					 | 
				
			||||||
      '543.21' => 543,
 | 
					 | 
				
			||||||
      '123.456' => 123,
 | 
					 | 
				
			||||||
      '22' => 22,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    $not_valid = array(
 | 
					 | 
				
			||||||
      '+0.1e3' => 0,
 | 
					 | 
				
			||||||
      '0xff' => 0,
 | 
					 | 
				
			||||||
      '0Xaa' => 0,
 | 
					 | 
				
			||||||
      '1x' => 1,
 | 
					 | 
				
			||||||
      '4.4 OR 1=1' => 4,
 | 
					 | 
				
			||||||
      '9 9' => 9,
 | 
					 | 
				
			||||||
      'XXX' => 0,
 | 
					 | 
				
			||||||
      'e' => 0,
 | 
					 | 
				
			||||||
      '--1' => 0,
 | 
					 | 
				
			||||||
      'DROP TABLE' => 0,
 | 
					 | 
				
			||||||
      '44-66' => 44,
 | 
					 | 
				
			||||||
      '' => 0,
 | 
					 | 
				
			||||||
      '.' => 0,
 | 
					 | 
				
			||||||
      '%88' => 0,
 | 
					 | 
				
			||||||
     );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $schema = array(
 | 
					 | 
				
			||||||
      'fields' => array(
 | 
					 | 
				
			||||||
        'n' => array(
 | 
					 | 
				
			||||||
          'type' => 'int',
 | 
					 | 
				
			||||||
          'not null' => TRUE,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $ret = array();
 | 
					 | 
				
			||||||
    db_create_table($ret, 'test_int', $schema);
 | 
					 | 
				
			||||||
    $insert_query = 'INSERT INTO {test_int} (n) VALUES (' . db_type_placeholder('int') . ')';
 | 
					 | 
				
			||||||
    foreach ($valid as $insert => $select) {
 | 
					 | 
				
			||||||
      db_query('DELETE FROM {test_int}');
 | 
					 | 
				
			||||||
      db_query($insert_query, $insert);
 | 
					 | 
				
			||||||
      $count = db_result(db_query('SELECT COUNT(*) FROM {test_int}'));
 | 
					 | 
				
			||||||
      $this->assertEqual(1, $count, "[int] One row ($count) after inserting $insert");
 | 
					 | 
				
			||||||
      $test = db_result(db_query('SELECT n FROM {test_int}'));
 | 
					 | 
				
			||||||
      $this->assertEqual($select, $test, "[int] Got $select ($test) after inserting valid value $insert");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    foreach ($not_valid as $insert => $select) {
 | 
					 | 
				
			||||||
      db_query('DELETE FROM {test_int}');
 | 
					 | 
				
			||||||
      db_query($insert_query, $insert);
 | 
					 | 
				
			||||||
      $count = db_result(db_query('SELECT COUNT(*) FROM {test_int}'));
 | 
					 | 
				
			||||||
      $this->assertEqual(1, $count, "[int] One row ($count) after inserting $insert");
 | 
					 | 
				
			||||||
      $test = db_result(db_query('SELECT n FROM {test_int}'));
 | 
					 | 
				
			||||||
      $this->assertEqual($select, $test, "[int] Got $select ($test) after inserting invalid value $insert");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Test floats
 | 
					 | 
				
			||||||
    $valid = array(
 | 
					 | 
				
			||||||
      '0' => 0,
 | 
					 | 
				
			||||||
      '1' => 1,
 | 
					 | 
				
			||||||
      '543.21' => 543.21,
 | 
					 | 
				
			||||||
      '123.456' => 123.456,
 | 
					 | 
				
			||||||
      '22' => 22,
 | 
					 | 
				
			||||||
      '+0.1e3' => 100,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    $not_valid = array(
 | 
					 | 
				
			||||||
      '0xff' => 0,
 | 
					 | 
				
			||||||
      '0Xaa' => 0,
 | 
					 | 
				
			||||||
      '1x' => 1,
 | 
					 | 
				
			||||||
      '4.4 OR 1=1' => 4.4,
 | 
					 | 
				
			||||||
      '9 9' => 9,
 | 
					 | 
				
			||||||
      'XXX' => 0,
 | 
					 | 
				
			||||||
      'e' => 0,
 | 
					 | 
				
			||||||
      '--1' => 0,
 | 
					 | 
				
			||||||
      'DROP TABLE' => 0,
 | 
					 | 
				
			||||||
      '44-66' => 44,
 | 
					 | 
				
			||||||
      '' => 0,
 | 
					 | 
				
			||||||
      '.' => 0,
 | 
					 | 
				
			||||||
      '%88' => 0,
 | 
					 | 
				
			||||||
     );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $schema = array(
 | 
					 | 
				
			||||||
      'fields' => array(
 | 
					 | 
				
			||||||
        'n' => array(
 | 
					 | 
				
			||||||
          'type' => 'float',
 | 
					 | 
				
			||||||
          'not null' => TRUE,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $ret = array();
 | 
					 | 
				
			||||||
    db_create_table($ret, 'test_float', $schema);
 | 
					 | 
				
			||||||
    $insert_query = 'INSERT INTO {test_float} (n) VALUES (' . db_type_placeholder('float') . ')';
 | 
					 | 
				
			||||||
    foreach ($valid as $insert => $select) {
 | 
					 | 
				
			||||||
      db_query('DELETE FROM {test_float}');
 | 
					 | 
				
			||||||
      db_query($insert_query, $insert);
 | 
					 | 
				
			||||||
      $count = db_result(db_query('SELECT COUNT(*) FROM {test_float}'));
 | 
					 | 
				
			||||||
      $this->assertEqual(1, $count, "[float] One row ($count) after inserting $insert");
 | 
					 | 
				
			||||||
      $test = db_result(db_query('SELECT n FROM {test_float}'));
 | 
					 | 
				
			||||||
      $this->assertEqual($select, $test, "[float] Got $select ($test) after inserting valid value $insert");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    foreach ($not_valid as $insert => $select) {
 | 
					 | 
				
			||||||
      db_query('DELETE FROM {test_float}');
 | 
					 | 
				
			||||||
      db_query($insert_query, $insert);
 | 
					 | 
				
			||||||
      $count = db_result(db_query('SELECT COUNT(*) FROM {test_float}'));
 | 
					 | 
				
			||||||
      $this->assertEqual(1, $count, "[float] One row ($count) after inserting $insert");
 | 
					 | 
				
			||||||
      $test = db_result(db_query('SELECT n FROM {test_float}'));
 | 
					 | 
				
			||||||
      $this->assertEqual($select, $test, "[float] Got $select ($test) after inserting invalid value $insert");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -107,8 +107,8 @@ function statistics_top_visitors() {
 | 
				
			||||||
 * Menu callback; presents the "referrer" page.
 | 
					 * Menu callback; presents the "referrer" page.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function statistics_top_referrers() {
 | 
					function statistics_top_referrers() {
 | 
				
			||||||
  $query = "SELECT url, COUNT(url) AS hits, MAX(timestamp) AS last FROM {accesslog} WHERE url NOT LIKE '%%%s%%' AND url <> '' GROUP BY url";
 | 
					  $query = "SELECT url, COUNT(url) AS hits, MAX(timestamp) AS last FROM {accesslog} WHERE url NOT LIKE :host AND url <> '' GROUP BY url";
 | 
				
			||||||
  $query_cnt = "SELECT COUNT(DISTINCT(url)) FROM {accesslog} WHERE url <> '' AND url NOT LIKE '%%%s%%'";
 | 
					  $query_cnt = "SELECT COUNT(DISTINCT(url)) FROM {accesslog} WHERE url <> '' AND url NOT LIKE :host";
 | 
				
			||||||
  drupal_set_title(t('Top referrers in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))));
 | 
					  drupal_set_title(t('Top referrers in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $header = array(
 | 
					  $header = array(
 | 
				
			||||||
| 
						 | 
					@ -118,7 +118,7 @@ function statistics_top_referrers() {
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $query .= tablesort_sql($header);
 | 
					  $query .= tablesort_sql($header);
 | 
				
			||||||
  $result = pager_query($query, 30, 0, $query_cnt, $_SERVER['HTTP_HOST']);
 | 
					  $result = pager_query($query, 30, 0, $query_cnt, array(':host' => '%'. $_SERVER['HTTP_HOST'] .'%'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $rows = array();
 | 
					  $rows = array();
 | 
				
			||||||
  while ($referrer = db_fetch_object($result)) {
 | 
					  while ($referrer = db_fetch_object($result)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,17 +51,31 @@ function statistics_exit() {
 | 
				
			||||||
    // We are counting content views.
 | 
					    // We are counting content views.
 | 
				
			||||||
    if ((arg(0) == 'node') && is_numeric(arg(1)) && arg(2) == '') {
 | 
					    if ((arg(0) == 'node') && is_numeric(arg(1)) && arg(2) == '') {
 | 
				
			||||||
      // A node has been viewed, so update the node's counters.
 | 
					      // A node has been viewed, so update the node's counters.
 | 
				
			||||||
      db_query('UPDATE {node_counter} SET daycount = daycount + 1, totalcount = totalcount + 1, timestamp = %d WHERE nid = %d', time(), arg(1));
 | 
					      $fields = array(
 | 
				
			||||||
      // If we affected 0 rows, this is the first time viewing the node.
 | 
					        'daycount' => 1,
 | 
				
			||||||
      if (!db_affected_rows()) {
 | 
					        'totalcount' => 1,
 | 
				
			||||||
        // We must create a new row to store counters for the new node.
 | 
					        'nid' => arg(1),
 | 
				
			||||||
        db_query('INSERT INTO {node_counter} (nid, daycount, totalcount, timestamp) VALUES (%d, 1, 1, %d)', arg(1), time());
 | 
					        'timestamp' => time(),
 | 
				
			||||||
      }
 | 
					      );
 | 
				
			||||||
 | 
					      db_merge('node_counter')
 | 
				
			||||||
 | 
					        ->fields($fields)
 | 
				
			||||||
 | 
					        ->expression('daycount', 'daycount + 1')
 | 
				
			||||||
 | 
					        ->expression('totalcount', 'totalcount + 1')
 | 
				
			||||||
 | 
					        ->execute();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (variable_get('statistics_enable_access_log', 0)) {
 | 
					  if (variable_get('statistics_enable_access_log', 0)) {
 | 
				
			||||||
    // Log this page access.
 | 
					    // Log this page access.
 | 
				
			||||||
    db_query("INSERT INTO {accesslog} (title, path, url, hostname, uid, sid, timer, timestamp) values('%s', '%s', '%s', '%s', %d, '%s', %d, %d)", strip_tags(drupal_get_title()), $_GET['q'], referer_uri(), ip_address(), $user->uid, session_id(), timer_read('page'), time());
 | 
					    db_insert('accesslog')->fields(array(
 | 
				
			||||||
 | 
					      'title' => strip_tags(drupal_get_title()),
 | 
				
			||||||
 | 
					      'path' => $_GET['q'], 
 | 
				
			||||||
 | 
					      'url' => referer_uri(), 
 | 
				
			||||||
 | 
					      'hostname' => ip_address(), 
 | 
				
			||||||
 | 
					      'uid' => $user->uid, 
 | 
				
			||||||
 | 
					      'sid' => session_id(), 
 | 
				
			||||||
 | 
					      'timer' => timer_read('page'), 
 | 
				
			||||||
 | 
					      'timestamp' => time(),
 | 
				
			||||||
 | 
					    ))->execute();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -606,11 +606,11 @@ function _system_is_incompatible(&$incompatible, $files, $file) {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function system_modules($form_state = array()) {
 | 
					function system_modules($form_state = array()) {
 | 
				
			||||||
  // Clear all caches.
 | 
					  // Clear all caches.
 | 
				
			||||||
 | 
					  registry_rebuild();
 | 
				
			||||||
  drupal_theme_rebuild();
 | 
					  drupal_theme_rebuild();
 | 
				
			||||||
  node_types_rebuild();
 | 
					  node_types_rebuild();
 | 
				
			||||||
  menu_rebuild();
 | 
					  menu_rebuild();
 | 
				
			||||||
  cache_clear_all('schema', 'cache');
 | 
					  cache_clear_all('schema', 'cache');
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Get current list of modules.
 | 
					  // Get current list of modules.
 | 
				
			||||||
  $files = module_rebuild_cache();
 | 
					  $files = module_rebuild_cache();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -677,6 +677,9 @@ function system_modules($form_state = array()) {
 | 
				
			||||||
        $extra['dependents'][] = $files[$dependent]->info['name'] . t(' (<span class="admin-disabled">disabled</span>)');
 | 
					        $extra['dependents'][] = $files[$dependent]->info['name'] . t(' (<span class="admin-disabled">disabled</span>)');
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (!isset($module->info['package'])) {
 | 
				
			||||||
 | 
					      $module->info['package'] = 'Other';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    $form['modules'][$module->info['package']][$filename] = _system_modules_build_row($module->info, $extra);
 | 
					    $form['modules'][$module->info['package']][$filename] = _system_modules_build_row($module->info, $extra);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  // Add basic information to the fieldsets.
 | 
					  // Add basic information to the fieldsets.
 | 
				
			||||||
| 
						 | 
					@ -2245,4 +2248,4 @@ function theme_system_themes_form($form) {
 | 
				
			||||||
  $output = theme('table', $header, $rows);
 | 
					  $output = theme('table', $header, $rows);
 | 
				
			||||||
  $output .= drupal_render($form);
 | 
					  $output .= drupal_render($form);
 | 
				
			||||||
  return $output;
 | 
					  return $output;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -303,7 +303,7 @@ function system_requirements($phase) {
 | 
				
			||||||
 * Implementation of hook_install().
 | 
					 * Implementation of hook_install().
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function system_install() {
 | 
					function system_install() {
 | 
				
			||||||
  if ($GLOBALS['db_type'] == 'pgsql') {
 | 
					  if (db_driver() == 'pgsql') {
 | 
				
			||||||
    // We create some custom types and functions using global names instead of
 | 
					    // We create some custom types and functions using global names instead of
 | 
				
			||||||
    // prefixing them like we do with table names. If this function is ever
 | 
					    // prefixing them like we do with table names. If this function is ever
 | 
				
			||||||
    // called again (for example, by the test framework when creating prefixed
 | 
					    // called again (for example, by the test framework when creating prefixed
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1123,7 +1123,7 @@ function system_region_list($theme_key) {
 | 
				
			||||||
  static $list = array();
 | 
					  static $list = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!array_key_exists($theme_key, $list)) {
 | 
					  if (!array_key_exists($theme_key, $list)) {
 | 
				
			||||||
    $info = unserialize(db_result(db_query("SELECT info FROM {system} WHERE type = 'theme' AND name = '%s'", $theme_key)));
 | 
					    $info = unserialize(db_result(db_query("SELECT info FROM {system} WHERE type = :type AND name = :name", array(':type' => 'theme', ':name' => $theme_key))));
 | 
				
			||||||
    $list[$theme_key] = array_map('t', $info['regions']);
 | 
					    $list[$theme_key] = array_map('t', $info['regions']);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,7 +119,10 @@ function taxonomy_autocomplete($vid, $string = '') {
 | 
				
			||||||
  $last_string = trim(array_pop($array));
 | 
					  $last_string = trim(array_pop($array));
 | 
				
			||||||
  $matches = array();
 | 
					  $matches = array();
 | 
				
			||||||
  if ($last_string != '') {
 | 
					  if ($last_string != '') {
 | 
				
			||||||
    $result = db_query_range(db_rewrite_sql("SELECT t.tid, t.name FROM {term_data} t WHERE t.vid = %d AND LOWER(t.name) LIKE LOWER('%%%s%%')", 't', 'tid'), $vid, $last_string, 0, 10);
 | 
					    $result = db_query_range(db_rewrite_sql("SELECT t.tid, t.name FROM {term_data} t WHERE t.vid = :vid AND LOWER(t.name) LIKE LOWER(:last_string)", 't', 'tid'), array(
 | 
				
			||||||
 | 
					      ':vid' => $vid, 
 | 
				
			||||||
 | 
					      ':last_string' => '%'. $last_string .'%',
 | 
				
			||||||
 | 
					    ), 0, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $prefix = count($array) ? implode(', ', $array) . ', ' : '';
 | 
					    $prefix = count($array) ? implode(', ', $array) . ', ' : '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -295,7 +295,8 @@ function trigger_comment($a1, $op) {
 | 
				
			||||||
      actions_do($aid, $objects[$action_info['type']], $context);
 | 
					      actions_do($aid, $objects[$action_info['type']], $context);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
      actions_do($aid, (object) $a1, $context);
 | 
					      $a1 = (object) $a1;
 | 
				
			||||||
 | 
					      actions_do($aid, $a1, $context);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -387,8 +388,9 @@ function trigger_taxonomy($op, $type, $array) {
 | 
				
			||||||
    'hook' => 'taxonomy',
 | 
					    'hook' => 'taxonomy',
 | 
				
			||||||
    'op' => $op
 | 
					    'op' => $op
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					  $_array = (object) $array;
 | 
				
			||||||
  foreach ($aids as $aid => $action_info) {
 | 
					  foreach ($aids as $aid => $action_info) {
 | 
				
			||||||
    actions_do($aid, (object) $array, $context);
 | 
					    actions_do($aid, $_array, $context);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1192,10 +1192,12 @@ function user_set_authmaps($account, $authmaps) {
 | 
				
			||||||
  foreach ($authmaps as $key => $value) {
 | 
					  foreach ($authmaps as $key => $value) {
 | 
				
			||||||
    $module = explode('_', $key, 2);
 | 
					    $module = explode('_', $key, 2);
 | 
				
			||||||
    if ($value) {
 | 
					    if ($value) {
 | 
				
			||||||
      db_query("UPDATE {authmap} SET authname = '%s' WHERE uid = %d AND module = '%s'", $value, $account->uid, $module[1]);
 | 
					      db_insert('authmap')->key(array(
 | 
				
			||||||
      if (!db_affected_rows()) {
 | 
					        'uid' => $account->uid,
 | 
				
			||||||
        db_query("INSERT INTO {authmap} (authname, uid, module) VALUES ('%s', %d, '%s')", $value, $account->uid, $module[1]);
 | 
					        'module' => $module[1],
 | 
				
			||||||
      }
 | 
					      ))->fields(array(
 | 
				
			||||||
 | 
					        'authname' => $value,
 | 
				
			||||||
 | 
					      ))->execute();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module[1]);
 | 
					      db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module[1]);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@
 | 
				
			||||||
function user_autocomplete($string = '') {
 | 
					function user_autocomplete($string = '') {
 | 
				
			||||||
  $matches = array();
 | 
					  $matches = array();
 | 
				
			||||||
  if ($string) {
 | 
					  if ($string) {
 | 
				
			||||||
    $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string, 0, 10);
 | 
					    $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER(:name)", array(':name' => $string .'%'), 0, 10);
 | 
				
			||||||
    while ($user = db_fetch_object($result)) {
 | 
					    while ($user = db_fetch_object($result)) {
 | 
				
			||||||
      $matches[$user->name] = check_plain($user->name);
 | 
					      $matches[$user->name] = check_plain($user->name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,10 +136,21 @@ function default_profile_tasks(&$task, $url) {
 | 
				
			||||||
  // Create a default vocabulary named "Tags", enabled for the 'article' content type.
 | 
					  // Create a default vocabulary named "Tags", enabled for the 'article' content type.
 | 
				
			||||||
  $description = st('Use tags to group articles on similar topics into categories.');
 | 
					  $description = st('Use tags to group articles on similar topics into categories.');
 | 
				
			||||||
  $help = st('Enter a comma-separated list of words.');
 | 
					  $help = st('Enter a comma-separated list of words.');
 | 
				
			||||||
  db_query("INSERT INTO {vocabulary} VALUES (NULL, 'Tags', '%s', '%s', 0, 0, 0, 0, 1, 'taxonomy', 0)", $description, $help);
 | 
					  
 | 
				
			||||||
  $vid = db_last_insert_id('vocabulary', 'vid');
 | 
					  $vid = db_insert('vocabulary')->fields(array(
 | 
				
			||||||
  db_query("INSERT INTO {vocabulary_node_types} VALUES (%d, 'article')", $vid);
 | 
					    'name' => 'Tags',
 | 
				
			||||||
 | 
					    'description' => $description,
 | 
				
			||||||
 | 
					    'help' => $help,
 | 
				
			||||||
 | 
					    'relations' => 0,
 | 
				
			||||||
 | 
					    'hierarchy' => 0,
 | 
				
			||||||
 | 
					    'multiple' => 0,
 | 
				
			||||||
 | 
					    'required' => 0,
 | 
				
			||||||
 | 
					    'tags' => 1,
 | 
				
			||||||
 | 
					    'module' => 'taxonomy',
 | 
				
			||||||
 | 
					    'weight' => 0,
 | 
				
			||||||
 | 
					  ))->execute();
 | 
				
			||||||
 | 
					  db_insert('vocabulary_node_types')->fields(array('vid' => $vid, 'type' => 'article'))->execute();
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
  // Update the menu router information.
 | 
					  // Update the menu router information.
 | 
				
			||||||
  menu_rebuild();
 | 
					  menu_rebuild();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,20 +46,76 @@
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Database settings:
 | 
					 * Database settings:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Note that the $db_url variable gets parsed using PHP's built-in
 | 
					 * The $databases array specifies the database connection or 
 | 
				
			||||||
 * URL parser (i.e. using the "parse_url()" function) so make sure
 | 
					 * connections that Drupal may use.  Drupal is able to connect
 | 
				
			||||||
 * not to confuse the parser. If your username, password
 | 
					 * to multiple databases, including multiple types of databases,
 | 
				
			||||||
 * or database name contain characters used to delineate
 | 
					 * during the same request.
 | 
				
			||||||
 * $db_url parts, you can escape them via URI hex encodings:
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *   : = %3a   / = %2f   @ = %40
 | 
					 * Each database connection is specified as an array of settings,
 | 
				
			||||||
 *   + = %2b   ( = %28   ) = %29
 | 
					 * similar to the following:
 | 
				
			||||||
 *   ? = %3f   = = %3d   & = %26
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * To specify multiple connections to be used in your site (i.e. for
 | 
					 * array(
 | 
				
			||||||
 * complex custom modules) you can also specify an associative array
 | 
					 *   'driver' => 'mysql',
 | 
				
			||||||
 * of $db_url variables with the 'default' element used until otherwise
 | 
					 *   'database' => 'databasename',
 | 
				
			||||||
 * requested.
 | 
					 *   'username' => 'username',
 | 
				
			||||||
 | 
					 *   'password' => 'password',
 | 
				
			||||||
 | 
					 *   'host' => 'localhost',
 | 
				
			||||||
 | 
					 * );
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The "driver" property indicates what Drupal database driver the 
 | 
				
			||||||
 | 
					 * connection should use.  This is usually the same as the name of the
 | 
				
			||||||
 | 
					 * database type, such as mysql or sqlite, but not always.  The other
 | 
				
			||||||
 | 
					 * properties will vary depending on the driver.  For SQLite, you must
 | 
				
			||||||
 | 
					 * specify a database.  For most other drivers, you must specify a username,
 | 
				
			||||||
 | 
					 * password, host, and database name.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Some database engines support transactions.  In order to enable
 | 
				
			||||||
 | 
					 * transaction support for a given database, set the 'transaction' key
 | 
				
			||||||
 | 
					 * to TRUE.  To disable it, set it to FALSE.  Note that the default value
 | 
				
			||||||
 | 
					 * varies by driver.  For MySQL, the default is FALSE since MyISAM tables
 | 
				
			||||||
 | 
					 * do not support transactions.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * For each database, you may optionally specify multiple "target" databases.
 | 
				
			||||||
 | 
					 * A target database allows Drupal to try to send certain queries to a
 | 
				
			||||||
 | 
					 * different database if it can but fall back to the default connection if not.
 | 
				
			||||||
 | 
					 * That is useful for master/slave replication, as Drupal may try to connect
 | 
				
			||||||
 | 
					 * to a slave server when appropriate and if one is not available will simply 
 | 
				
			||||||
 | 
					 * fall back to the single master server.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The general format for the $databases array is as follows:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * $databases['default']['default'] = $info_array;
 | 
				
			||||||
 | 
					 * $databases['default']['slave'][] = $info_array;
 | 
				
			||||||
 | 
					 * $databases['default']['slave'][] = $info_array;
 | 
				
			||||||
 | 
					 * $databases['extra'] = $info_array;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * In the above example, $info_array is an array of settings described above.
 | 
				
			||||||
 | 
					 * The first line sets a "default" database that has one master database
 | 
				
			||||||
 | 
					 * (the second level default).  The second and third lines create an array
 | 
				
			||||||
 | 
					 * of potential slave databases.  Drupal will select one at random for a given
 | 
				
			||||||
 | 
					 * request as needed.  The fourth line creates a new database with a name of
 | 
				
			||||||
 | 
					 * "extra".  Since no target is specified, it is assumed to be "default", that
 | 
				
			||||||
 | 
					 * is, only one server.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * For a single database configuration, the following is sufficient:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * $databases = array(
 | 
				
			||||||
 | 
					 *   'driver' => 'mysql',
 | 
				
			||||||
 | 
					 *   'database' => 'databasename',
 | 
				
			||||||
 | 
					 *   'username' => 'username',
 | 
				
			||||||
 | 
					 *   'password' => 'password',
 | 
				
			||||||
 | 
					 *   'host' => 'localhost',
 | 
				
			||||||
 | 
					 * );
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * That is equivalent to:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * $databases['default']['default'] = array(
 | 
				
			||||||
 | 
					 *   'driver' => 'mysql',
 | 
				
			||||||
 | 
					 *   'database' => 'databasename',
 | 
				
			||||||
 | 
					 *   'username' => 'username',
 | 
				
			||||||
 | 
					 *   'password' => 'password',
 | 
				
			||||||
 | 
					 *   'host' => 'localhost',
 | 
				
			||||||
 | 
					 * );
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You can optionally set prefixes for some or all database table names
 | 
					 * You can optionally set prefixes for some or all database table names
 | 
				
			||||||
 * by using the $db_prefix setting. If a prefix is specified, the table
 | 
					 * by using the $db_prefix setting. If a prefix is specified, the table
 | 
				
			||||||
| 
						 | 
					@ -84,12 +140,27 @@
 | 
				
			||||||
 *     'authmap'   => 'shared_',
 | 
					 *     'authmap'   => 'shared_',
 | 
				
			||||||
 *   );
 | 
					 *   );
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Database URL format:
 | 
					 * Database configuration format:
 | 
				
			||||||
 *   $db_url = 'mysql://username:password@localhost/databasename';
 | 
					 *   $databases = array(
 | 
				
			||||||
 *   $db_url = 'mysqli://username:password@localhost/databasename';
 | 
					 *     'driver' => 'mysql',
 | 
				
			||||||
 *   $db_url = 'pgsql://username:password@localhost/databasename';
 | 
					 *     'database' => 'databasename',
 | 
				
			||||||
 | 
					 *     'username' => 'username',
 | 
				
			||||||
 | 
					 *     'password' => 'password',
 | 
				
			||||||
 | 
					 *     'host' => 'localhost',
 | 
				
			||||||
 | 
					 *   );
 | 
				
			||||||
 | 
					 *   $databases = array(
 | 
				
			||||||
 | 
					 *     'driver' => 'pgsql',
 | 
				
			||||||
 | 
					 *     'database' => 'databasename',
 | 
				
			||||||
 | 
					 *     'username' => 'username',
 | 
				
			||||||
 | 
					 *     'password' => 'password',
 | 
				
			||||||
 | 
					 *     'host' => 'localhost',
 | 
				
			||||||
 | 
					 *   );
 | 
				
			||||||
 | 
					 *   $databases = array(
 | 
				
			||||||
 | 
					 *     'driver' => 'sqlite',
 | 
				
			||||||
 | 
					 *     'database' => 'databasefilename',
 | 
				
			||||||
 | 
					 *   );
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
$db_url = '';
 | 
					$databases = array();
 | 
				
			||||||
$db_prefix = '';
 | 
					$db_prefix = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue