diff --git a/.travis.yml b/.travis.yml index d76e949..4de4509 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,23 @@ language: php +dist: precise + sudo: false matrix: include: - php: 5.3 env: DB=POSTGRESQL CORE_RELEASE=3.4 + - php: 5.4 + env: DB=POSTGRESQL CORE_RELEASE=3.5 + - php: 5.5 + env: DB=POSTGRESQL CORE_RELEASE=3.6 - php: 5.6 env: DB=POSTGRESQL CORE_RELEASE=3 - php: 7.0 env: DB=POSTGRESQL CORE_RELEASE=3 + - php: 7.1 + env: DB=POSTGRESQL CORE_RELEASE=3 before_script: - composer self-update || true @@ -19,4 +27,4 @@ before_script: - cd ~/builds/ss script: - - vendor/bin/phpunit framework/tests + - vendor/bin/phpunit framework/tests diff --git a/code/PostgreSQLDatabase.php b/code/PostgreSQLDatabase.php index e6b247a..b5a2508 100644 --- a/code/PostgreSQLDatabase.php +++ b/code/PostgreSQLDatabase.php @@ -2,7 +2,7 @@ /** * PostgreSQL connector class. - * + * * @package sapphire * @subpackage model */ @@ -10,14 +10,14 @@ class PostgreSQLDatabase extends SS_Database { /** * Database schema manager object - * + * * @var PostgreSQLSchemaManager */ protected $schemaManager; /** * The currently selected database schema name. - * + * * @var string */ protected $schema; @@ -30,7 +30,7 @@ class PostgreSQLDatabase extends SS_Database { /** * Full text cluster method. (e.g. GIN or GiST) - * + * * @return string */ public static function default_fts_cluster_method() { @@ -39,7 +39,7 @@ class PostgreSQLDatabase extends SS_Database { /** * Full text search method. - * + * * @return string */ public static function default_fts_search_method() { @@ -53,7 +53,7 @@ class PostgreSQLDatabase extends SS_Database { * Some locked down systems prevent access to the 'postgres' table in * which case you need to set this to false. * - * If allow_query_master_postgres is false, and model_schema_as_database is also false, + * If allow_query_master_postgres is false, and model_schema_as_database is also false, * then attempts to create or check databases beyond the initial connection will * result in a runtime error. */ @@ -67,7 +67,7 @@ class PostgreSQLDatabase extends SS_Database { * instead of using databases. This may be useful if the database user does not * have cross-database permissions, and in cases where multiple databases are used * (such as in running test cases). - * + * * If this is true then the database will only be set during the initial connection, * and attempts to change to this database will use the 'public' schema instead */ @@ -88,7 +88,7 @@ class PostgreSQLDatabase extends SS_Database { /** * The database name specified at initial connection - * + * * @var string */ protected $databaseOriginal = ''; @@ -149,7 +149,7 @@ class PostgreSQLDatabase extends SS_Database { } } - // Connect to the actual database we're requesting + // Connect to the actual database we 're requesting $this->connectDefault(); // Set up the schema if required @@ -175,7 +175,7 @@ class PostgreSQLDatabase extends SS_Database { /** * Sets the system timezone for the database connection - * + * * @param string $timezone */ public function selectTimezone($timezone) { @@ -197,7 +197,7 @@ class PostgreSQLDatabase extends SS_Database { /** * Returns the name of the current schema in use - * + * * @return string Name of current schema */ public function currentSchema() { @@ -207,7 +207,7 @@ class PostgreSQLDatabase extends SS_Database { /** * Utility method to manually set the schema to an alternative * Check existance & sets search path to the supplied schema name - * + * * @param string $name Name of the schema * @param boolean $create Flag indicating whether the schema should be created * if it doesn't exist. If $create is false and the schema doesn't exist @@ -240,7 +240,7 @@ class PostgreSQLDatabase extends SS_Database { * the search path is provided as an advanced PostgreSQL feature for raw * SQL queries. Sapphire cannot search for datamodel tables in alternate * schemas, so be wary of using alternate schemas within the ORM environment. - * + * * @param string $arg1 First schema to use * @param string $arg2 Second schema to use * @param string $argN Nth schema to use @@ -354,12 +354,14 @@ class PostgreSQLDatabase extends SS_Database { $fullQuery = "SELECT * FROM (" . implode(" UNION ", $tables) . ") AS q1 $orderBy LIMIT $limit OFFSET $offset"; + // Get the total items in this search + $totalItemsQuery = "SELECT COUNT(*) AS totalitems FROM (" . implode(" UNION ", $tables) . ") AS q1"; + $totalCount = DB::query($totalItemsQuery); + // Get records $records = $this->preparedQuery($fullQuery, $tableParameters); - $totalCount=0; foreach($records as $record){ $objects[] = new $record['ClassName']($record); - $totalCount++; } if(isset($objects)) $results = new ArrayList($objects); @@ -368,7 +370,7 @@ class PostgreSQLDatabase extends SS_Database { $list->setLimitItems(false); $list->setPageStart($start); $list->setPageLength($pageLength); - $list->setTotalItems($totalCount); + $list->setTotalItems($totalCount->value()); return $list; } @@ -414,6 +416,7 @@ class PostgreSQLDatabase extends SS_Database { $this->query('COMMIT;'); } + public function comparisonClause($field, $value, $exact = false, $negate = false, $caseSensitive = null, $parameterised = false) { if($exact && $caseSensitive === null) { $comp = ($negate) ? '!=' : '='; @@ -422,12 +425,10 @@ class PostgreSQLDatabase extends SS_Database { if($negate) $comp = 'NOT ' . $comp; $field.='::text'; } - if($parameterised) { return sprintf("%s %s ?", $field, $comp); } else { - return sprintf("%s %s '%s'", $field, $comp, $value); - } + return sprintf("%s %s '%s'", $field, $comp, $value);} } /** @@ -536,7 +537,7 @@ class PostgreSQLDatabase extends SS_Database { * Determines the name of the current database to be reported externally * by substituting the schema name for the database name. * Should only be used when model_schema_as_database is true - * + * * @param string $schema Name of the schema * @return string Name of the database to report */ @@ -550,7 +551,7 @@ class PostgreSQLDatabase extends SS_Database { /** * Translates a requested database name to a schema name to substitute internally. * Should only be used when model_schema_as_database is true - * + * * @param string $database Name of the database * @return string Name of the schema to use for this database internally */ diff --git a/code/PostgreSQLSchemaManager.php b/code/PostgreSQLSchemaManager.php index b737c30..f52f8a5 100644 --- a/code/PostgreSQLSchemaManager.php +++ b/code/PostgreSQLSchemaManager.php @@ -464,7 +464,8 @@ class PostgreSQLSchemaManager extends DBSchemaManager { } // SET check constraint (The constraint HAS to be dropped) - $existing_constraint=$this->query("SELECT conname FROM pg_constraint WHERE conname='{$tableName}_{$colName}_check';")->value(); + $constraint_name = "{$tableName}_{$colName}_check"; + $existing_constraint = $this->constraintExists($constraint_name, false); if(isset($matches[4])) { //Take this new constraint and see what's outstanding from the target table: $constraint_bits=explode('(', $matches[4]); @@ -488,12 +489,12 @@ class PostgreSQLSchemaManager extends DBSchemaManager { //First, delete any existing constraint on this column, even if it's no longer an enum if($existing_constraint) { - $alterCol .= ",\nDROP CONSTRAINT \"{$tableName}_{$colName}_check\""; + $alterCol .= ",\nDROP CONSTRAINT \"{$constraint_name}\""; } //Now create the constraint (if we've asked for one) if(!empty($matches[4])) { - $alterCol .= ",\nADD CONSTRAINT \"{$tableName}_{$colName}_check\" $matches[4]"; + $alterCol .= ",\nADD CONSTRAINT \"{$constraint_name}\" $matches[4]"; } } @@ -873,15 +874,25 @@ class PostgreSQLSchemaManager extends DBSchemaManager { * query all over again. * * @param string $constraint + * @param bool $cache Flag whether a cached version should be used. Set to false to cache bust. + * @return false|array Either false, if the constraint doesn't exist, or an array + * with the keys conname and pg_get_constraintdef */ - protected function constraintExists($constraint){ - if(!isset(self::$cached_constraints[$constraint])){ - $exists = $this->preparedQuery(" + protected function constraintExists($constraint, $cache = true){ + if(!$cache || !isset(self::$cached_constraints[$constraint])){ + $value = $this->preparedQuery(" SELECT conname,pg_catalog.pg_get_constraintdef(r.oid, true) - FROM pg_catalog.pg_constraint r WHERE r.contype = 'c' AND conname = ? ORDER BY 1;", - array($constraint) + FROM pg_catalog.pg_constraint r + INNER JOIN pg_catalog.pg_namespace n + ON r.connamespace = n.oid + WHERE r.contype = 'c' AND conname = ? AND n.nspname = ? + ORDER BY 1;", + array($constraint, $this->database->currentSchema()) )->first(); - self::$cached_constraints[$constraint]=$exists; + if (!$cache) { + return $value; + } + self::$cached_constraints[$constraint] = $value; } return self::$cached_constraints[$constraint]; @@ -903,10 +914,13 @@ class PostgreSQLSchemaManager extends DBSchemaManager { WHERE c.relname = ? AND pg_catalog.pg_table_is_visible(c.oid) AND n.nspname = ? );"; - $result = $this->preparedQuery($query, $tableName, $this->database->currentSchema()); + $result = $this->preparedQuery( + $query, + array($tableName, $this->database->currentSchema()) + ); $table = array(); - while($row = pg_fetch_assoc($result)) { + foreach ($result as $row) { $table[] = array( 'Column' => $row['Column'], 'DataType' => $row['DataType'] @@ -1388,12 +1402,10 @@ class PostgreSQLSchemaManager extends DBSchemaManager { $this->query("CREATE TABLE \"$partition_name\" (CHECK (" . str_replace('NEW.', '', $partition_value) . ")) INHERITS (\"$tableName\")$tableSpace;"); } else { //Drop the constraint, we will recreate in in the next line - $existing_constraint = $this->preparedQuery( - "SELECT conname FROM pg_constraint WHERE conname = ?;", - array("{$partition_name}_pkey") - ); + $constraint_name = "{$partition_name}_pkey"; + $existing_constraint = $this->constraintExists($constraint_name, false); if($existing_constraint){ - $this->query("ALTER TABLE \"$partition_name\" DROP CONSTRAINT \"{$partition_name}_pkey\";"); + $this->query("ALTER TABLE \"$partition_name\" DROP CONSTRAINT \"{$constraint_name}\";"); } $this->dropTrigger(strtolower('trigger_' . $tableName . '_insert'), $tableName); } diff --git a/composer.json b/composer.json index dedd130..879ed59 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "silverstripe/framework": "^3.2.0" + "silverstripe/framework": "^3.2" }, "extra": { "branch-alias": {