Skip to content

Commit

Permalink
fix default value CURRENT_TIMESTAMP
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov committed May 25, 2020
1 parent 574d04f commit b59bcd2
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 40 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
}
],
"require": {
"yiisoft/yii2": "^2.0.14.1"
"yiisoft/yii2": "^2.0.29"
},
"require-dev": {
"phpunit/phpunit": "4.8.34"
Expand Down
26 changes: 17 additions & 9 deletions src/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class Schema extends \yii\db\pgsql\Schema
const TYPE_BIT = 'bit';
const TYPE_COMPOSITE = 'composite';

const DATE_TYPES = [self::TYPE_TIMESTAMP, self::TYPE_DATETIME, self::TYPE_DATE, self::TYPE_TIME];
const CURRENT_TIME_DEFAULTS = ['now()', 'CURRENT_TIMESTAMP', 'CURRENT_DATE', 'CURRENT_TIME'];

/**
* @var array mapping from composite column types (keys) to PHP types (classes in configuration style).
* `array` by default, `object` also available as PHP type then a result will be converted to \stdClass.
Expand Down Expand Up @@ -62,6 +65,12 @@ protected function findColumns($table)
{
$tableName = $this->db->quoteValue($table->name);
$schemaName = $this->db->quoteValue($table->schemaName);

$orIdentity = '';
if (version_compare($this->db->serverVersion, '12.0', '>=')) {
$orIdentity = 'OR a.attidentity != \'\'';
}

$sql = <<<SQL
SELECT
d.nspname AS table_schema,
Expand All @@ -74,7 +83,8 @@ protected function findColumns($table)
COALESCE(NULLIF(a.atttypmod, -1), t.typtypmod) AS modifier,
NOT (a.attnotnull OR t.typnotnull) AS is_nullable,
COALESCE(t.typdefault, pg_get_expr(ad.adbin, ad.adrelid)::varchar) AS column_default,
COALESCE(pg_get_expr(ad.adbin, ad.adrelid) ~ 'nextval', false) AS is_autoinc,
COALESCE(pg_get_expr(ad.adbin, ad.adrelid) ~ 'nextval', false) {$orIdentity} AS is_autoinc,
pg_get_serial_sequence(quote_ident(d.nspname) || '.' || quote_ident(c.relname), a.attname) AS sequence_name,
CASE WHEN COALESCE(td.typtype, tb.typtype, t.typtype) = 'e'::char
THEN array_to_string((SELECT array_agg(enumlabel) FROM pg_enum WHERE enumtypid = COALESCE(td.oid, tb.oid, a.atttypid))::varchar[], ',')
ELSE NULL
Expand All @@ -95,7 +105,7 @@ protected function findColumns($table)
LEFT JOIN pg_namespace d ON d.oid = c.relnamespace
LEFT JOIN pg_constraint ct ON ct.conrelid = c.oid AND ct.contype = 'p'
WHERE
a.attnum > 0 AND t.typname != ''
a.attnum > 0 AND t.typname != '' AND NOT a.attisdropped
AND c.relname = {$tableName}
AND d.nspname = {$schemaName}
ORDER BY
Expand All @@ -114,16 +124,14 @@ protected function findColumns($table)
$table->columns[$column->name] = $column;
if ($column->isPrimaryKey) {
$table->primaryKey[] = $column->name;
if ($table->sequenceName === null && preg_match("/nextval\\('\"?\\w+\"?\.?\"?\\w+\"?'(::regclass)?\\)/", $column->defaultValue) === 1) {
$table->sequenceName = preg_replace(['/nextval/', '/::/', '/regclass/', '/\'\)/', '/\(\'/'], '', $column->defaultValue);
if ($table->sequenceName === null) {
$table->sequenceName = $column->sequenceName;
}
$column->defaultValue = null;
} elseif ($column->defaultValue) {
if (in_array($column->type, [static::TYPE_TIMESTAMP, static::TYPE_DATETIME, static::TYPE_DATE, static::TYPE_TIME]) && $column->defaultValue === 'now()') {
$column->defaultValue = new \DateTime;
} elseif ($column->type === static::TYPE_BIT && !$column->dimension) {
$column->defaultValue = $column->phpTypecast(trim($column->defaultValue, 'B\''));
} elseif (preg_match("/^'(.*?)'::/", $column->defaultValue, $matches)) {
if (in_array($column->type, static::DATE_TYPES) && in_array($column->defaultValue, static::CURRENT_TIME_DEFAULTS)) {
$column->defaultValue = new \DateTime();
} elseif (preg_match("/^B?'(.*?)'::/", $column->defaultValue, $matches)) {
$column->defaultValue = $column->phpTypecast($matches[1]);
} elseif (preg_match('/^(\()?(.*?)(?(1)\))(?:::.+)?$/', $column->defaultValue, $matches)) {
if ($matches[2] === 'NULL') {
Expand Down
8 changes: 0 additions & 8 deletions tests/ActiveRecordCompositeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,6 @@ protected function setUp()
if (file_exists(__DIR__ . '/data/config.local.php')) {
$config = ArrayHelper::merge($config, require(__DIR__ . '/data/config.local.php'));
}
if (is_array($config['components']['db']['schemaMap']['pgsql'])) {
$config['components']['db']['schemaMap']['pgsql']['compositeMap']['money'] = '\tigrov\tests\unit\pgsql\data\Money';
} else {
$config['components']['db']['schemaMap']['pgsql'] = [
'class' => $config['components']['db']['schemaMap']['pgsql'],
'compositeMap' => ['money' => '\tigrov\tests\unit\pgsql\data\Money'],
];
}

$this->mockApplication($config);
$this->createDatatypesTable();
Expand Down
12 changes: 7 additions & 5 deletions tests/ActiveRecordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace tigrov\tests\unit\pgsql;

use tigrov\tests\unit\pgsql\data\Datatypes;
use tigrov\tests\unit\pgsql\data\Money;
use yii\helpers\ArrayHelper;

class ActiveRecordTest extends TestCase
Expand Down Expand Up @@ -106,6 +107,7 @@ public function testDefaults()
// For default values see TestCase::createDatatypesTable()
$now = new \DateTime;
$this->assertLessThanOrEqual(1, static::convertIntervalToSeconds($now->diff($model->datetime)));
$this->assertLessThanOrEqual(1, static::convertIntervalToSeconds($now->diff($model->datetime2)));
foreach ($model->datetimes as $datetime) {
$this->assertLessThanOrEqual(1, static::convertIntervalToSeconds($now->diff($datetime)));
}
Expand All @@ -121,8 +123,8 @@ public function testDefaults()
$this->assertSame(true, $model->boolean);
$this->assertSame(1, $model->smallint);
$this->assertNull($model->timestamp);
$this->assertSame(['value' => '1.0000', 'currency_code' => 'USD'], $model->price);
$this->assertSame([['value' => '1.0000', 'currency_code' => 'USD']], $model->prices);
$this->assertEquals(new Money(['value' => '1.0000', 'currency_code' => 'USD']), $model->price);
$this->assertEquals([new Money(['value' => '1.0000', 'currency_code' => 'USD'])], $model->prices);
$this->assertSame('USD', $model->currency_code);
$this->assertSame('test', $model->binary);
$this->assertSame(['test'], $model->binaries);
Expand Down Expand Up @@ -199,9 +201,9 @@ public function valuesProvider()
['json', ['key' => 'value']],
['json', ['key1' => 'value1', 'key2' => true, 'key3' => false, 'key4' => '', 'key5' => null]],
['json', ['key' => ['key' => ['key' => 'value']]]],
['price', ['value' => null, 'currency_code' => 'EUR']],
['price', ['value' => '10.0000', 'currency_code' => 'USD']],
['prices', [['value' => '10.0000', 'currency_code' => 'USD'], ['value' => '99.9999', 'currency_code' => 'EUR']]],
['price', new Money(['value' => null, 'currency_code' => 'EUR']), false],
['price', new Money(['value' => '10.0000', 'currency_code' => 'USD']), false],
['prices', [new Money(['value' => '10.0000', 'currency_code' => 'USD']), new Money(['value' => '99.9999', 'currency_code' => 'EUR'])], false],
['binary', 'string'],
['binaries', ['string']],
];
Expand Down
8 changes: 0 additions & 8 deletions tests/SchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@ protected function setUp()
if (file_exists(__DIR__ . '/data/config.local.php')) {
$config = ArrayHelper::merge($config, require(__DIR__ . '/data/config.local.php'));
}
if (is_array($config['components']['db']['schemaMap']['pgsql'])) {
$config['components']['db']['schemaMap']['pgsql']['compositeMap']['money'] = '\tigrov\tests\unit\pgsql\data\Money';
} else {
$config['components']['db']['schemaMap']['pgsql'] = [
'class' => $config['components']['db']['schemaMap']['pgsql'],
'compositeMap' => ['money' => '\tigrov\tests\unit\pgsql\data\Money'],
];
}

$this->mockApplication($config);
$this->createDatatypesTable();
Expand Down
8 changes: 0 additions & 8 deletions tests/SchemaViewTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ protected function setUp()
if (file_exists(__DIR__ . '/data/config.local.php')) {
$config = ArrayHelper::merge($config, require(__DIR__ . '/data/config.local.php'));
}
if (is_array($config['components']['db']['schemaMap']['pgsql'])) {
$config['components']['db']['schemaMap']['pgsql']['compositeMap']['money'] = '\tigrov\tests\unit\pgsql\data\Money';
} else {
$config['components']['db']['schemaMap']['pgsql'] = [
'class' => $config['components']['db']['schemaMap']['pgsql'],
'compositeMap' => ['money' => '\tigrov\tests\unit\pgsql\data\Money'],
];
}

$this->mockApplication($config);
$this->createDatatypesTable();
Expand Down
2 changes: 2 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ protected function createDatatypesTable()
'varbit' => 'varbit DEFAULT \'B101\'',
'bits' => 'varbit[] DEFAULT \'{101}\'',
'datetime' => 'timestamp DEFAULT now()',
'datetime2' => 'timestamp DEFAULT CURRENT_TIMESTAMP',
'datetimes' => 'timestamp[] DEFAULT \'{now(),now()}\'',
'json' => 'jsonb DEFAULT \'[]\'',
'boolean' => 'boolean DEFAULT true',
Expand Down Expand Up @@ -115,5 +116,6 @@ protected function dropDatatypesTable()
$db->createCommand('DROP TABLE IF EXISTS ' . static::TABLENAME . ' CASCADE')->execute();
$db->createCommand('DROP TYPE IF EXISTS ' . $moneyType . ' CASCADE')->execute();
$db->createCommand('DROP DOMAIN IF EXISTS ' . $currencyType . ' CASCADE')->execute();
$db->close();
}
}
7 changes: 6 additions & 1 deletion tests/data/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
'password' => '',
'charset' => 'utf8',
'schemaMap' => [
'pgsql'=> 'tigrov\pgsql\Schema',
'pgsql'=> [
'class' => 'tigrov\pgsql\Schema',
'compositeMap' => [
'money' => '\tigrov\tests\unit\pgsql\data\Money'
],
],
],
],
],
Expand Down

0 comments on commit b59bcd2

Please sign in to comment.