Skip to content

Loading…

Added $this->db->switch_db('db_name') to DB Driver #396

Closed
wants to merge 7 commits into from

5 participants

@kylefarris

Added switch_db method to Database driver to allow you to switch to another database that shares the same connection info as the current connection. This should help prevent you from having to litter your database config with a bunch of the same exact connection information with just different database names.

I know what you're thinking... "Kyle, you can just do this..."

$this->db->query("select * from db_name.table_name");

or

$this->db->query("use database_name");
$this->db->query("select * from table_name");

And, I agree... this is what you should do whenever you can. But, it doesn't always work.

Problem:

// This block will end up making a backup of database1 despite switching to database2
$this->load->database('database1');
$res = $this->db->query("select * from table_name");
$this->db->query("use database2"); // shares same connection info as database2
$this->load->dbutil();
$this->db->backup();

Solution:

// This block will end up making a backup of database2, yay!
$this->load->database('database1');
$res = $this->db->query("select * from table_name");
$this->db->switch_db("database2");// shares same connection info as database2
$this->load->dbutil();
$this->db->backup();
@timw4mail

What do you mean by same connection information?

@kylefarris

@timw4mail: Same, host, username, password, etc...

To clarify:

Instead of:

$db['db1']['hostname'] = "localhost";
$db['db1']['username'] = "scripts";
$db['db1']['password'] = "some_password";
$db['db1']['database'] = "database1";
$db['db1']['dbdriver'] = "mysql";
$db['db1']['dbprefix'] = "";
$db['db1']['pconnect'] = TRUE;
$db['db1']['db_debug'] = TRUE;
$db['db1']['cache_on'] = FALSE;
$db['db1']['cachedir'] = "";
$db['db1']['char_set'] = "utf8";
$db['db1']['dbcollat'] = "utf8_general_ci";
$db['db1']['swap_pre'] = '';
$db['db1']['autoinit'] = TRUE;
$db['db1']['stricton'] = TRUE;
$db['db1']['ssl'] = TRUE;

$db['db2']['hostname'] = "localhost";
$db['db2']['username'] = "scripts";
$db['db2']['password'] = "some_password";
$db['db2']['database'] = "database2"; // the only thing different
$db['db2']['dbdriver'] = "mysql";
$db['db2']['dbprefix'] = "";
$db['db2']['pconnect'] = TRUE;
$db['db2']['db_debug'] = TRUE;
$db['db2']['cache_on'] = FALSE;
$db['db2']['cachedir'] = "";
$db['db2']['char_set'] = "utf8";
$db['db2']['dbcollat'] = "utf8_general_ci";
$db['db2']['swap_pre'] = '';
$db['db2']['autoinit'] = TRUE;
$db['db2']['stricton'] = TRUE;
$db['db2']['ssl'] = TRUE;

You only need to list one... of those and then use $this->db->switch_db('database2') to change dbs.

Sidenote:

I suppose you could always do this in your config:

$db['db1']['hostname'] = "localhost";
$db['db1']['username'] = "scripts";
$db['db1']['password'] = "some_password";
$db['db1']['database'] = "database1";
$db['db1']['dbdriver'] = "mysql";
$db['db1']['dbprefix'] = "";
$db['db1']['pconnect'] = TRUE;
$db['db1']['db_debug'] = TRUE;
$db['db1']['cache_on'] = FALSE;
$db['db1']['cachedir'] = "";
$db['db1']['char_set'] = "utf8";
$db['db1']['dbcollat'] = "utf8_general_ci";
$db['db1']['swap_pre'] = '';
$db['db1']['autoinit'] = TRUE;
$db['db1']['stricton'] = TRUE;
$db['db1']['ssl'] = TRUE;

$db['db2'] = $db['db1'];
$db['db2']['database'] = "database2";

And then switch your databases like $this->load->database('db2');. But then you still have to list every database you might have in your config and then, to switch it, you'd have to create a new instance of the DB object which creates a new db connection handle which would be quite a bit slower than just changing the database being communicated with (which in MySQL's case is just a matter of a single function call: mysql_select_db()).

@timw4mail

Hmm...is there a reason the other connection information has to be the same? I could see this being more useful if you could switch databases in general.

@kylefarris

@timew4mail: You can already do that using database configs or passing DSN strings to $this->load->database() like:

$this->load->database('dbdriver://username:password@hostname/database');

The reason I'm providing this method is simply for convenience so you don't have to create a config entry for every database on your host that all share the same username/password combo (of which there can be hundreds in some cases). In my opinion you also don't want to get into the maintainability nightmare of DSN strings scattered throughout your models, not to mention the performance degradation that would ensue from creating a new handle every time it's called.

@kylefarris

In all honesty, this is not something people will really be using all that much, I don't think. There are only a few cases where using this method is preferable to just using the database_name.table_name syntax in queries... those being where you currently don't have that kind of control through the API like when using $this->dbutil->list_tables() or $this->dbutil->backup().

This is something that is going to speed up development of sites that utilize many databases on the same host that can all be connected to with a single username/password combo (even ones that just use 2 or 3 dbs). It will increase maintainability and reduce the need to configure before getting your hands dirty—which I think is the CodeIgniter way...

@kylefarris

This pull request has been merged with develop. Could we try and get this merged soon (if it's something we all would like to have)? Thanks.

@mpmont

Well I like the idea. =9 go for it... I found myself doing this all the time for backups =)

@mexitek

This is assuming that you use the same user for all your databases on the db machine? Same db user for production and db backups?

@narfbg

You can use $this->db->db_select('dbname') now - see pull #1069 for details.

@narfbg narfbg closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 6, 2011
  1. @kylefarris

    Added `switch_db` method to Database driver to allow you to switch to…

    kylefarris committed
    … another database that shares the same connection info as the current connection.
  2. @kylefarris
  3. @kylefarris
  4. @kylefarris

    Added new language entry for bad databases switches happen (ex. the d…

    kylefarris committed
    …atabase string is empty when calling switch_db()).
Commits on Oct 14, 2011
  1. Merged with develop

    Kyle Farris committed
  2. @kylefarris

    Updated to new changelog.

    kylefarris committed
  3. @kylefarris
View
28 system/database/DB_driver.php
@@ -1145,6 +1145,34 @@ function close()
}
$this->conn_id = FALSE;
}
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Switch the active database. The database must share the same
+ * connection settings as the default connection.
+ *
+ * @access public
+ * @param string
+ * @return resource
+ */
+ public function switch_db($db_name = '')
+ {
+ if (empty($db_name))
+ {
+ log_message('error', 'You did not provide a database name to switch to.');
+
+ if ($this->db_debug)
+ {
+ $this->display_error('db_bad_switch');
+ }
+ }
+ $this->database = $db_name;
+ $this->db_select();
+ // Must clear the cache to prevent things like $this->list_tables()
+ // from showing the wrong items.
+ $this->data_cache = array();
+ }
// --------------------------------------------------------------------
View
1 system/language/english/db_lang.php
@@ -24,6 +24,7 @@
$lang['db_column_definition_required'] = 'A column definition is required for that operation.';
$lang['db_unable_to_set_charset'] = 'Unable to set client connection character set: %s';
$lang['db_error_heading'] = 'A Database Error Occurred';
+$lang['db_bad_switch'] = 'No database name provided to switch databases.';
/* End of file db_lang.php */
/* Location: ./system/language/english/db_lang.php */
View
2 user_guide_src/source/changelog.rst
@@ -46,6 +46,8 @@ Release Date: Not Released
$this->db->like() in the :doc:`Database
Driver <database/active_record>`.
- Added $this->db->insert_batch() support to the OCI8 (Oracle) driver.
+ - Added the ability to switch to a database that shares the same connection information
+ as the current connection using $this->db->switch_db().
- Libraries
View
16 user_guide_src/source/database/connecting.rst
@@ -68,7 +68,8 @@ page <configuration>`.
Or you can submit your database values as a Data Source Name. DSNs must
have this prototype::
- $dsn = 'dbdriver://username:password@hostname/database'; $this->load->database($dsn);
+ $dsn = 'dbdriver://username:password@hostname/database';
+ $this->load->database($dsn);
To override default config values when connecting with a DSN string, add
the config variables as a query string.
@@ -76,6 +77,19 @@ the config variables as a query string.
::
$dsn = 'dbdriver://username:password@hostname/database?char_set=utf8&dbcollat=utf8_general_ci&cache_on=true&cachedir=/path/to/cache'; $this->load->database($dsn);
+ $this->load->database(<samp>$dsn</samp>);
+
+To avoid making several entries in your database configuration with the
+same connection information and/or peppering your models with the same DSN
+strings, you can switch to a database that shares the same connection
+information as your current connection using::
+
+ $this->db->query("use database_name");
+
+However, when using certain database utilities like ``$this->dbutil->list_tables()``,
+the above query is not sufficient. You must use::
+
+ $this->db->switch_db("database_name");
Connecting to Multiple Databases
================================
Something went wrong with that request. Please try again.