final public AppendIdentifier ( $QueryStringFormat, array $IdentifierSegments, $ValuePlaceholder = self::DefaultPlaceholder ) | ||
$IdentifierSegments | array |
private function AppendOnDuplicateKeyUpdate(QueryBuilder $QueryBuilder, $TableName, array $Columns, array $PrimaryKeyIdentifiers) { $QueryBuilder->Append(' ON DUPLICATE KEY UPDATE '); $FirstPrimaryKey = true; foreach ($QueryBuilder->Delimit($Columns, ',') as $ColumName => $Column) { $ColumnIdentifier = [$TableName, $ColumName]; if ($FirstPrimaryKey && $Column->IsPrimaryKey()) { /* * Ugly fix/hack to prevent mysql from updating primary key when encountering * a duplicate value on a seperate unique constraint. Sadly Mysql does not support * the more robust 'MERGE' operation. Furthermore there is no clean way to throw a * conditional runtime error in Mysql reliably. * * Example: Persisting a account entity with a unique username, if the user changes * their username and and a duplicate username exists, mysql could attempt to update * the other duplicate row with the new values/primary key. This should not be an * issue as then it will fail with a duplicate primary key but could lead to some * wacky edge cases that I want no part in. */ $QueryBuilder->AppendIdentifier('# = IF(', $ColumnIdentifier); foreach ($QueryBuilder->Delimit($PrimaryKeyIdentifiers, ' AND ') as $PrimaryKeyIdentifier) { $QueryBuilder->AppendIdentifier('# = VALUES(#)', $PrimaryKeyIdentifier); } $QueryBuilder->Append(','); $QueryBuilder->AppendIdentifier('VALUES(#)', $ColumnIdentifier); $QueryBuilder->Append(','); $QueryBuilder->Append('(SELECT 1 UNION ALL SELECT 1))'); $FirstPrimaryKey = false; } else { $QueryBuilder->AppendIdentifier('# = VALUES(#)', $ColumnIdentifier); } } }
protected function DeletePrimaryKeysQuery(QueryBuilder $QueryBuilder, Table $Table, array $PrimaryKeys) { $TableName = $Table->GetName(); $DerivedTableName = $TableName . 'PrimaryKeys'; $TransformedDerivedTableName = $TableName . 'PersistencePrimaryKeys'; $PrimaryKeysColumns = $Table->GetPrimaryKeyColumns(); $PrimaryKeyNames = array_keys($PrimaryKeysColumns); $QueryBuilder->AppendIdentifier('DELETE # FROM # INNER JOIN (', [$TableName]); $this->StandardPersister->AppendDataAsInlineTable($QueryBuilder, $PrimaryKeysColumns, $DerivedTableName, $PrimaryKeys); $QueryBuilder->AppendIdentifier(') #', [$TransformedDerivedTableName]); $QueryBuilder->Append(' ON '); foreach ($QueryBuilder->Delimit($PrimaryKeyNames, ' AND ') as $PrimaryKeyName) { $QueryBuilder->AppendIdentifier('# = ', [$TableName, $PrimaryKeyName]); $QueryBuilder->AppendIdentifier('#', [$TransformedDerivedTableName, $PrimaryKeyName]); } }
protected function UpsertRowsQuery(QueryBuilder $QueryBuilder, Table $Table, array $Rows, $ShouldReturnKeyData) { if ($ShouldReturnKeyData) { throw new \Storm\Drivers\Base\Relational\PlatformException('SQLite does not support returning data'); } $Columns = $Table->GetColumns(); $PrimaryKeyColumns = $Table->GetPrimaryKeyColumns(); $ColumnNames = array_keys($Columns); $PrimaryKeyColumnNames = array_keys($PrimaryKeyColumns); $TableName = $Table->GetName(); $DerivedTableName = $TableName . 'Values'; $PrimaryKeyIdentifiers = []; foreach ($PrimaryKeyColumnNames as $ColumnName) { $PrimaryKeyIdentifiers[] = [$TableName, $ColumnName]; } $QueryBuilder->AppendIdentifier('INSERT OR REPLACE INTO #', [$TableName]); $QueryBuilder->AppendIdentifiers('(#)', $ColumnNames, ','); //TODO: Fix unique constraint conflicts $this->AppendDataAsInlineTable($QueryBuilder, $Table->GetColumns(), $DerivedTableName, $Rows); }
protected function AppendIdentifier(QueryBuilder $QueryBuilder, E\IdentifierExpression $Expression) { $QueryBuilder->AppendIdentifier('#', $Expression->GetIdentifierSegments()); }
public function AppendCollation(QueryBuilder $QueryBuilder, Mysql\Columns\Collation $Trait) { $QueryBuilder->AppendIdentifier('COLLATE #', [$Trait->GetName()]); }
public static function AppendAlterTable(QueryBuilder $Builder, Relational\Table $Table) { $Builder->AppendIdentifier('ALTER TABLE # ', [$Table->GetName()]); }
public function Index(QueryBuilder $QueryBuilder, Table $Table, Mysql\Tables\Index $Trait) { $QueryBuilder->AppendIdentifier($this->MapIndexType($Trait->GetType()) . ' INDEX # ', [$Trait->GetName()]); $QueryBuilder->Append('('); $First = true; foreach ($Trait->GetColumns() as $Column) { if ($First) { $First = false; } else { $QueryBuilder->Append(','); } $ColumnName = $Column->GetName(); $QueryBuilder->AppendIdentifier('#', [$ColumnName]); $QueryBuilder->Append(' ' . $this->MapIndexDirection($Trait->GetColumnDirection($QueryBuilder))); } $QueryBuilder->Append(')'); $StorageType = $Trait->GetStorageType(); if ($StorageType !== null) { $QueryBuilder->Append('USING' . $this->MapIndexStorageType($Trait->GetStorageType())); } }
public final function AppendDataAsInlineTable(QueryBuilder $QueryBuilder, array $Columns, $DerivedTableName, array $ColumnDataArray) { $QueryBuilder->Append(' SELECT '); /* * Apply all the persisting data expressions as a select on the inline table * rather than on every row */ foreach ($QueryBuilder->Delimit($Columns, ', ') as $ColumnName => $Column) { $QueryBuilder->AppendExpression(Expression::PersistData($Column, Expression::Identifier([$DerivedTableName, $ColumnName]))); } $QueryBuilder->Append(' FROM ('); $ColumnDataArray = array_map(function (Relational\ColumnData $ColumnData) { return $ColumnData->GetData(); }, $ColumnDataArray); $ColumnNames = array_map(function ($Column) { return $Column->GetName(); }, $Columns); $Identifiers = array_combine($ColumnNames, array_map(function ($Column) { return $Column->GetIdentifier(); }, $Columns)); $ParameterTypes = $this->GetParamterTypes($Columns); $First = true; $QueryBuilder->Append('SELECT '); foreach ($QueryBuilder->Delimit($ColumnDataArray, ' UNION ALL SELECT ') as $ColumnData) { $FirstValue = true; foreach ($Identifiers as $ColumnName => $Identifier) { if ($FirstValue) { $FirstValue = false; } else { $QueryBuilder->Append(','); } $Value = isset($ColumnData[$Identifier]) ? $ColumnData[$Identifier] : null; $QueryBuilder->AppendSingleValue($Value, $Value === null ? ParameterType::Null : $ParameterTypes[$ColumnName]); if ($First) { $QueryBuilder->AppendIdentifier(' AS #', [$ColumnName]); } } $First = false; } $QueryBuilder->AppendIdentifier(') #', [$DerivedTableName]); }
private function AppendColumnPosition(QueryBuilder $QueryBuilder, Column $PreviousColumn = null) { return $PreviousColumn === null ? $QueryBuilder->Append('FIRST') : $QueryBuilder->AppendIdentifier('AFTER #', [$PreviousColumn->GetName()]); }