Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotfix/insert get id fix #2

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"homepage": "https://github.com/yuk1/laravel-redshift",
"keywords": ["Laravel", "Redshift"],
"require": {
"illuminate/support": "~7|~8"
"illuminate/support": ">= 7.0"
},
"require-dev": {
"phpunit/phpunit": "~9.0",
Expand Down
17 changes: 15 additions & 2 deletions src/Database/Query/Grammars/RedshiftGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,21 @@
namespace YuK1\LaravelRedshift\Database\Query\Grammars;

use Illuminate\Database\Query\Grammars\PostgresGrammar;
use Illuminate\Database\Query\Builder;

class RedshiftGrammar extends PostgresGrammar
{

}
/**
* Compile insert statement.
* Unlike PostgreSQL, in Redshift it is not possible to return the id at the same time
*
* @param \Illuminate\Database\Query\Builder $query
* @param array $values
* @param string $sequence
* @return string
*/
public function compileInsertGetId(Builder $query, $values, $sequence)
{
return $this->compileInsert($query, $values);
}
}
24 changes: 23 additions & 1 deletion src/Database/Query/Processors/RedshiftProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,30 @@
namespace YuK1\LaravelRedshift\Database\Query\Processors;

use Illuminate\Database\Query\Processors\PostgresProcessor;
use Illuminate\Database\Query\Builder;

class RedshiftProcessor extends PostgresProcessor
{
/**
* Process an "insert get ID" query.
*
* @param \Illuminate\Database\Query\Builder $query
* @param string $sql
* @param array $values
* @param string|null $sequence
* @return int
*/
public function processInsertGetId(Builder $query, $sql, $values, $sequence = null)
{
$connection = $query->getConnection();

}
$connection->insert($sql, $values);

$idColumn = $sequence ?: 'id';
$wrappedTable = $query->getGrammar()->wrapTable($query->from);
$result = $connection->selectOne('select max('. $idColumn .') from '.$wrappedTable);
$id = array_values((array) $result)[0];

return is_numeric($id) ? (int) $id : $id;
}
}
52 changes: 26 additions & 26 deletions src/Database/RedshiftConnection.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace YuK1\LaravelRedshift\Database;

use Illuminate\Database\PostgresConnection;
Expand All @@ -8,37 +9,36 @@
use YuK1\LaravelRedshift\Database\Schema\Grammars\RedshiftGrammar as SchemaGrammar;
use YuK1\LaravelRedshift\Database\Schema\RedshiftBuilder;
use YuK1\LaravelRedshift\Database\Schema\RedshiftSchemaState;
use Illuminate\Database\Filesystem;
use Illuminate\Filesystem\Filesystem;

class RedshiftConnection extends PostgresConnection
{
protected function getDefaultQueryGrammar()
{
return $this->withTablePrefix(new QueryGrammar);
protected function getDefaultQueryGrammar()
{
return $this->withTablePrefix(new QueryGrammar);
}

public function getSchemaBuilder()
{
if (is_null($this->schemaGrammar)) {
$this->useDefaultSchemaGrammar();
}

public function getSchemaBuilder()
{
if (is_null($this->schemaGrammar)) {
$this->useDefaultSchemaGrammar();
}

return new RedshiftBuilder($this);
}
return new RedshiftBuilder($this);
}

protected function getDefaultSchemaGrammar()
{
return $this->withTablePrefix(new SchemaGrammar);
}
protected function getDefaultSchemaGrammar()
{
return $this->withTablePrefix(new SchemaGrammar);
}

public function getSchemaState(Filesystem $files = null, callable $processFactory = null)
{
return new RedshiftSchemaState($this, $files, $processFactory);
}

protected function getDefaultPostProcessor()
{
return new RedshiftProcessor;
}
public function getSchemaState(Filesystem $files = null, callable $processFactory = null)
{
return new RedshiftSchemaState($this, $files, $processFactory);
}

}
protected function getDefaultPostProcessor()
{
return new RedshiftProcessor;
}
}
205 changes: 110 additions & 95 deletions src/Database/Schema/Grammars/RedshiftGrammar.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace YuK1\LaravelRedshift\Database\Schema\Grammars;

use Illuminate\Database\Schema\Grammars\PostgresGrammar;
Expand All @@ -8,114 +9,128 @@

class RedshiftGrammar extends PostgresGrammar
{
protected function getColumns(Blueprint $blueprint)
{
$columns = [];

foreach ($blueprint->getAddedColumns() as $column) {
$sql = $this->wrap($column).' '.$this->getType($column);
protected function getColumns(Blueprint $blueprint)
{
$columns = [];

/**
* Add Redshift-specific encoding settings
*/
if ($encode = $this->getEncode($column)) {
$sql .= ' '.$encode;
}
foreach ($blueprint->getAddedColumns() as $column) {
$sql = $this->wrap($column) . ' ' . $this->getType($column);

$columns[] = $this->addModifiers($sql, $blueprint, $column);
}
/**
* Add Redshift-specific encoding settings
*/
if ($encode = $this->getEncode($column)) {
$sql .= ' ' . $encode;
}

return $columns;
$columns[] = $this->addModifiers($sql, $blueprint, $column);
}

protected function getEncode(Fluent $column) {
return $column->encode !== null ? 'encode '.$column->encode : null;
return $columns;
}

protected function getEncode(Fluent $column)
{
return $column->encode !== null ? 'encode ' . $column->encode : null;
}

protected function generatableColumn($type, Fluent $column)
{
if (!$column->autoIncrement && is_null($column->generatedAs)) {
return $type;
}

protected function generatableColumn($type, Fluent $column)
{
if (! $column->autoIncrement && is_null($column->generatedAs)) {
return $type;
}

if ($column->autoIncrement && is_null($column->generatedAs)) {
return with([
'integer' => 'INTEGER',
'bigint' => 'BIGINT',
'smallint' => 'SMALLINT',
])[$type];
}

return parent::generatableColumn($type, $column);
if ($column->autoIncrement && is_null($column->generatedAs)) {
return with([
'integer' => 'INTEGER',
'bigint' => 'BIGINT',
'smallint' => 'SMALLINT',
])[$type];
}

protected function typeTimestamp(Fluent $column)
{
$columnType = 'timestamp without time zone';
return parent::generatableColumn($type, $column);
}

return $column->useCurrent ? "$columnType default CURRENT_TIMESTAMP" : $columnType;
}
protected function typeTimestamp(Fluent $column)
{
$columnType = 'timestamp without time zone';

protected function modifyIncrement(Blueprint $blueprint, Fluent $column)
{
if ((in_array($column->type, $this->serials) || ($column->generatedAs !== null)) && $column->autoIncrement) {
return ' identity(1,1)';
}
}
return $column->useCurrent ? "$columnType default CURRENT_TIMESTAMP" : $columnType;
}

public function compileCreate(Blueprint $blueprint, Fluent $command)
{
return array_values(array_filter(array_merge([sprintf('%s table %s (%s)',
$blueprint->temporary ? 'create temporary' : 'create',
$this->wrapTable($blueprint),
implode(', ', $this->getColumns($blueprint)),
)],
$this->compileAlter($blueprint)
)));
protected function modifyIncrement(Blueprint $blueprint, Fluent $column)
{
if ((in_array($column->type, $this->serials) || ($column->generatedAs !== null)) && $column->autoIncrement) {
return ' identity(1,1)';
}

protected function compileAlter(Blueprint $blueprint)
{
$distKey = $this->compileDistKey($blueprint);
$sortKey = $this->compileSortKey($blueprint);
$keys = collect([ $distKey, $sortKey ])->flatten()->filter()->values();

return $keys->map(function($key) use($blueprint) {
return sprintf('alter table %s %s', $blueprint->getTable(), $key);
}

public function compileCreate(Blueprint $blueprint, Fluent $command)
{
return array_values(array_filter(array_merge(
[sprintf(
'%s table %s (%s)',
$blueprint->temporary ? 'create temporary' : 'create',
$this->wrapTable($blueprint),
implode(', ', $this->getColumns($blueprint)),
)],
$this->compileAlter($blueprint)
)));
}

protected function compileAlter(Blueprint $blueprint)
{
$distKey = $this->compileDistKey($blueprint);
$sortKey = $this->compileSortKey($blueprint);
$keys = collect([$distKey, $sortKey])->flatten()->filter()->values();

return $keys->map(function ($key) use ($blueprint) {
return sprintf('alter table %s %s', $blueprint->getTable(), $key);
})
->values()->all();
}

protected function compileSortKey(Blueprint $blueprint)
{
if ($values = $blueprint->sortKeyValues()) {
return sprintf(
'alter compound sortkey (%s)',
collect($values)->sort()->keys()->map(function ($value) {
return '"' . $value . '"';
})
->values()->all();
->join(', ')
);
}

protected function compileSortKey(Blueprint $blueprint)
{
if ($values = $blueprint->sortKeyValues()) {
return sprintf('alter compound sortkey (%s)',
collect($values)->sort()->keys()->map(function($value) {
return '"' . $value . '"';
})
->join(', '));
}
return null;
return null;
}

protected function compileDistKey(Blueprint $blueprint)
{
if ($distKeyColumn = $blueprint->distKeyValue()) {
$distKeyColumn = collect($distKeyColumn);

switch ($distKeyColumn[0]) {
case 'key':
return sprintf('alter diststyle key distkey %s', $distKeyColumn[1]);
case 'all':
case 'auto':
case 'even':
return sprintf('alter diststyle %s', $distKeyColumn[0]);
default:
throw new LaravelRedshiftException(sprintf('Dist key name "%s" is not supported.', $distKeyColumn[0]));
}
}

protected function compileDistKey(Blueprint $blueprint)
{
if ($distKeyColumn = $blueprint->distKeyValue()) {
$distKeyColumn = collect($distKeyColumn);

switch ($distKeyColumn[0]) {
case 'key':
return sprintf('alter diststyle key distkey %s', $distKeyColumn[1]);
case 'all':
case 'auto':
case 'even':
return sprintf('alter diststyle %s', $distKeyColumn[0]);
default:
throw new LaravelRedshiftException(sprintf('Dist key name "%s" is not supported.', $distKeyColumn[0]));

}
}
return null;
}

}
return null;
}

/**
* Create the column definition for a uuid type.
*
* @param \Illuminate\Support\Fluent $column
* @return string
*/
protected function typeUuid(Fluent $column)
{
return 'char(36)';
}
}