diff options
author | Angie Byron <webchick@24967.no-reply.drupal.org> | 2010-01-07 04:51:26 +0000 |
---|---|---|
committer | Angie Byron <webchick@24967.no-reply.drupal.org> | 2010-01-07 04:51:26 +0000 |
commit | 37fcdbc67cd5591107c93016d1d3bb109be5e9e6 (patch) | |
tree | 9f0ffd5a6d54456e97e53b57f3de29b0966a4bbc /includes/database/pgsql/database.inc | |
parent | 39f4d7245c0cb5e258b0ca6ec7fd31df6699408d (diff) | |
download | brdo-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.inc | 48 |
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; + } } /** |