Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix bugs on postgresql dialect #10375

Merged
merged 6 commits into from May 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions phalcon/db/adapter.zep
Expand Up @@ -20,6 +20,7 @@
namespace Phalcon\Db;

use Phalcon\Db;
use Phalcon\Db\ColumnInterface;
use Phalcon\Events\EventsAwareInterface;
use Phalcon\Events\ManagerInterface;

Expand Down
74 changes: 74 additions & 0 deletions phalcon/db/adapter/pdo/postgresql.zep
Expand Up @@ -24,6 +24,7 @@ use Phalcon\Db\Column;
use Phalcon\Db\AdapterInterface;
use Phalcon\Db\RawValue;
use Phalcon\Db\Adapter\Pdo as PdoAdapter;
use Phalcon\Db\Exception;

/**
* Phalcon\Db\Adapter\Pdo\Postgresql
Expand Down Expand Up @@ -290,6 +291,79 @@ class Postgresql extends PdoAdapter implements AdapterInterface

return columns;
}

/**
* Creates a table
*/
public function createTable(string! tableName, string! schemaName, array! definition) -> boolean
{
var sql,queries,query,exception,columns;

if !fetch columns, definition["columns"] {
throw new Exception("The table must contain at least one column");
}

if !count(columns) {
throw new Exception("The table must contain at least one column");
}

let sql = this->_dialect->createTable(tableName, schemaName, definition);

let queries = explode(";",sql);

if count(queries) > 1 {
try {
this->{"begin"}();
for query in queries {
if empty query {
continue;
}
this->{"query"}(query . ";");
}
return this->{"commit"}();
} catch \Exception, exception {

this->{"rollback"}();
throw exception;
}

} else {
return this->{"execute"}(queries[0] . ";");
}
return true;
}

/**
* Modifies a table column based on a definition
*/
public function modifyColumn(string! tableName, string! schemaName, <\Phalcon\Db\ColumnInterface> column, <\Phalcon\Db\ColumnInterface> currentColumn = null) -> boolean
{
var sql,queries,query,exception;

let sql = this->_dialect->modifyColumn(tableName, schemaName, column, currentColumn);
let queries = explode(";",sql);

if count(queries) > 1 {
try {
this->{"begin"}();
for query in queries {
if empty query {
continue;
}
this->{"query"}(query . ";");
}
return this->{"commit"}();
} catch \Exception, exception {

this->{"rollback"}();
throw exception;
}

} else {
return !empty sql ? this->{"execute"}(queries[0] . ";") : true;
}
return true;
}

/**
* Check whether the database system requires an explicit value for identity columns
Expand Down
59 changes: 38 additions & 21 deletions phalcon/db/dialect/postgresql.zep
Expand Up @@ -57,7 +57,11 @@ class Postgresql extends Dialect

case Column::TYPE_INTEGER:
if empty columnSql {
let columnSql .= "INT";
if column->isAutoIncrement() {
let columnSql .= "SERIAL";
} else {
let columnSql .= "INT";
}
}
break;

Expand Down Expand Up @@ -189,7 +193,6 @@ class Postgresql extends Dialect
let sql .= sqlAlterTable . " ALTER COLUMN \"" . column->getName() . "\" SET NOT NULL;";
} else {
let sql .= sqlAlterTable . " ALTER COLUMN \"" . column->getName() . "\" DROP NOT NULL;";
let sql .= sqlAlterTable . " ALTER COLUMN \"" . column->getName() . "\" SET NULL;";
}
}
//DEFAULT
Expand Down Expand Up @@ -274,7 +277,7 @@ class Postgresql extends Dialect
} else {
let sql = "ALTER TABLE \"" . tableName . "\"";
}
let sql .= " ADD CONSTRAINT \"pk\" PRIMARY KEY (" . this->getColumnList(index->getColumns()) . ")";
let sql .= " ADD CONSTRAINT \"PRIMARY\" PRIMARY KEY (" . this->getColumnList(index->getColumns()) . ")";

return sql;
}
Expand All @@ -291,7 +294,7 @@ class Postgresql extends Dialect
} else {
let sql = "ALTER TABLE \"" . tableName . "\"";
}
let sql .= " DROP CONSTRAINT \"pk\"";
let sql .= " DROP CONSTRAINT \"PRIMARY\"";

return sql;
}
Expand All @@ -304,9 +307,9 @@ class Postgresql extends Dialect
var sql, onDelete, onUpdate;

if schemaName {
let sql = "ALTER TABLE \"" . schemaName . "\".\"" . tableName . "\" ADD FOREIGN KEY ";
let sql = "ALTER TABLE \"" . schemaName . "\".\"" . tableName . "\" ";
} else {
let sql = "ALTER TABLE \"" . tableName . "\" ADD FOREIGN KEY ";
let sql = "ALTER TABLE \"" . tableName . "\" ";
}
let sql .= "ADD CONSTRAINT \"" . reference->getName() . "\" FOREIGN KEY (" . this->getColumnList(reference->getColumns()) . ")"
. " REFERENCES \"" . reference->getReferencedTable() . "\" (" . this->getColumnList(reference->getReferencedColumns()) . ")";
Expand Down Expand Up @@ -345,21 +348,21 @@ class Postgresql extends Dialect
/**
* Generates SQL to create a table
*/
public function createTable(string! tableName, string! schemaName, array! definition) -> string
public function createTable(string! tableName, string! schemaName, array! definition) -> string | array
{
var temporary, options, table, createLines, columns,
column, indexes, index, reference, references, indexName,
indexSql, indexSqlAfterCreate, sql, columnLine, indexType,
referenceSql, onDelete, onUpdate, defaultValue;
referenceSql, onDelete, onUpdate, defaultValue, primaryColumns;

if !fetch columns, definition["columns"] {
throw new Exception("The index 'columns' is required in the definition array");
}

if schemaName {
let table = schemaName . "." . tableName;
let table = "\"" . schemaName . "\".\"" . tableName . "\"";
} else {
let table = tableName;
let table = "\"" . tableName . "\"";
}

let temporary = false;
Expand All @@ -371,12 +374,13 @@ class Postgresql extends Dialect
* Create a temporary o normal table
*/
if temporary {
let sql = "CREATE TEMPORARY TABLE \"" . table . "\" (\n\t";
let sql = "CREATE TEMPORARY TABLE " . table . " (\n\t";
} else {
let sql = "CREATE TABLE \"" . table . "\" (\n\t";
let sql = "CREATE TABLE " . table . " (\n\t";
}

let createLines = [];
let primaryColumns = [];
for column in columns {

let columnLine = "\"" . column->getName() . "\" " . this->getColumnDefinition(column);
Expand Down Expand Up @@ -407,11 +411,14 @@ class Postgresql extends Dialect
* Mark the column as primary key
*/
if column->isPrimary() {
let columnLine .= " PRIMARY KEY";
let primaryColumns[] = column->getName() ;
}

let createLines[] = columnLine;
}
if !empty primaryColumns {
let createLines[] = "PRIMARY KEY (" . implode(",",primaryColumns) . ")";
}

/**
* Create related indexes
Expand All @@ -420,15 +427,16 @@ class Postgresql extends Dialect
if fetch indexes, definition["indexes"] {

for index in indexes {

let indexName = index->getName();
let indexType = index->getType();

let indexSql = "";

/**
* If the index name is primary we add a primary key
*/
if indexName == "PRIMARY" {
let indexSql = "CONSTRAINT pk PRIMARY KEY (" . this->getColumnList(index->getColumns()) . ")";
let indexSql = "CONSTRAINT \"PRIMARY\" PRIMARY KEY (" . this->getColumnList(index->getColumns()) . ")";
} else {
if !empty indexType {
let indexSql = "CONSTRAINT \"" . indexName . "\" " . indexType . " (" . this->getColumnList(index->getColumns()) . ")";
Expand All @@ -445,17 +453,26 @@ class Postgresql extends Dialect
let indexSqlAfterCreate .= " (" . this->getColumnList(index->getColumns()) . ");";
}
}

let createLines[] = indexSql;
if !empty indexSql {
let createLines[] = indexSql;
}
}
}
/**
* Create related references
*/
if fetch references, definition["references"] {
for reference in references {
let referenceSql = "CONSTRAINT \"" . reference->getName() . "\" FOREIGN KEY (" . this->getColumnList(reference->getColumns()) . ")"
. " REFERENCES \"" . reference->getReferencedTable() . "\" (" . this->getColumnList(reference->getReferencedColumns()) . ")";

let referenceSql = "CONSTRAINT \"" . reference->getName() . "\" FOREIGN KEY (" . this->getColumnList(reference->getColumns()) . ") REFERENCES ";

if schemaName {
let referenceSql .= "\"" . schemaName . "\".\"" . reference->getReferencedTable() . "\" ";
} else {
let referenceSql .= "\"" . reference->getReferencedTable() . "\" ";
}

let referenceSql .= "(" . this->getColumnList(reference->getReferencedColumns()) . ")";

let onDelete = reference->getOnDelete();
if !empty onDelete {
Expand All @@ -466,7 +483,7 @@ class Postgresql extends Dialect
if !empty onUpdate {
let referenceSql .= " ON UPDATE " . onUpdate;
}

let createLines[] = referenceSql;
}
}
Expand Down
38 changes: 19 additions & 19 deletions unit-tests/DbDialectTest.php
Expand Up @@ -659,8 +659,8 @@ public function testPostgresqlDialect()
$this->assertEquals($dialect->addIndex('table', 'schema', $indexes['index1']), 'CREATE INDEX "index1" ON "schema"."table" ("column1")');
$this->assertEquals($dialect->addIndex('table', null, $indexes['index2']), 'CREATE INDEX "index2" ON "table" ("column1", "column2")');
$this->assertEquals($dialect->addIndex('table', 'schema', $indexes['index2']), 'CREATE INDEX "index2" ON "schema"."table" ("column1", "column2")');
$this->assertEquals($dialect->addIndex('table', null, $indexes['PRIMARY']), 'ALTER TABLE "table" ADD CONSTRAINT "pk" PRIMARY KEY ("column3")');
$this->assertEquals($dialect->addIndex('table', 'schema', $indexes['PRIMARY']), 'ALTER TABLE "schema"."table" ADD CONSTRAINT "pk" PRIMARY KEY ("column3")');
$this->assertEquals($dialect->addIndex('table', null, $indexes['PRIMARY']), 'ALTER TABLE "table" ADD CONSTRAINT "PRIMARY" PRIMARY KEY ("column3")');
$this->assertEquals($dialect->addIndex('table', 'schema', $indexes['PRIMARY']), 'ALTER TABLE "schema"."table" ADD CONSTRAINT "PRIMARY" PRIMARY KEY ("column3")');
$this->assertEquals($dialect->addIndex('table', null, $indexes['index4']), 'CREATE UNIQUE INDEX "index4" ON "table" ("column4")');
$this->assertEquals($dialect->addIndex('table', 'schema', $indexes['index4']), 'CREATE UNIQUE INDEX "index4" ON "schema"."table" ("column4")');

Expand All @@ -669,27 +669,27 @@ public function testPostgresqlDialect()
$this->assertEquals($dialect->dropIndex('table', 'schema', 'index1'), 'DROP INDEX "index1"');

//Add Primary
$this->assertEquals($dialect->addPrimaryKey('table', null, $indexes['PRIMARY']), 'ALTER TABLE "table" ADD CONSTRAINT "pk" PRIMARY KEY ("column3")');
$this->assertEquals($dialect->addPrimaryKey('table', 'schema', $indexes['PRIMARY']), 'ALTER TABLE "schema"."table" ADD CONSTRAINT "pk" PRIMARY KEY ("column3")');
$this->assertEquals($dialect->addPrimaryKey('table', null, $indexes['PRIMARY']), 'ALTER TABLE "table" ADD CONSTRAINT "PRIMARY" PRIMARY KEY ("column3")');
$this->assertEquals($dialect->addPrimaryKey('table', 'schema', $indexes['PRIMARY']), 'ALTER TABLE "schema"."table" ADD CONSTRAINT "PRIMARY" PRIMARY KEY ("column3")');

//Drop Primary Key
$this->assertEquals($dialect->dropPrimaryKey('table', null), 'ALTER TABLE "table" DROP CONSTRAINT "pk"');
$this->assertEquals($dialect->dropPrimaryKey('table', 'schema'), 'ALTER TABLE "schema"."table" DROP CONSTRAINT "pk"');
$this->assertEquals($dialect->dropPrimaryKey('table', null), 'ALTER TABLE "table" DROP CONSTRAINT "PRIMARY"');
$this->assertEquals($dialect->dropPrimaryKey('table', 'schema'), 'ALTER TABLE "schema"."table" DROP CONSTRAINT "PRIMARY"');

$references = $this->getReferences();

//Add Foreign Key
$this->assertEquals($dialect->addForeignKey('table', null, $references['fk1']), 'ALTER TABLE "table" ADD FOREIGN KEY ADD CONSTRAINT "fk1" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2")');
$this->assertEquals($dialect->addForeignKey('table', 'schema', $references['fk1']), 'ALTER TABLE "schema"."table" ADD FOREIGN KEY ADD CONSTRAINT "fk1" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2")');
$this->assertEquals($dialect->addForeignKey('table', null, $references['fk2']), 'ALTER TABLE "table" ADD FOREIGN KEY ADD CONSTRAINT "fk2" FOREIGN KEY ("column3", "column4") REFERENCES "ref_table" ("column5", "column6")');
$this->assertEquals($dialect->addForeignKey('table', 'schema', $references['fk2']), 'ALTER TABLE "schema"."table" ADD FOREIGN KEY ADD CONSTRAINT "fk2" FOREIGN KEY ("column3", "column4") REFERENCES "ref_table" ("column5", "column6")');

$this->assertEquals($dialect->addForeignKey('table', null, $references['fk3']), 'ALTER TABLE "table" ADD FOREIGN KEY ADD CONSTRAINT "fk3" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON DELETE CASCADE');
$this->assertEquals($dialect->addForeignKey('table', 'schema', $references['fk3']), 'ALTER TABLE "schema"."table" ADD FOREIGN KEY ADD CONSTRAINT "fk3" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON DELETE CASCADE');
$this->assertEquals($dialect->addForeignKey('table', null, $references['fk4']), 'ALTER TABLE "table" ADD FOREIGN KEY ADD CONSTRAINT "fk4" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON UPDATE SET NULL');
$this->assertEquals($dialect->addForeignKey('table', 'schema', $references['fk4']), 'ALTER TABLE "schema"."table" ADD FOREIGN KEY ADD CONSTRAINT "fk4" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON UPDATE SET NULL');
$this->assertEquals($dialect->addForeignKey('table', null, $references['fk5']), 'ALTER TABLE "table" ADD FOREIGN KEY ADD CONSTRAINT "fk5" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON DELETE CASCADE ON UPDATE NO ACTION');
$this->assertEquals($dialect->addForeignKey('table', 'schema', $references['fk5']), 'ALTER TABLE "schema"."table" ADD FOREIGN KEY ADD CONSTRAINT "fk5" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON DELETE CASCADE ON UPDATE NO ACTION');
$this->assertEquals($dialect->addForeignKey('table', null, $references['fk1']), 'ALTER TABLE "table" ADD CONSTRAINT "fk1" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2")');
$this->assertEquals($dialect->addForeignKey('table', 'schema', $references['fk1']), 'ALTER TABLE "schema"."table" ADD CONSTRAINT "fk1" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2")');
$this->assertEquals($dialect->addForeignKey('table', null, $references['fk2']), 'ALTER TABLE "table" ADD CONSTRAINT "fk2" FOREIGN KEY ("column3", "column4") REFERENCES "ref_table" ("column5", "column6")');
$this->assertEquals($dialect->addForeignKey('table', 'schema', $references['fk2']), 'ALTER TABLE "schema"."table" ADD CONSTRAINT "fk2" FOREIGN KEY ("column3", "column4") REFERENCES "ref_table" ("column5", "column6")');

$this->assertEquals($dialect->addForeignKey('table', null, $references['fk3']), 'ALTER TABLE "table" ADD CONSTRAINT "fk3" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON DELETE CASCADE');
$this->assertEquals($dialect->addForeignKey('table', 'schema', $references['fk3']), 'ALTER TABLE "schema"."table" ADD CONSTRAINT "fk3" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON DELETE CASCADE');
$this->assertEquals($dialect->addForeignKey('table', null, $references['fk4']), 'ALTER TABLE "table" ADD CONSTRAINT "fk4" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON UPDATE SET NULL');
$this->assertEquals($dialect->addForeignKey('table', 'schema', $references['fk4']), 'ALTER TABLE "schema"."table" ADD CONSTRAINT "fk4" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON UPDATE SET NULL');
$this->assertEquals($dialect->addForeignKey('table', null, $references['fk5']), 'ALTER TABLE "table" ADD CONSTRAINT "fk5" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON DELETE CASCADE ON UPDATE NO ACTION');
$this->assertEquals($dialect->addForeignKey('table', 'schema', $references['fk5']), 'ALTER TABLE "schema"."table" ADD CONSTRAINT "fk5" FOREIGN KEY ("column1") REFERENCES "ref_table" ("column2") ON DELETE CASCADE ON UPDATE NO ACTION');

$this->assertEquals($dialect->dropForeignKey('table', null, 'fk1'), 'ALTER TABLE "table" DROP CONSTRAINT "fk1"');
$this->assertEquals($dialect->dropForeignKey('table', 'schema', 'fk1'), 'ALTER TABLE "schema"."table" DROP CONSTRAINT "fk1"');
Expand Down Expand Up @@ -723,7 +723,7 @@ public function testPostgresqlDialect()
$expected .= " \"column2\" INT,\n";
$expected .= " \"column3\" NUMERIC(10,2) NOT NULL,\n";
$expected .= " \"column1\" CHARACTER VARYING(10),\n";
$expected .= " CONSTRAINT pk PRIMARY KEY (\"column3\")\n";
$expected .= " CONSTRAINT \"PRIMARY\" PRIMARY KEY (\"column3\")\n";
$expected .= ");";
$this->assertEquals($dialect->createTable('table', null, $definition), $expected);

Expand All @@ -735,7 +735,7 @@ public function testPostgresqlDialect()
$expected .= " \"column2\" INT,\n";
$expected .= " \"column3\" NUMERIC(10,2) NOT NULL,\n";
$expected .= " \"column1\" CHARACTER VARYING(10),\n";
$expected .= " CONSTRAINT pk PRIMARY KEY (\"column3\"),\n";
$expected .= " CONSTRAINT \"PRIMARY\" PRIMARY KEY (\"column3\"),\n";
$expected .= " CONSTRAINT \"fk3\" FOREIGN KEY (\"column1\") REFERENCES \"ref_table\" (\"column2\") ON DELETE CASCADE\n";
$expected .= ");";
$this->assertEquals($dialect->createTable('table', null, $definition), $expected);
Expand Down