Your SlideShare is downloading. ×
Drupal7  dbtng
Upcoming SlideShare
Loading in...5

Thanks for flagging this SlideShare!

Oops! An error has occurred.


Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

Drupal7 dbtng


Published on

Published in: Technology

  • Be the first to comment

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

No notes for slide


  • 1. Drupal 7: DBTNG
  • 2. DBTNG?Databases:
  • 3. Databases: The next generation A brand new database layer for drupal7 Support for MySQL, PostgreSQL, SQL Lite Add-on drivers can be made
  • 4. Basic Queries
  • 5. Basic Queries Most SELECT queries are simple and don’t change Drupal calls these: static queries $result = db_query("SELECT name, filename FROM {system} WHERE type = :type AND status = :status", array(:type => module, :status => 1));
  • 6. Basic Queries Table names  wrapped in curly braces No database-specific syntax in the query. There are no literal values in the query. Instead, literal values are specified by placeholders.
  • 7. Placeholders Must be unique within a query, and must begin with a colon. Should never have quotation marks around them, regardless of the data type. The database server will handle that for us. Should be used for all literal data, even if it will not vary.
  • 8. Result Object The return value from a db_query() call is a result object.$list = array();foreach ($result as $record) { $list[] = t(@name: @filename, array( @name => $record->name, @filename => $record->filename, ));}
  • 9. Result as array By default, each $record in the result set is a stdClass object. This is how you get an array:$result = db_query("SELECT name, filename FROM {system} WHERE type =:type AND status = :status", array(:type => module, :status => 1), array(fetch=> PDO::FETCH_ASSOC));
  • 10. Fetch option We can also fetch a single record, or even just a single field:// Fetch a single record as an object.$record = $result->fetchObject();// Fetch a single record as an array.$record = $result->fetchAssoc();// Fetch just the first field of the next record.$field = $result->fetchField();// Fetch the entire result set at once into an array.$records = $result->fetchAll()
  • 11. Dynamic Queries
  • 12. Dynamic Queries To start, we create a new query object with db_select():$query = db_select(node, n); The first parameter is the name of the base table of the query and the second is the alias.
  • 13. Dynamic Queries  We then call additional methods on the $query object in order to build up the query logic we want to create dynamically$query = db_select(node, n);$query->fields(n, array(nid, title));$u_alias = $query->innerJoin(users ,u, %alias.uid = n.uid);$query->addField($u_alias, name, username);$query->condition("{$u_alias}.name", Bob);$query->condition(n.created, REQUEST_TIME - 604800, >=);$query->orderBy(n.created, DESC);$query->range(0, 5);$query->addTag(node_access);$result = $query->execute();
  • 14. Dynamic Queries The resulting querySELECT n.nid AS nid, n.title AS title, AS usernameFROM {node} nINNER JOIN {users} u ON u.nid = n.nidWHERE (n.created >= 1286213869) AND ( = Bob)ORDER BY n.created DESCLIMIT 5 OFFSET 0
  • 15. Dynamic Queries Theres one more important method to call —addTag(). It does mark the type of query it is If a query has been tagged then before it is turned into an SQL string it will be passed through hook_query_alter() and hook_query_TAG_alter().
  • 16. Dynamic Queries The node_access tag, is most important as it allows the node access system to alter the query, to filter out nodes that the current user should not have access to.
  • 17. Dynamic Queries  Most methods of the select builder return the select object itself and thus are chainable.  The exceptions are the addField() and join() methods, as those need to return a generated alias instead.n);$query = db_select(node,$u_alias = $query->innerJoin(users ,u, %alias.uid = n.uid); $query->addField($u_alias, name, username);$result = $query ->fields(n, array(nid, title)); ->condition("{$u_alias}.name", Bob); ->condition(n.created, REQUEST_TIME - 604800, >=); ->orderBy(n.created, DESC); ->range(0, 5); ->addTag(node_access) ->execute();
  • 18. Dynamic Queries SELECT queries have both static and dynamic versions INSERT, UPDATE, DELETE, and MERGE queries only support a dynamic version
  • 19. Insert
  • 20. Insert all methods of Insert queries are chainable.$id = db_insert(imports) ->fields(array( name => Groucho, address => 123 Casablanca Ave., phone => 555-1212, )) ->execute();
  • 21. Insert it supports multi-insert statements$values[] = array( name => Groucho, address => 123 Casablanca Ave., phone => 555-1212,);$values[] = array( name => Chico, address => 456 Races St., phone => 555-1234,);$values[] = array( name => Harpo, address => 789 Horn Ave., phone => 555-1234,);$values[] = array( name => Zeppo, address => 22 University Way, phone => 555-3579,);
  • 22. Insert it supports multi-insert statements$insert = db_insert(imports) ->fields(array(name, address, phone => 555-1212));foreach ($values as $value) { $insert->values($value);}$insert->execute();
  • 23. Insert On databases that support multi-insert statements, the preceding code will be run as a single query. For those that dont, they will run as separate queries within a single transaction. Note that in a multi-insert query the return value from execute() is undefined and should be ignored.
  • 24. Update
  • 25. Update Update queries look like a hybrid of Insert and Select statements. consist of both fields to set on a table and conditions to restrict the query.db_update(imports) ->condition(name, Chico) ->fields(array(address => Go West St.)) ->execute(); Resulting query:UPDATE {imports} SET address = Go West St. WHERE name = Chico;
  • 26. Update Return value from execute() for Update queries = number of records that were changed. changed does not mean matched. If the WHERE portion of the query matches a record but if that record already has the values that it would be set to, it will not be changed and would not count towards the return value from execute().
  • 27. Delete
  • 28. Delete Delete queries should come as no surprise, as they consist of essentially just a WHERE clause:db_delete(imports) ->condition(name => Zeppo) ->execute(); Return value from execute() = number of records that were deleted by the query.
  • 29. Merge
  • 30. Merge one of the oft-forgotten parts of SQL the most popular open source databases do not support them directly "If this record exists, update it with this query otherwise create it with this other query" It is most useful for setting records that may or may not exist yet, that is, merging data into the table.
  • 31. Merge A true merge query is atomic = were guaranteed that it will run as a single uninterrupted operation or fail completely. Since most of the databases Drupal works with do not directly support Merge queries, Drupal emulates them with multiple queries and a transaction, which in most cases is close enough.
  • 32. Mergedb_merge(variable) ->key(array(name => $name)) ->fields(array(value => serialize($value))) ->execute(); The key() method takes an associative array of field/value pairs that are the pivot of the query. The fields() method is about the fields to set
  • 33. Merge The query can be read as: "If there is a record where the field name has the value $name, set the value field. If not, insert a new record with name equal to $name and value equal to the given string.”
  • 34. Merge We can also define more complex logic using the insertFields() and updateFields() methods.db_merge(people) ->key(array(job => Speaker)) ->insertFields(array( age => 31, name => Meredith, )) ->updateFields(array( name => Tiffany, )) ->execute();
  • 35. Advanced subjects
  • 36. Transactions A transaction in a database is a way to wrap two or more queries together and declare that they should be atomic. That is, either all succeed or none succeed. We start a transaction by creating a transaction object. Everything we do to the database is then part of the transaction until that object is destroyed, at which point the entire query is committed at once. In most cases, we let PHP destroy the transaction object for us when a function ends.
  • 37. Transactionsfunction my_function() { $transaction = db_transaction(); try { $id = db_insert(example) ->fields(array( field1 => mystring, field2 => 5, )) ->execute(); my_other_function($id); return $id; } catch (Exception $e) { $transaction->rollback(); watchdog_exception(type, $e); }}
  • 38. Slave servers Drupal also supports Master/slave database replication select queries can be run against a slave server to offload the work to separate servers The third parameter to db_query() or db_select() is an array of options that tweak the behavior of the query.
  • 39. Slave servers The key of interest = target It specifies which database variant the system should try. Legal values: default (which is the default) and slave. If "slave" is specified, Drupal will try to run the query against a slave server. If one is not available, it will silently fall back to the default server.
  • 40. Slave servers$result = db_query("SELECT name, filename FROM {system} WHERE type =:type AND status = :status", array(:type => module, :status => 1), array(fetch=> PDO::FETCH_ASSOC, target => slave));
  • 41. Slave servers Data on a slave server is always a little behind the master server Not all Select queries can handle their data being slightly stale After writing data, we can call db_ignore_slave(). It will make a note in the active session to disable the slave server for the current user only for a configurable period of time. (The default is five minutes.)
  • 42. Simplify code Especially for modules creating their own API They need their own query builder Example: Voting API
  • 43. Drupal 6: 96 code lines Drupal 7: 16 code lines<?php/*** Select individual votes from the database. <?php*/function votingapi_select_votes($criteria = array(), $limit = 0) { function votingapi_select_votes($criteria = array(), $limit = 0) { $anon_window = variable_get(votingapi_anonymous_window, 3600); if (!empty($criteria[vote_source]) && $anon_window > 0) { $criteria[timestamp] = time() - $anon_window; $anon_window = variable_get(votingapi_anonymous_window, 3600); } $votes = array(); if (!empty($criteria[vote_source]) && $anon_window >= 0) { $result = _votingapi_select(vote, $criteria, $limit); while ($vote = db_fetch_array($result)) { $votes[] = $vote; $criteria[timestamp] = REQUEST_TIME - $anon_window; } return $votes; }}/** $query = db_select(votingapi_vote)->fields(votingapi_vote);* Internal helper function constructs WHERE clauses. Dont use unless youre me.*/ foreach ($criteria as $key => $value) {function _votingapi_query($table = vote, $criteria = array(), $alias = v.) { $criteria += array( vote_id => NULL, $query->condition($key, $value, is_array($value) ? IN : =); vote_cache_id => NULL, content_id => NULL, } content_type => NULL, value_type => NULL, value => NULL, if (!empty($limit)) { tag => NULL, uid => NULL, $query->range(0, $limit); timestamp => NULL, vote_source => NULL, function => NULL, } ); return $query->execute()->fetchAll(PDO::FETCH_ASSOC); $query = ; $args = array(); if (!empty($criteria[vote_id])) { } } _votingapi_query_builder($alias . vote_id, $criteria[vote_id], $query, $args); ?> elseif (!empty($criteria[vote_cache_id])) { _votingapi_query_builder($alias . vote_cache_id, $criteria[vote_cache_id], $query, $args); } else { _votingapi_query_builder($alias . content_type, $criteria[content_type], $query, $args, TRUE); _votingapi_query_builder($alias . content_id, $criteria[content_id], $query, $args); _votingapi_query_builder($alias . value_type, $criteria[value_type], $query, $args, TRUE); _votingapi_query_builder($alias . tag, $criteria[tag], $query, $args, TRUE); _votingapi_query_builder($alias . function, $criteria[function], $query, $args, TRUE); _votingapi_query_builder($alias . uid, $criteria[uid], $query, $args); _votingapi_query_builder($alias . vote_source, $criteria[vote_source], $query, $args, TRUE); _votingapi_query_builder($alias . timestamp, $criteria[timestamp], $query, $args); } return array(query => $query, args => $args);}/*** Internal helper function constructs individual elements of WHERE clauses.* Dont use unless youre me.*/function _votingapi_query_builder($name, $value, &$query, &$args, $col_is_string = FALSE) { if (!isset($value)) { // Do nothing } elseif ($name === timestamp) { $query .= " AND timestamp >= %d"; $args[] = $value; } elseif ($name === v.timestamp) { $query .= " AND v.timestamp >= %d"; $args[] = $value; } else { if (is_array($value)) { if ($col_is_string) { $query .= " AND $name IN (" . db_placeholders($value, varchar) . ")"; $args = array_merge($args, $value); } else { $query .= " AND $name IN (" . db_placeholders($value, int) . ")"; $args = array_merge($args, $value); } } else { if ($col_is_string) { $query .= " AND $name = %s"; $args[] = $value; } else { $query .= " AND $name = %d"; $args[] = $value; } } }}?>
  • 44. See you in another Galaxy