Browse Source

Fix default values in postgres.

Postgres returns additional data that is not helpful when building
entities or rebuilding schema.

Refs #4398
mark_story 11 years ago
parent
commit
a6eff184e7

+ 29 - 3
src/Database/Schema/PostgresSchema.php

@@ -135,10 +135,9 @@ class PostgresSchema extends BaseSchema {
 				$row['default'] = 0;
 			}
 		}
-
 		$field += [
+			'default' => $this->_defaultValue($row['default']),
 			'null' => $row['null'] === 'YES' ? true : false,
-			'default' => $row['default'],
 			'comment' => $row['comment']
 		];
 		$field['length'] = $row['char_length'] ?: $field['length'];
@@ -146,6 +145,32 @@ class PostgresSchema extends BaseSchema {
 	}
 
 /**
+ * Manipulate the default value.
+ *
+ * Postgres includes sequence data and casting information in default values.
+ * We need to remove those.
+ *
+ * @param string $default The default value.
+ * @return string
+ */
+	protected function _defaultValue($default) {
+		if (is_numeric($default) || $default === null) {
+			return $default;
+		}
+		// Sequences
+		if (strpos($default, 'nextval') === 0) {
+			return null;
+		}
+
+		// Remove quotes and postgres casts
+		return preg_replace(
+			"/^'(.*)'(?:::.*)$/",
+			"$1",
+			$default
+		);
+	}
+
+/**
  * {@inheritDoc}
  */
 	public function describeIndexSql($table, $config) {
@@ -201,7 +226,8 @@ class PostgresSchema extends BaseSchema {
 			$columnDef = $table->column($columns[0]);
 			if (
 				count($columns) === 1 &&
-				in_array($columnDef['type'], ['integer', 'biginteger'])
+				in_array($columnDef['type'], ['integer', 'biginteger']) &&
+				$type === Table::CONSTRAINT_PRIMARY
 			) {
 				$columnDef['autoIncrement'] = true;
 				$table->addColumn($columns[0], $columnDef);

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

@@ -51,9 +51,9 @@ class PostgresSchemaTest extends TestCase {
 		$table = <<<SQL
 CREATE TABLE schema_authors (
 id SERIAL,
-name VARCHAR(50),
+name VARCHAR(50) DEFAULT 'bob',
 bio DATE,
-position INT,
+position INT DEFAULT 1,
 created TIMESTAMP,
 PRIMARY KEY (id),
 CONSTRAINT "unique_position" UNIQUE ("position")
@@ -338,6 +338,70 @@ SQL;
 	}
 
 /**
+ * Test describing a table containing defaults with Postgres
+ *
+ * @return void
+ */
+	public function testDescribeTableWithDefaults() {
+		$connection = ConnectionManager::get('test');
+		$this->_createTables($connection);
+
+		$schema = new SchemaCollection($connection);
+		$result = $schema->describe('schema_authors');
+		$expected = [
+			'id' => [
+				'type' => 'integer',
+				'null' => false,
+				'default' => null,
+				'length' => 10,
+				'precision' => null,
+				'unsigned' => null,
+				'comment' => null,
+				'autoIncrement' => true,
+			],
+			'name' => [
+				'type' => 'string',
+				'null' => true,
+				'default' => 'bob',
+				'length' => 50,
+				'precision' => null,
+				'comment' => null,
+				'fixed' => null,
+			],
+			'bio' => [
+				'type' => 'date',
+				'null' => true,
+				'default' => null,
+				'length' => null,
+				'precision' => null,
+				'comment' => null,
+			],
+			'position' => [
+				'type' => 'integer',
+				'null' => true,
+				'default' => '1',
+				'length' => 10,
+				'precision' => null,
+				'comment' => null,
+				'unsigned' => null,
+				'autoIncrement' => null,
+			],
+			'created' => [
+				'type' => 'timestamp',
+				'null' => true,
+				'default' => null,
+				'length' => null,
+				'precision' => null,
+				'comment' => null,
+			],
+		];
+		$this->assertEquals(['id'], $result->primaryKey());
+		foreach ($expected as $field => $definition) {
+			$this->assertEquals($definition, $result->column($field), "Mismatch in $field column");
+		}
+	}
+
+/**
  * Test describing a table with containing keywords
  *
  * @return void