Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/Propel/Generator/Model/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,11 @@ public function addColumn($data)
$this->columnsSize[$name] = $data['size'];
}
if ($this->getTable()) {
$this->columnObjects[] = $this->getTable()->getColumn($name);
$column = $this->getTable()->getColumn($name);
$this->columnObjects[] = $column;
if (!isset($data['size']) && $column->getSize()) {
$this->columnsSize[$name] = $column->getSize();
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Propel/Generator/Model/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ public function setupReferrers($throwErrors = false)

// check for incomplete foreign key references when foreign table
// has a composite primary key
if ($foreignTable->hasCompositePrimaryKey()) {
if (!is_null($foreignTable) && $foreignTable->hasCompositePrimaryKey()) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 as it fixes this specific case

// get composite foreign key's keys
$foreignPrimaryKeys = $foreignTable->getPrimaryKey();
// check all keys are referenced in foreign key
Expand Down
164 changes: 161 additions & 3 deletions src/Propel/Generator/Platform/MssqlPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
namespace Propel\Generator\Platform;

use Propel\Generator\Model\Database;
use Propel\Generator\Model\Diff\ColumnDiff;
use Propel\Generator\Model\Domain;
use Propel\Generator\Model\ForeignKey;
use Propel\Generator\Model\Index;
use Propel\Generator\Model\PropelTypes;
use Propel\Generator\Model\Table;
use Propel\Generator\Model\Unique;
use Propel\Generator\Model\Column;

/**
* MS SQL PlatformInterface implementation.
Expand Down Expand Up @@ -202,16 +205,171 @@ public function getForeignKeyDDL(ForeignKey $fk)
$this->quoteIdentifier($fk->getForeignTableName()),
$this->getColumnListDDL($fk->getForeignColumnObjects())
);
if ($fk->hasOnUpdate() && $fk->getOnUpdate() != ForeignKey::SETNULL) {
if ($fk->hasOnUpdate() && $fk->getOnUpdate()) {
$script .= ' ON UPDATE ' . $fk->getOnUpdate();
}
if ($fk->hasOnDelete() && $fk->getOnDelete() != ForeignKey::SETNULL) {
if ($fk->hasOnDelete() && $fk->getOnDelete()) {
$script .= ' ON DELETE '. $fk->getOnDelete();
}

return $script;
}

/**
* Builds the DDL SQL to drop a foreign key.
*
* @param ForeignKey $fk
* @return string
*/
public function getDropForeignKeyDDL(ForeignKey $fk)
{
if ($fk->isSkipSql() || $fk->isPolymorphic()) {
return;
}

$sql = "
IF EXISTS (SELECT 1 FROM sysobjects WHERE name='" . $fk->getName() . "')
ALTER TABLE " . $this->quoteIdentifier($fk->getTable()->getName()) . " DROP CONSTRAINT " . $this->quoteIdentifier($fk->getName()) . ";
";

return $sql;
}

/**
* Returns the DDL SQL to add an Index.
*
* @param Index $index
* @return string
*/
public function getAddIndexDDL(Index $index)
{
// Unique indexes must be treated as constraints
if ($index->isUnique()) {
return "\nALTER TABLE " . $this->quoteIdentifier($index->getTable()->getName()) . " ADD " . $this->getUniqueDDL($index).";\n";

} else {
$pattern = "
CREATE INDEX %s ON %s (%s);
";

return sprintf($pattern,
$this->quoteIdentifier($index->getName()),
$this->quoteIdentifier($index->getTable()->getName()),
$this->getColumnListDDL($index->getColumnObjects())
);
}
}

/**
* Builds the DDL SQL to drop an Index.
*
* @param Index $index
* @return string
*/
public function getDropIndexDDL(Index $index)
{
// Unique indexes must be treated as constraints
if ($index->isUnique()) {
$sql = "
IF EXISTS (SELECT 1 FROM sysobjects WHERE name='" . $index->getFQName() . "')
ALTER TABLE " . $this->quoteIdentifier($index->getTable()->getName()) . " DROP CONSTRAINT " . $this->quoteIdentifier($index->getFQName()) . ";
";

return $sql;
}

$pattern = "\nDROP INDEX %s ON %s;\n";

return sprintf($pattern,
$this->quoteIdentifier($index->getFQName()),
$this->quoteIdentifier($index->getTable()->getName())
);

}

/**
* Builds the DDL SQL to rename a column
*
* @return string
*/
public function getRenameColumnDDL(Column $fromColumn, Column $toColumn)
{
$fromColumnName = $this->quoteIdentifier($fromColumn->getTable()->getName().".".$fromColumn->getName());
$toColumnName = $this->quoteIdentifier($toColumn->getName());

$script = "
EXEC sp_rename $fromColumnName, $toColumnName, 'COLUMN';
";

return $script;
}

/**
* Builds the DDL SQL to add a list of columns
*
* @param Column[] $columns
* @return string
*/
public function getAddColumnsDDL($columns)
{
$lines = [];
$table = null;
foreach ($columns as $column) {
if (null === $table) {
$table = $column->getTable();
}
$lines[] = $this->getColumnDDL($column);
}

$sep = ",\n";

$pattern = "\nALTER TABLE %s ADD %s;";

return sprintf($pattern,
$this->quoteIdentifier($table->getName()),
implode($sep, $lines)
);
}

/**
* Builds the DDL SQL to modify a column
*
* @return string
*/
public function getModifyColumnDDL(ColumnDiff $columnDiff)
{
$toColumn = $columnDiff->getToColumn();
$pattern = "ALTER TABLE %s ALTER COLUMN %s;\n";

return sprintf($pattern,
$this->quoteIdentifier($toColumn->getTable()->getName()),
$this->getColumnDDL($toColumn)
);
}

/**
* Builds the DDL SQL to modify a list of columns
*
* @param ColumnDiff[] $columnDiffs
* @return string
*/
public function getModifyColumnsDDL($columnDiffs)
{
$lines = [];
$table = null;
foreach ($columnDiffs as $columnDiff) {
$toColumn = $columnDiff->getToColumn();
if (null === $table) {
$table = $toColumn->getTable();
}
$lines[] = $this->getModifyColumnDDL($columnDiff);
}

$sep = "";

return "\n" . implode($sep, $lines);
}

/**
* @see Platform::supportsSchemas()
*/
Expand All @@ -231,7 +389,7 @@ public function hasSize($sqlType)
*/
public function doQuoting($text)
{
return '[' . strtr($text, ['.' => '].[']) . ']';
return "[$text]";
}

public function getTimestampFormatter()
Expand Down
51 changes: 45 additions & 6 deletions src/Propel/Generator/Reverse/MssqlSchemaParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class MssqlSchemaParser extends AbstractSchemaParser
'bit' => PropelTypes::BOOLEAN,
'char' => PropelTypes::CHAR,
'datetime' => PropelTypes::TIMESTAMP,
'datetime2' => PropelTypes::TIMESTAMP,
'decimal() identity' => PropelTypes::DECIMAL,
'decimal' => PropelTypes::DECIMAL,
'image' => PropelTypes::LONGVARBINARY,
Expand Down Expand Up @@ -72,6 +73,32 @@ class MssqlSchemaParser extends AbstractSchemaParser
'sql_variant' => PropelTypes::VARCHAR,
];

/**
* List with types where size comparison makes sense
* @var array
*/
private static $mssqlTypesWithSize = [
PropelTypes::CHAR,
PropelTypes::DECIMAL,
PropelTypes::VARCHAR,
PropelTypes::VARBINARY
];

/**
* https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-foreign-keys-transact-sql
* 0 = No action
* 1 = Cascade
* 2 = Set null
* 3 = Set default
*/
private static $mssqlForeignKeyTypes = [
0 => ForeignKey::NOACTION,
1 => ForeignKey::CASCADE,
2 => ForeignKey::SETNULL,
3 => ForeignKey::SETDEFAULT,
];


/**
* @see AbstractSchemaParser::getTypeMapping()
*/
Expand Down Expand Up @@ -126,9 +153,9 @@ protected function addColumns(Table $table)

$name = $this->cleanDelimitedIdentifiers($row['COLUMN_NAME']);
$type = $row['TYPE_NAME'];
$size = $row['LENGTH'];
$size = $row['PRECISION'];
$isNullable = $row['NULLABLE'];
$default = $row['COLUMN_DEF'];
$default = trim(str_replace(["((", "))","('", "')","(", ")",'DEFAULT'], '', $row['COLUMN_DEF']));
$scale = $row['SCALE'];
$autoincrement = false;
if (strtolower($type) == 'int identity') {
Expand All @@ -140,6 +167,9 @@ protected function addColumns(Table $table)
$propelType = Column::DEFAULT_TYPE;
$this->warn(sprintf('Column [%s.%s] has a column type (%s) that Propel does not support.', $table->getName(), $name, $type));
}
if (!in_array($propelType, self::$mssqlTypesWithSize)) {
$size = null;
}

$column = new Column($name);
$column->setTable($table);
Expand All @@ -148,7 +178,7 @@ protected function addColumns(Table $table)
// $column->getDomain()->replaceSqlType($type);
$column->getDomain()->replaceSize($size);
$column->getDomain()->replaceScale($scale);
if ($default !== null) {
if (strlen($default) > 0) {
$column->getDomain()->setDefaultValue(new ColumnDefaultValue($default, ColumnDefaultValue::TYPE_VALUE));
}
$column->setAutoIncrement($autoincrement);
Expand All @@ -165,7 +195,8 @@ protected function addForeignKeys(Table $table)
{
$database = $table->getDatabase();

$dataFetcher = $this->dbh->query("select fk.name as CONSTRAINT_NAME, lcol.name as COLUMN_NAME, rtab.name as FK_TABLE_NAME, rcol.name as FK_COLUMN_NAME
$dataFetcher = $this->dbh->query("select fk.name as CONSTRAINT_NAME, lcol.name as COLUMN_NAME, rtab.name as FK_TABLE_NAME, rcol.name as FK_COLUMN_NAME,
fk.[update_referential_action] as FK_ON_UPDATE_ACTION, fk.[delete_referential_action] as FK_ON_DELETE_ACTION
from sys.foreign_keys as fk
inner join sys.foreign_key_columns ref on ref.constraint_object_id = fk.object_id
inner join sys.columns lcol on lcol.object_id = ref.parent_object_id and lcol.column_id = ref.parent_column_id
Expand All @@ -187,11 +218,19 @@ protected function addForeignKeys(Table $table)
$localColumn = $table->getColumn($lcol);

if (!isset($foreignKeys[$name])) {
// default for mssql -> 'NO ACTION'
$fkactions = [
'ON DELETE' => array_key_exists($row['FK_ON_DELETE_ACTION'], self::$mssqlForeignKeyTypes) ?
self::$mssqlForeignKeyTypes[$row['FK_ON_DELETE_ACTION']] : ForeignKey::NOACTION,
'ON UPDATE' => array_key_exists($row['FK_ON_UPDATE_ACTION'], self::$mssqlForeignKeyTypes) ?
self::$mssqlForeignKeyTypes[$row['FK_ON_UPDATE_ACTION']] : ForeignKey::NOACTION,
];

$fk = new ForeignKey($name);
$fk->setForeignTableCommonName($foreignTable->getCommonName());
$fk->setForeignSchemaName($foreignTable->getSchema());
//$fk->setOnDelete($fkactions['ON DELETE']);
//$fk->setOnUpdate($fkactions['ON UPDATE']);
$fk->setOnDelete($fkactions['ON DELETE']);
$fk->setOnUpdate($fkactions['ON UPDATE']);
$table->addForeignKey($fk);
$foreignKeys[$name] = $fk;
}
Expand Down
5 changes: 5 additions & 0 deletions src/Propel/Runtime/Connection/ConnectionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public static function create(array $configuration = [], AdapterInterface $adapt
}
$value = constant($value);
}

if ($option == "ATTR_EMULATE_PREPARES" || $option == "ATTR_TIMEOUT") {
continue;
}

$connection->setAttribute($option, $value);
}
}
Expand Down