Commit 8ce891e4 authored by catch's avatar catch
Browse files

Issue #3232699 by alexpott, daffie, andypost, longwave: SQLite schema...

Issue #3232699 by alexpott, daffie, andypost, longwave: SQLite schema introspection implementation struggles with NULL default values
parent bd90218c
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -505,11 +505,30 @@ protected function introspectSchema($table) {
          'type' => $type,
          'size' => $size,
          'not null' => !empty($row->notnull) || $row->pk !== "0",
          'default' => trim($row->dflt_value, "'"),
        ];
        if ($length) {
          $schema['fields'][$row->name]['length'] = $length;
        }

        // Convert the default into a properly typed value.
        if ($row->dflt_value === 'NULL') {
          $schema['fields'][$row->name]['default'] = NULL;
        }
        elseif (is_string($row->dflt_value) && $row->dflt_value[0] === '\'') {
          // Remove the wrapping single quotes. And replace duplicate single
          // quotes with a single quote.
          $schema['fields'][$row->name]['default'] = str_replace("''", "'", substr($row->dflt_value, 1, -1));
        }
        elseif (is_numeric($row->dflt_value)) {
          // Adding 0 to a string will cause PHP to convert it to a float or
          // an integer depending on what the string is. For example:
          // - '1' + 0 = 1
          // - '1.0' + 0 = 1.0
          $schema['fields'][$row->name]['default'] = $row->dflt_value + 0;
        }
        else {
          $schema['fields'][$row->name]['default'] = $row->dflt_value;
        }
        // $row->pk contains a number that reflects the primary key order. We
        // use that as the key and sort (by key) below to return the primary key
        // in the same order that it is stored in.
+71 −0
Original line number Diff line number Diff line
@@ -1276,4 +1276,75 @@ public function testUpperCaseTableName() {
    $this->assertTrue($this->schema->dropTable($table_name), 'Table with uppercase table name dropped');
  }

  /**
   * Tests default values after altering table.
   */
  public function testDefaultAfterAlter() {
    $table_name = 'test_table';

    // Create the table.
    $table_specification = [
      'description' => 'Test table.',
      'fields' => [
        'column1'  => [
          'type' => 'int',
          'default' => NULL,
        ],
        'column2'  => [
          'type' => 'varchar',
          'length' => 20,
          'default' => NULL,
        ],
        'column3'  => [
          'type' => 'int',
          'default' => 200,
        ],
        'column4'  => [
          'type' => 'float',
          'default' => 1.23,
        ],
        'column5'  => [
          'type' => 'varchar',
          'length' => 20,
          'default' => "'s o'clock'",
        ],
        'column6'  => [
          'type' => 'varchar',
          'length' => 20,
          'default' => "o'clock",
        ],
        'column7'  => [
          'type' => 'varchar',
          'length' => 20,
          'default' => 'default value',
        ],
      ],
    ];
    $this->schema->createTable($table_name, $table_specification);

    // Insert a row and check that columns have the expected default values.
    $this->connection->insert($table_name)->fields(['column1' => 1])->execute();
    $result = $this->connection->select($table_name, 't')->fields('t', ['column2', 'column3', 'column4', 'column5', 'column6', 'column7'])->condition('column1', 1)->execute()->fetchObject();
    $this->assertNull($result->column2);
    $this->assertSame('200', $result->column3);
    $this->assertSame('1.23', $result->column4);
    $this->assertSame("'s o'clock'", $result->column5);
    $this->assertSame("o'clock", $result->column6);
    $this->assertSame('default value', $result->column7);

    // Force SQLite schema to create a new table and copy data by adding a not
    // field with an initial value.
    $this->schema->addField('test_table', 'new_column', ['type' => 'varchar', 'length' => 20, 'not null' => TRUE, 'description' => 'Added new column', 'initial' => 'test']);

    // Test that the columns default values are still correct.
    $this->connection->insert($table_name)->fields(['column1' => 2, 'new_column' => 'value'])->execute();
    $result = $this->connection->select($table_name, 't')->fields('t', ['column2', 'column3', 'column4', 'column5', 'column6', 'column7'])->condition('column1', 2)->execute()->fetchObject();
    $this->assertNull($result->column2);
    $this->assertSame('200', $result->column3);
    $this->assertSame('1.23', $result->column4);
    $this->assertSame("'s o'clock'", $result->column5);
    $this->assertSame("o'clock", $result->column6);
    $this->assertSame('default value', $result->column7);
  }

}