Support serial columns in Posgres, which is different from auto_increment on MySQL. Affects grid editing and table designer. Closes #279

This commit is contained in:
Ansgar Becker
2023-05-13 10:03:07 +02:00
parent ac9028c627
commit 7d9f59381f
4 changed files with 61 additions and 16 deletions

View File

@ -347,7 +347,7 @@ end;
procedure TCopyTableForm.btnOKClick(Sender: TObject);
var
CreateCode, InsertCode, TargetTable, DataCols, Msg: String;
TableExistence: String;
TableExistence, AutoIncName: String;
ParentNode, Node: PVirtualNode;
DoData, AutoIncGetsKey, AutoIncRemoved, TableHasAutoInc: Boolean;
SelectedColumns: TTableColumnList;
@ -409,9 +409,11 @@ begin
// Columns code. Remove auto_increment attribute if pkey was unchecked, to overcome
// "there can be only one auto column and it must be defined as a key"
AutoIncName := 'unknown';
for Column in SelectedColumns do begin
AutoIncGetsKey := False;
AutoIncRemoved := False;
AutoIncName := Column.AutoIncName;
if Column.DefaultType = cdtAutoInc then begin
for Key in SelectedKeys do begin
// Don't check index type, MySQL allows auto-increment columns on nearly all indexes
@ -486,7 +488,7 @@ begin
Screen.Cursor := crDefault;
Msg := E.Message;
if FConnection.LastErrorCode = ER_WRONG_AUTO_KEY then
Msg := Msg + CRLF + CRLF + f_('Please select the required index for the %s flag.', ['auto_increment']);
Msg := Msg + CRLF + CRLF + f_('Please select the required index for the %s flag.', [AutoIncName]);
ErrorDialog(Msg);
ModalResult := mrNone;
end;

View File

@ -61,6 +61,7 @@ type
function CastAsText: String;
property Status: TEditingStatus read FStatus write SetStatus;
property Connection: TDBConnection read FConnection;
function AutoIncName: String;
end;
PTableColumn = ^TTableColumn;
TTableColumnList = class(TObjectList<TTableColumn>)
@ -425,7 +426,7 @@ type
spGlobalStatus, spCommandsCounters, spSessionVariables, spGlobalVariables,
spISSchemaCol,
spUSEQuery, spKillQuery, spKillProcess,
spFuncLength, spFuncCeil, spFuncLeft, spFuncNow,
spFuncLength, spFuncCeil, spFuncLeft, spFuncNow, spFuncLastAutoIncNumber,
spLockedTables, spDisableForeignKeyChecks, spEnableForeignKeyChecks,
spOrderAsc, spOrderDesc);
@ -3071,6 +3072,7 @@ begin
FSQLSpecifities[spFuncCeil] := 'CEIL';
FSQLSpecifities[spFuncLeft] := IfThen(Parameters.IsProxySQLAdmin, 'SUBSTR(%s, 1, %d)', 'LEFT(%s, %d)');
FSQLSpecifities[spFuncNow] := IfThen(Parameters.IsProxySQLAdmin, 'CURRENT_TIMESTAMP', 'NOW()');
FSQLSpecifities[spFuncLastAutoIncNumber] := 'LAST_INSERT_ID()';
FSQLSpecifities[spLockedTables] := '';
FSQLSpecifities[spDisableForeignKeyChecks] := 'SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0';
FSQLSpecifities[spEnableForeignKeyChecks] := 'SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1)';
@ -3094,6 +3096,7 @@ begin
FSQLSpecifities[spFuncCeil] := 'CEILING';
FSQLSpecifities[spFuncLeft] := 'LEFT(%s, %d)';
FSQLSpecifities[spFuncNow] := 'GETDATE()';
FSQLSpecifities[spFuncLastAutoIncNumber] := 'LAST_INSERT_ID()';
FSQLSpecifities[spLockedTables] := '';
FSQLSpecifities[spDisableForeignKeyChecks] := '';
FSQLSpecifities[spEnableForeignKeyChecks] := '';
@ -3119,6 +3122,7 @@ begin
FSQLSpecifities[spFuncCeil] := 'CEIL';
FSQLSpecifities[spFuncLeft] := 'SUBSTRING(%s, 1, %d)';
FSQLSpecifities[spFuncNow] := 'NOW()';
FSQLSpecifities[spFuncLastAutoIncNumber] := 'LASTVAL()';
FSQLSpecifities[spLockedTables] := '';
FSQLSpecifities[spDisableForeignKeyChecks] := '';
FSQLSpecifities[spEnableForeignKeyChecks] := '';
@ -3143,6 +3147,7 @@ begin
FSQLSpecifities[spFuncCeil] := 'CEIL';
FSQLSpecifities[spFuncLeft] := 'SUBSTR(%s, 1, %d)';
FSQLSpecifities[spFuncNow] := 'DATETIME()';
FSQLSpecifities[spFuncLastAutoIncNumber] := 'LAST_INSERT_ID()';
FSQLSpecifities[spLockedTables] := '';
FSQLSpecifities[spDisableForeignKeyChecks] := '';
FSQLSpecifities[spEnableForeignKeyChecks] := '';
@ -3170,6 +3175,7 @@ begin
FSQLSpecifities[spFuncCeil] := 'CEIL';
FSQLSpecifities[spFuncLeft] := 'SUBSTR(%s, 1, %d)';
FSQLSpecifities[spFuncNow] := ' cast(''now'' as timestamp) from rdb$database';
FSQLSpecifities[spFuncLastAutoIncNumber] := 'LAST_INSERT_ID()';
FSQLSpecifities[spLockedTables] := '';
FSQLSpecifities[spDisableForeignKeyChecks] := '';
FSQLSpecifities[spEnableForeignKeyChecks] := '';
@ -5605,6 +5611,9 @@ begin
// from an expression:
Result := not Value.Contains('(');
end;
end else if FParameters.IsAnyPostgreSQL then begin
// text only if starting with '
Result := Value.StartsWith('''');
end else begin
// MS SQL, PG and SQLite:
Result := True;
@ -5684,20 +5693,30 @@ begin
DefText := ColQuery.Col('COLUMN_DEFAULT');
Col.OnUpdateType := cdtNothing;
if ExecRegExpr('\bauto_increment\b', ExtraText.ToLowerInvariant) then begin
if ColQuery.Col('COLUMN_DEFAULT').StartsWith('nextval(', True) then begin
// PG auto increment
Col.DefaultType := cdtAutoInc;
Col.DefaultText := 'AUTO_INCREMENT';
end else if DefText.ToLowerInvariant = 'null' then begin
Col.DefaultText := ColQuery.Col('COLUMN_DEFAULT');
end
else if ExecRegExpr('\bauto_increment\b', ExtraText.ToLowerInvariant) then begin
// MySQL auto increment
Col.DefaultType := cdtAutoInc;
Col.DefaultText := Col.AutoIncName;
end
else if DefText.ToLowerInvariant = 'null' then begin
Col.DefaultType := cdtNull;
end else if ColQuery.IsNull('COLUMN_DEFAULT') then begin
end
else if ColQuery.IsNull('COLUMN_DEFAULT') then begin
if Col.AllowNull then
Col.DefaultType := cdtNull
else
Col.DefaultType := cdtNothing;
end else if IsTextDefault(DefText, Col.DataType) then begin
end
else if IsTextDefault(DefText, Col.DataType) then begin
Col.DefaultType := cdtText;
Col.DefaultText := IfThen(DefText.StartsWith(''''), ExtractLiteral(DefText, ''), DefText);
end else begin
end
else begin
Col.DefaultType := cdtExpression;
Col.DefaultText := DefText;
end;
@ -5770,7 +5789,7 @@ begin
Col.OnUpdateType := cdtNothing;
if ExecRegExpr('^auto_increment$', ExtraText.ToLowerInvariant) then begin
Col.DefaultType := cdtAutoInc;
Col.DefaultText := 'AUTO_INCREMENT';
Col.DefaultText := Col.AutoIncName;
end else if ColQuery.IsNull('Default') then begin
Col.DefaultType := cdtNothing;
end else if IsTextDefault(DefText, Col.DataType) then begin
@ -9545,7 +9564,7 @@ begin
if Assigned(ColAttr) and (ColAttr.DefaultType = cdtAutoInc) then begin
Row[i].NewText := UnformatNumber(Row[i].NewText);
if Row[i].NewText = '0' then
Row[i].NewText := Connection.GetVar('SELECT LAST_INSERT_ID()');
Row[i].NewText := Connection.GetVar('SELECT ' + Connection.GetSQLSpecifity(spFuncLastAutoIncNumber));
Row[i].NewIsNull := False;
break;
end;
@ -10500,7 +10519,16 @@ begin
end;
if InParts(cpType) then begin
Result := Result + DataType.Name;
case FConnection.Parameters.NetTypeGroup of
ngPgSQL: begin
if DefaultType = cdtAutoInc then
Result := Result + 'SERIAL'
else
Result := Result + DataType.Name;
end;
else Result := Result + DataType.Name;
end;
if (LengthSet <> '') and DataType.HasLength then
Result := Result + '(' + LengthSet + ')';
if (DataType.Category in [dtcInteger, dtcReal]) and Unsigned then
@ -10523,7 +10551,12 @@ begin
// cdtNothing: leave out whole clause
cdtText: Result := Result + 'DEFAULT '+FConnection.EscapeString(DefaultText);
cdtNull: Result := Result + 'DEFAULT NULL';
cdtAutoInc: Result := Result + 'AUTO_INCREMENT';
cdtAutoInc: begin
case FConnection.Parameters.NetTypeGroup of
ngPgSQL:;
else Result := Result + AutoIncName;
end;
end;
cdtExpression: begin
if FConnection.Parameters.IsMySQL(True) and (FConnection.ServerVersionInt >= 80013) then
Result := Result + 'DEFAULT ('+DefaultText+')'
@ -10631,6 +10664,16 @@ begin
end;
end;
function TTableColumn.AutoIncName: String;
begin
case FConnection.Parameters.NetTypeGroup of
ngPgSQL: Result := 'SERIAL';
else Result := 'AUTO_INCREMENT';
end;
end;
procedure TTableColumnList.Assign(Source: TTableColumnList);
var
Item, ItemCopy: TTableColumn;

View File

@ -1358,7 +1358,7 @@ begin
FRadioAutoInc.Width := FRadioAutoInc.Parent.Width - 2 * FRadioAutoInc.Left;
FRadioAutoInc.OnClick := RadioClick;
FRadioAutoInc.OnKeyDown := DoKeyDown;
FRadioAutoInc.Caption := 'AUTO_INCREMENT';
FRadioAutoInc.Caption := Col.AutoIncName;
FBtnOk := TButton.Create(FPanel);
FBtnOk.Parent := FPanel;
@ -1522,7 +1522,7 @@ begin
cdtText: Col.DefaultText := FTextEdit.Text;
cdtNull: Col.DefaultText := 'NULL';
cdtExpression: Col.DefaultText := FExpressionEdit.Text;
cdtAutoInc: Col.DefaultText := 'AUTO_INCREMENT';
cdtAutoInc: Col.DefaultText := Col.AutoIncName;
end;
if FOnUpdateEdit.Text <> '' then

View File

@ -1297,7 +1297,7 @@ begin
cdtText: CellText := Col.Connection.EscapeString(Col.DefaultText);
cdtNull: CellText := 'NULL';
cdtExpression: CellText := Col.DefaultText;
cdtAutoInc: CellText := 'AUTO_INCREMENT';
cdtAutoInc: CellText := Col.AutoIncName;
end;
case Col.OnUpdateType of
// cdtNothing: leave clause away