mirror of
https://github.com/silverstripe/silverstripe-postgresql
synced 2024-10-01 13:48:23 +02:00
MINOR: transaction functions renamed for consistency, field list lookups now cached for speed improvements
This commit is contained in:
parent
99f2cb179e
commit
2bd6e9fb8e
@ -88,6 +88,15 @@ class PostgreSQLDatabase extends SS_Database {
|
|||||||
*/
|
*/
|
||||||
private static $cached_ordered_specifically=array();
|
private static $cached_ordered_specifically=array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This holds a copy of all the queries that run through the function fieldList()
|
||||||
|
* This is one of the most-often called functions, and repeats itself a great deal in the unit tests.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $cached_fieldlists=array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override the language that tsearch uses. By default it is 'english, but
|
* Override the language that tsearch uses. By default it is 'english, but
|
||||||
* could be any of the supported languages that can be found in the
|
* could be any of the supported languages that can be found in the
|
||||||
@ -278,7 +287,7 @@ class PostgreSQLDatabase extends SS_Database {
|
|||||||
$this->selectDatabase($this->database_original);
|
$this->selectDatabase($this->database_original);
|
||||||
$this->connectDatabase();
|
$this->connectDatabase();
|
||||||
|
|
||||||
$this->query("DROP DATABASE $db_to_drop");
|
$this->query("DROP DATABASE \"$db_to_drop\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -647,6 +656,7 @@ class PostgreSQLDatabase extends SS_Database {
|
|||||||
// First, we split the column specifications into parts
|
// First, we split the column specifications into parts
|
||||||
// TODO: this returns an empty array for the following string: int(11) not null auto_increment
|
// TODO: this returns an empty array for the following string: int(11) not null auto_increment
|
||||||
// on second thoughts, why is an auto_increment field being passed through?
|
// on second thoughts, why is an auto_increment field being passed through?
|
||||||
|
|
||||||
$pattern = '/^([\w()]+)\s?((?:not\s)?null)?\s?(default\s[\w\']+)?\s?(check\s[\w()\'",\s]+)?$/i';
|
$pattern = '/^([\w()]+)\s?((?:not\s)?null)?\s?(default\s[\w\']+)?\s?(check\s[\w()\'",\s]+)?$/i';
|
||||||
preg_match($pattern, $colSpec, $matches);
|
preg_match($pattern, $colSpec, $matches);
|
||||||
|
|
||||||
@ -757,88 +767,92 @@ class PostgreSQLDatabase extends SS_Database {
|
|||||||
public function fieldList($table) {
|
public function fieldList($table) {
|
||||||
//Query from http://www.alberton.info/postgresql_meta_info.html
|
//Query from http://www.alberton.info/postgresql_meta_info.html
|
||||||
//This gets us more information than we need, but I've included it all for the moment....
|
//This gets us more information than we need, but I've included it all for the moment....
|
||||||
$fields = $this->query("SELECT ordinal_position, column_name, data_type, column_default, is_nullable, character_maximum_length, numeric_precision, numeric_scale FROM information_schema.columns WHERE table_name = '$table' ORDER BY ordinal_position;");
|
|
||||||
|
|
||||||
$output = array();
|
if(!isset(self::$cached_fieldlists[$table])){
|
||||||
if($fields) foreach($fields as $field) {
|
$fields = $this->query("SELECT ordinal_position, column_name, data_type, column_default, is_nullable, character_maximum_length, numeric_precision, numeric_scale FROM information_schema.columns WHERE table_name = '$table' ORDER BY ordinal_position;");
|
||||||
|
|
||||||
switch($field['data_type']){
|
$output = array();
|
||||||
case 'character varying':
|
if($fields) foreach($fields as $field) {
|
||||||
//Check to see if there's a constraint attached to this column:
|
|
||||||
//$constraint=$this->query("SELECT conname,pg_catalog.pg_get_constraintdef(r.oid, true) FROM pg_catalog.pg_constraint r WHERE r.contype = 'c' AND conname='" . $table . '_' . $field['column_name'] . "_check' ORDER BY 1;")->first();
|
|
||||||
$constraint=$this->constraintExists($table . '_' . $field['column_name'] . '_check');
|
|
||||||
$enum='';
|
|
||||||
if($constraint){
|
|
||||||
//Now we need to break this constraint text into bits so we can see what we have:
|
|
||||||
//Examples:
|
|
||||||
//CHECK ("CanEditType"::text = ANY (ARRAY['LoggedInUsers'::character varying, 'OnlyTheseUsers'::character varying, 'Inherit'::character varying]::text[]))
|
|
||||||
//CHECK ("ClassName"::text = 'PageComment'::text)
|
|
||||||
|
|
||||||
//TODO: replace all this with a regular expression!
|
switch($field['data_type']){
|
||||||
$value=$constraint['pg_get_constraintdef'];
|
case 'character varying':
|
||||||
$value=substr($value, strpos($value,'='));
|
//Check to see if there's a constraint attached to this column:
|
||||||
$value=str_replace("''", "'", $value);
|
//$constraint=$this->query("SELECT conname,pg_catalog.pg_get_constraintdef(r.oid, true) FROM pg_catalog.pg_constraint r WHERE r.contype = 'c' AND conname='" . $table . '_' . $field['column_name'] . "_check' ORDER BY 1;")->first();
|
||||||
|
$constraint=$this->constraintExists($table . '_' . $field['column_name'] . '_check');
|
||||||
|
$enum='';
|
||||||
|
if($constraint){
|
||||||
|
//Now we need to break this constraint text into bits so we can see what we have:
|
||||||
|
//Examples:
|
||||||
|
//CHECK ("CanEditType"::text = ANY (ARRAY['LoggedInUsers'::character varying, 'OnlyTheseUsers'::character varying, 'Inherit'::character varying]::text[]))
|
||||||
|
//CHECK ("ClassName"::text = 'PageComment'::text)
|
||||||
|
|
||||||
$in_value=false;
|
//TODO: replace all this with a regular expression!
|
||||||
$constraints=Array();
|
$value=$constraint['pg_get_constraintdef'];
|
||||||
$current_value='';
|
$value=substr($value, strpos($value,'='));
|
||||||
for($i=0; $i<strlen($value); $i++){
|
$value=str_replace("''", "'", $value);
|
||||||
$char=substr($value, $i, 1);
|
|
||||||
if($in_value)
|
|
||||||
$current_value.=$char;
|
|
||||||
|
|
||||||
if($char=="'"){
|
$in_value=false;
|
||||||
if(!$in_value)
|
$constraints=Array();
|
||||||
$in_value=true;
|
$current_value='';
|
||||||
else {
|
for($i=0; $i<strlen($value); $i++){
|
||||||
$in_value=false;
|
$char=substr($value, $i, 1);
|
||||||
$constraints[]=substr($current_value, 0, -1);
|
if($in_value)
|
||||||
$current_value='';
|
$current_value.=$char;
|
||||||
|
|
||||||
|
if($char=="'"){
|
||||||
|
if(!$in_value)
|
||||||
|
$in_value=true;
|
||||||
|
else {
|
||||||
|
$in_value=false;
|
||||||
|
$constraints[]=substr($current_value, 0, -1);
|
||||||
|
$current_value='';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(sizeof($constraints)>0){
|
||||||
|
//Get the default:
|
||||||
|
$default=trim(substr($field['column_default'], 0, strpos($field['column_default'], '::')), "'");
|
||||||
|
$output[$field['column_name']]=$this->enum(Array('default'=>$default, 'name'=>$field['column_name'], 'enums'=>$constraints));
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
$output[$field['column_name']]='varchar(' . $field['character_maximum_length'] . ')';
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
if(sizeof($constraints)>0){
|
case 'numeric':
|
||||||
//Get the default:
|
$output[$field['column_name']]='decimal(' . $field['numeric_precision'] . ',' . $field['numeric_scale'] . ') default ' . (int)$field['column_default'];
|
||||||
$default=trim(substr($field['column_default'], 0, strpos($field['column_default'], '::')), "'");
|
break;
|
||||||
$output[$field['column_name']]=$this->enum(Array('default'=>$default, 'name'=>$field['column_name'], 'enums'=>$constraints));
|
|
||||||
}
|
|
||||||
} else{
|
|
||||||
$output[$field['column_name']]='varchar(' . $field['character_maximum_length'] . ')';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'numeric':
|
case 'integer':
|
||||||
$output[$field['column_name']]='decimal(' . $field['numeric_precision'] . ',' . $field['numeric_scale'] . ') default ' . (int)$field['column_default'];
|
$output[$field['column_name']]='integer default ' . (int)$field['column_default'];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'integer':
|
case 'timestamp without time zone':
|
||||||
$output[$field['column_name']]='integer default ' . (int)$field['column_default'];
|
$output[$field['column_name']]='timestamp';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'timestamp without time zone':
|
case 'smallint':
|
||||||
$output[$field['column_name']]='timestamp';
|
$output[$field['column_name']]='smallint default ' . (int)$field['column_default'];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'smallint':
|
case 'time without time zone':
|
||||||
$output[$field['column_name']]='smallint default ' . (int)$field['column_default'];
|
$output[$field['column_name']]='time';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'time without time zone':
|
case 'double precision':
|
||||||
$output[$field['column_name']]='time';
|
$output[$field['column_name']]='float';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'double precision':
|
default:
|
||||||
$output[$field['column_name']]='float';
|
$output[$field['column_name']] = $field;
|
||||||
break;
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
$output[$field['column_name']] = $field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self::$cached_fieldlists[$table]=$output;
|
||||||
}
|
}
|
||||||
|
return self::$cached_fieldlists[$table];
|
||||||
return $output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1059,14 +1073,15 @@ class PostgreSQLDatabase extends SS_Database {
|
|||||||
*/
|
*/
|
||||||
public function tableList() {
|
public function tableList() {
|
||||||
$schema_SQL = pg_escape_string($this->dbConn, $this->schema);
|
$schema_SQL = pg_escape_string($this->dbConn, $this->schema);
|
||||||
foreach($this->query("SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = '{$schema_SQL}' AND tablename NOT ILIKE 'pg_%' AND tablename NOT ILIKE 'sql_%'") as $record) {
|
$tables=array();
|
||||||
|
foreach($this->query("SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = '{$schema_SQL}' AND tablename NOT ILIKE 'pg_%' AND tablename NOT ILIKE 'sql_%'") as $record) {
|
||||||
//$table = strtolower(reset($record));
|
//$table = strtolower(reset($record));
|
||||||
$table = reset($record);
|
$table = reset($record);
|
||||||
$tables[$table] = $table;
|
$tables[$table] = $table;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Return an empty array if there's nothing in this database
|
//Return an empty array if there's nothing in this database
|
||||||
return isset($tables) ? $tables : Array();
|
return $tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableExists($tableName){
|
function TableExists($tableName){
|
||||||
@ -1375,8 +1390,9 @@ class PostgreSQLDatabase extends SS_Database {
|
|||||||
|
|
||||||
//TODO: the DbValue result does not include the numeric_scale option (ie, the ,0 value in 4,0)
|
//TODO: the DbValue result does not include the numeric_scale option (ie, the ,0 value in 4,0)
|
||||||
if($asDbValue)
|
if($asDbValue)
|
||||||
return Array('data_type'=>'decimal', 'precision'=>'4', 'default'=> (int)$values['default']);
|
return Array('data_type'=>'decimal', 'precision'=>'4');
|
||||||
else return "decimal(4,0){$values['arrayValue']}";
|
else
|
||||||
|
return "decimal(4,0){$values['arrayValue']}";
|
||||||
}
|
}
|
||||||
|
|
||||||
function escape_character($escape=false){
|
function escape_character($escape=false){
|
||||||
@ -1712,7 +1728,7 @@ class PostgreSQLDatabase extends SS_Database {
|
|||||||
* Start a prepared transaction
|
* Start a prepared transaction
|
||||||
* See http://developer.postgresql.org/pgdocs/postgres/sql-set-transaction.html for details on transaction isolation options
|
* See http://developer.postgresql.org/pgdocs/postgres/sql-set-transaction.html for details on transaction isolation options
|
||||||
*/
|
*/
|
||||||
public function startTransaction($transaction_mode=false, $session_characteristics=false){
|
public function transactionStart($transaction_mode=false, $session_characteristics=false){
|
||||||
DB::query('BEGIN;');
|
DB::query('BEGIN;');
|
||||||
|
|
||||||
if($transaction_mode)
|
if($transaction_mode)
|
||||||
@ -1745,7 +1761,7 @@ class PostgreSQLDatabase extends SS_Database {
|
|||||||
/*
|
/*
|
||||||
* Commit everything inside this transaction so far
|
* Commit everything inside this transaction so far
|
||||||
*/
|
*/
|
||||||
public function endTransaction(){
|
public function transactionEnd(){
|
||||||
DB::query('COMMIT;');
|
DB::query('COMMIT;');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user