Documente Academic
Documente Profesional
Documente Cultură
Limitations
No DB-specific optimizations
No automated type handling No master/slave replication No transaction support No dynamic queries
DB Fail!
PDO
Formal prepared statements
Type-agnostic queries
Databases: Drupal 7
Built on PDO
Fully object-oriented Procedural wrappers New driver model More DB-agnostic Oodles of goodies
New concepts
Database targets
Placeholders Fluent API
Targets
Alternate database connection
May be used or not Fallback to default Master/slave replication Multi-slave configuration
Configuration
$db_url; $databases['default']['default'] = array( 'driver' => 'mysql', 'database' => 'drupaldb', 'username' => 'username', 'password' => 'secret', 'host' => 'localhost', );
Master/slave Configuration
$databases['default']['default'] = array( 'driver' => 'mysql', 'database' => 'drupaldb1', // ... 'host' => 'dbserver1', ); $databases['default']['slave'][] = array( 'driver' => 'mysql', 'database' => 'drupaldb2', // ... 'host' => 'dbserver2', ); $databases['default']['slave'][] = array( 'driver' => 'mysql', 'database' => 'drupaldb3', // ... 'host' => 'dbserver3', );
Types of queries
Static
Dynamic Insert Update Delete Merge Truncate
Static queries
Doesn't change based on environment
Takes named placeholders
DB_Query()
// Drupal 6 $result = db_query("SELECT nid, title FROM {node} WHERE uid = %d AND type = '%s'", 5, 'page'); // Drupal 7 $result = db_query("SELECT nid, title FROM {node} WHERE uid = :uid AND type = :type", array( ':uid' => 5, ':type' => 'page', ));
Auto-expanding placeholders
// This code: db_query("SELECT * FROM {node} WHERE nid IN (:nids)", array( ':nids' => array(13, 42, 144), ); // Auto-expands into the equivalent of: db_query("SELECT * FROM {node} WHERE nid IN (13, 42, 144)");
A look inside...
function db_query($query, $args = array(), $options = array()) { if (empty($options['target'])) { $options['target'] = 'default'; } $db = Database::getConnection($options['target']); $db->query($query, $args, $options); }
Result Sets
$result = db_query("SELECT, nid, title FROM {node}"); foreach ($result as $record) { // Do stuff with $record, which is an object } $result = db_query("SELECT ...", array(), array( 'fetch' => PDO::FETCH_ASSOC, )); foreach ($result as $record) { // Do stuff with $record, which is an array }
Query Options
db_query("Select, nid, title FROM {node}", array(), array( 'target' => 'slave', 'fetch' => PDO::FETCH_ASSOC, ));
Fetch Options
// Fetch into a stdClass object. $options['fetch'] = PDO::FETCH_OBJ; // Fetch into an associative array. $options['fetch'] = PDO::FETCH_ASSOC; // Fetch into a numeric array. $options['fetch'] = PDO::FETCH_NUM; // Fetch into a dual-keyed array. $options['fetch'] = PDO::FETCH_BOTH; // Fetch into a custom class. $options['fetch'] = 'MyClass';
Dynamic queries
SELECT queries using query builder
db_select() Only use if you really need dynamic behavior
hook_query_alter()
All dynamic SELECT statements
Query tagging Structured data is easy to alter Access internal query structure hook_db_rewrite_sql()
Dynamic queries
$query = db_select('users', 'u', $options) ->condition('u.uid', 0, '<>') ->fields('u', array('uid', 'name', 'created')) ->orderBy('u.created') ->range(0, 50) ->addTag('foo'); $result = $query->execute(); function mymod_query_foo_alter($query) { $query->range(0, 10); } // SELECT u.uid AS uid, u.name AS name, u.created AS created // FROM {users} u // WHERE u.uid <> 0 // ORDER BY u.created // LIMIT 0, 10
Extenders
$query = db_select('node', 'n') ->extend('PagerDefault'); $query ->fields('n', array('nid', 'title') // This method is part of PagerDefault! ->limit(5) ->orderBy('title'); $result = $query->execute();
Insert
// Drupal 6 db_query("INSERT INTO {mytable} (intvar, stringvar, floatvar) VALUES (%d, '%s', %f)", 5, 'hello world', 3.14); $id = db_last_insert_id(); // Drupal 7 $id = db_insert('mytable') ->fields(array( 'intvar' => 5, 'stringvar' => 'hello world', 'floatvar' => 3.14, )) ->execute();
Multi-Insert
Insert FROM
// Build a SELECT query. $query = db_select('node', 'n'); // Join to the users table. $query->join('users', 'u', 'n.uid = u.uid'); // Add the fields we want. $query->addField('n','nid'); $query->addField('u','name'); // Add a condition to only get page nodes. $query->condition('type', 'page'); // Perform the insert. db_insert('mytable') ->from($query) ->execute();
Update
// Drupal 6 db_query("UPDATE {node} SET title='%s', status=%d WHERE uid=%d", 'hello world', 1, 5); // Drupal 7 db_update('node') ->fields(array( 'title' => 'hello world', 'status' => 1, )) ->condition('uid', 5) ->execute();
Delete
// Drupal 6 db_query("DELETE FROM {node} WHERE uid=%d AND created < %d", 5, time() - 3600); // Drupal 7 db_delete('node') ->condition('uid', 5) ->condition('created', REQUEST_TIME - 3600, '<') ->execute();
Merge
db_merge()
"INSERT, UPDATE, whichever" Update to same value or new Database-specific implementation
MySQL: INSERT ... ON DUPLICATE KEY UPDATE ... PostgreSQL: Needs function...
Transactions
Force multiple queries to run atomically
Only supported on some databases
(Silly MyISAM)
Transactions
function my_transaction_function() { try { $txn = db_transaction(); $id = db_insert('example') ->fields(array( 'field1' => 'mystring', 'field2' => 5, )) ->execute(); my_other_function($id); return $id; } catch (Exception $e) { $transaction->rollback('node', $e->getMessage(), array(), WATCHDOG_ERROR); } }
Technical MaNual
http://drupal.org/node/310069
PostgreSQL
MySQL
SQLite
Questions?
Step 1) Locate this session on the DCSF site http://sf2010.drupal.org/conference/schedule Step 2) Click the Take Survey link