Browse Source

Improve support for `decimal` type in Postgres schema management

Yves P 9 years ago
parent
commit
a0ce4c453c

+ 8 - 0
src/Database/Schema/PostgresSchema.php

@@ -46,6 +46,8 @@ class PostgresSchema extends BaseSchema
             c.collation_name,
             d.description as comment,
             ordinal_position,
+            c.numeric_precision as column_precision,
+            c.numeric_scale as column_scale,
             pg_get_serial_sequence(attr.attrelid::regclass::text, attr.attname) IS NOT NULL AS has_serial
         FROM information_schema.columns c
         INNER JOIN pg_catalog.pg_namespace ns ON (ns.nspname = table_schema)
@@ -158,6 +160,7 @@ class PostgresSchema extends BaseSchema
         if (!empty($row['has_serial'])) {
             $field['autoIncrement'] = true;
         }
+
         $field += [
             'default' => $this->_defaultValue($row['default']),
             'null' => $row['null'] === 'YES' ? true : false,
@@ -165,6 +168,11 @@ class PostgresSchema extends BaseSchema
             'comment' => $row['comment']
         ];
         $field['length'] = $row['char_length'] ?: $field['length'];
+
+        if ($field['type'] === 'numeric' || $field['type'] === 'decimal') {
+            $field['length'] = $row['column_precision'];
+            $field['precision'] = $row['column_scale'] ? $row['column_scale'] : null;
+        }
         $table->addColumn($row['name'], $field);
     }
 

+ 29 - 2
tests/TestCase/Database/Schema/PostgresSchemaTest.php

@@ -75,6 +75,8 @@ published BOOLEAN DEFAULT false,
 views SMALLINT DEFAULT 0,
 readingtime TIME,
 data JSONB,
+average_note DECIMAL(4,2),
+average_income NUMERIC(10,2),
 created TIMESTAMP,
 CONSTRAINT "content_idx" UNIQUE ("title", "body"),
 CONSTRAINT "author_idx" FOREIGN KEY ("author_id") REFERENCES "schema_authors" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
@@ -139,11 +141,11 @@ SQL;
             // Decimal
             [
                 'NUMERIC',
-                ['type' => 'decimal', 'length' => null]
+                ['type' => 'decimal', 'length' => null, 'precision' => null]
             ],
             [
                 'DECIMAL(10,2)',
-                ['type' => 'decimal', 'length' => null]
+                ['type' => 'decimal', 'length' => 10, 'precision' => 2]
             ],
             // String
             [
@@ -228,6 +230,8 @@ SQL;
             'default' => 'Default value',
             'comment' => 'Comment section',
             'char_length' => null,
+            'column_precision' => null,
+            'column_scale' => null,
             'collation_name' => 'ja_JP.utf8',
         ];
         $expected += [
@@ -237,6 +241,11 @@ SQL;
             'collate' => 'ja_JP.utf8',
         ];
 
+        if ($field['type'] === 'NUMERIC' || strpos($field['type'], 'DECIMAL') !== false) {
+            $field['column_precision'] = $expected['length'];
+            $field['column_scale'] = $expected['precision'];
+        }
+
         $driver = $this->getMockBuilder('Cake\Database\Driver\Postgres')->getMock();
         $dialect = new PostgresSchema($driver);
 
@@ -367,6 +376,24 @@ SQL;
                 'precision' => null,
                 'comment' => null,
             ],
+            'average_note' => [
+                'type' => 'decimal',
+                'null' => true,
+                'default' => null,
+                'length' => 4,
+                'precision' => 2,
+                'unsigned' => null,
+                'comment' => null,
+            ],
+            'average_income' => [
+                'type' => 'decimal',
+                'null' => true,
+                'default' => null,
+                'length' => 10,
+                'precision' => 2,
+                'unsigned' => null,
+                'comment' => null,
+            ],
             'created' => [
                 'type' => 'timestamp',
                 'null' => true,