summaryrefslogtreecommitdiff
path: root/includes/database/pgsql/database.inc
diff options
context:
space:
mode:
authorAngie Byron <webchick@24967.no-reply.drupal.org>2010-01-07 04:51:26 +0000
committerAngie Byron <webchick@24967.no-reply.drupal.org>2010-01-07 04:51:26 +0000
commit37fcdbc67cd5591107c93016d1d3bb109be5e9e6 (patch)
tree9f0ffd5a6d54456e97e53b57f3de29b0966a4bbc /includes/database/pgsql/database.inc
parent39f4d7245c0cb5e258b0ca6ec7fd31df6699408d (diff)
downloadbrdo-37fcdbc67cd5591107c93016d1d3bb109be5e9e6.tar.gz
brdo-37fcdbc67cd5591107c93016d1d3bb109be5e9e6.tar.bz2
#633678 by Josh Waihi, chx, Crell, David Strauss, and Damien Tournoud: Make sequence API work on non-MySQL databases.
Diffstat (limited to 'includes/database/pgsql/database.inc')
-rw-r--r--includes/database/pgsql/database.inc48
1 files changed, 48 insertions, 0 deletions
diff --git a/includes/database/pgsql/database.inc b/includes/database/pgsql/database.inc
index 8b60b957b..218d10865 100644
--- a/includes/database/pgsql/database.inc
+++ b/includes/database/pgsql/database.inc
@@ -11,6 +11,11 @@
* @{
*/
+/**
+ * The name by which to obtain a lock for retrive the next insert id.
+ */
+define('POSTGRESQL_NEXTID_LOCK', 1000);
+
class DatabaseConnection_pgsql extends DatabaseConnection {
public function __construct(array $connection_options = array()) {
@@ -127,6 +132,49 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
return isset($specials[$operator]) ? $specials[$operator] : NULL;
}
+
+ /**
+ * Retrive a the next id in a sequence.
+ *
+ * PostgreSQL has built in sequences. We'll use these instead of inserting
+ * and updating a sequences table.
+ */
+ public function nextId($existing = 0) {
+
+ // Retrive the name of the sequence. This information cannot be cached
+ // because the prefix may change, for example, like it does in simpletests.
+ $sequence_name = $this->makeSequenceName('sequences', 'value');
+
+ // When PostgreSQL gets a value too small then it will lock the table,
+ // retry the INSERT and if it's still too small then alter the sequence.
+ $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
+ if ($id > $existing) {
+ return $id;
+ }
+
+ // PostgreSQL advisory locks are simply locks to be used by an
+ // application such as Drupal. This will prevent other Drupal proccesses
+ // from altering the sequence while we are.
+ $this->query("SELECT pg_advisory_lock(" . POSTGRESQL_NEXTID_LOCK . ")");
+
+ // While waiting to obtain the lock, the sequence may have been altered
+ // so lets try again to obtain an adequate value.
+ $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
+ if ($id > $existing) {
+ $this->query("SELECT pg_advisory_unlock(" . POSTGRESQL_NEXTID_LOCK . ")");
+ return $id;
+ }
+
+ // Reset the sequence to a higher value than the existing id.
+ $this->query("ALTER SEQUENCE " . $sequence_name . " RESTART WITH " . ($existing + 1));
+
+ // Retrive the next id. We know this will be as high as we want it.
+ $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
+
+ $this->query("SELECT pg_advisory_unlock(" . POSTGRESQL_NEXTID_LOCK . ")");
+
+ return $id;
+ }
}
/**