diff --git a/source/dbconnection.pas b/source/dbconnection.pas index 33c61926..01d199f1 100644 --- a/source/dbconnection.pas +++ b/source/dbconnection.pas @@ -99,7 +99,7 @@ type FStatus: TEditingStatus; constructor Create(AOwner: TDBConnection); destructor Destroy; override; - function SQLCode: String; + function SQLCode(OverrideCollation: String=''): String; function ValueList: TStringList; property Status: TEditingStatus read FStatus write SetStatus; property Connection: TDBConnection read FConnection; @@ -3467,6 +3467,7 @@ begin // Default value Col.DefaultType := cdtNothing; Col.DefaultText := ''; + rxCol.Expression := 'CURRENT_TIMESTAMP(\(\d+\))?(\s+ON\s+UPDATE\s+CURRENT_TIMESTAMP(\(\d+\))?)?'; if UpperCase(Copy(ColSpec, 1, 14)) = 'AUTO_INCREMENT' then begin Col.DefaultType := cdtAutoInc; Col.DefaultText := 'AUTO_INCREMENT'; @@ -3477,10 +3478,12 @@ begin Col.DefaultType := cdtNull; Col.DefaultText := 'NULL'; Delete(ColSpec, 1, 5); - end else if UpperCase(Copy(ColSpec, 1, 17)) = 'CURRENT_TIMESTAMP' then begin + end else if rxCol.Exec(ColSpec) then begin Col.DefaultType := cdtCurTS; Col.DefaultText := 'CURRENT_TIMESTAMP'; - Delete(ColSpec, 1, 18); + if rxCol.Match[2] <> '' then + Col.DefaultType := cdtCurTSUpdateTS; + Delete(ColSpec, 1, rxCol.MatchLen[0]); end else if (ColSpec[1] = '''') or (Copy(ColSpec, 1, 2) = 'b''') then begin InLiteral := True; LiteralStart := Pos('''', ColSpec)+1; @@ -3498,15 +3501,6 @@ begin Delete(ColSpec, 1, i); end; end; - if UpperCase(Copy(ColSpec, 1, 27)) = 'ON UPDATE CURRENT_TIMESTAMP' then begin - // Adjust default type - case Col.DefaultType of - cdtText: Col.DefaultType := cdtTextUpdateTS; - cdtNull: Col.DefaultType := cdtNullUpdateTS; - cdtCurTS: Col.DefaultType := cdtCurTSUpdateTS; - end; - Delete(ColSpec, 1, 28); - end; // Comment Col.Comment := ExtractComment(ColSpec); @@ -5343,9 +5337,10 @@ begin FStatus := Value; end; -function TTableColumn.SQLCode: String; +function TTableColumn.SQLCode(OverrideCollation: String=''): String; var IsVirtual: Boolean; + Text, TSLen: String; begin Result := FConnection.QuoteIdent(Name) + ' ' +DataType.Name; IsVirtual := (Expression <> '') and (Virtuality <> ''); @@ -5361,15 +5356,37 @@ begin Result := Result + ' NULL'; end; if DefaultType <> cdtNothing then begin - Result := Result + ' ' + GetColumnDefaultClause(DefaultType, DataType.Index, DefaultText); + Text := esc(DefaultText); + // Support BIT syntax in MySQL + if DataType.Index = dtBit then + Text := 'b'+Text; + TSLen := ''; + if LengthSet <> '' then + TSLen := '('+LengthSet+')'; + Result := Result + ' '; + case DefaultType of + // cdtNothing: + cdtText: Result := Result + 'DEFAULT '+Text; + cdtTextUpdateTS: Result := Result + 'DEFAULT '+Text+' ON UPDATE CURRENT_TIMESTAMP'+TSLen; + cdtNull: Result := Result + 'DEFAULT NULL'; + cdtNullUpdateTS: Result := Result + 'DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP'+TSLen; + cdtCurTS: Result := Result + 'DEFAULT CURRENT_TIMESTAMP'+TSLen; + cdtCurTSUpdateTS: Result := Result + 'DEFAULT CURRENT_TIMESTAMP'+TSLen+' ON UPDATE CURRENT_TIMESTAMP'+TSLen; + cdtAutoInc: Result := Result + 'AUTO_INCREMENT'; + end; Result := TrimRight(Result); // Remove whitespace for columns without default value end; if IsVirtual then Result := Result + ' AS ('+Expression+') '+Virtuality; if Comment <> '' then Result := Result + ' COMMENT '+esc(Comment); - if Collation <> '' then - Result := Result + ' COLLATE '+esc(Collation); + if Collation <> '' then begin + Result := Result + ' COLLATE '; + if OverrideCollation <> '' then + Result := Result + esc(OverrideCollation) + else + Result := Result + esc(Collation); + end; end; diff --git a/source/helpers.pas b/source/helpers.pas index 3a135b29..f5de7c31 100644 --- a/source/helpers.pas +++ b/source/helpers.pas @@ -306,7 +306,6 @@ type function StringListCompareAnythingDesc(List: TStringList; Index1, Index2: Integer): Integer; function StringListCompareByValue(List: TStringList; Index1, Index2: Integer): Integer; function GetColumnDefaultType(var Text: String): TColumnDefaultType; - function GetColumnDefaultClause(DefaultType: TColumnDefaultType; DataTypeIndex: TDBDatatypeIndex; Text: String): String; function GetImageLinkTimeStamp(const FileName: string): TDateTime; function IsEmpty(Str: String): Boolean; function IsNotEmpty(Str: String): Boolean; @@ -2148,25 +2147,6 @@ begin end; -function GetColumnDefaultClause(DefaultType: TColumnDefaultType; DataTypeIndex: TDBDatatypeIndex; Text: String): String; -begin - Text := esc(Text); - // Support BIT syntax in MySQL - if DataTypeIndex = dtBit then - Text := 'b'+Text; - case DefaultType of - cdtNothing: Result := ''; - cdtText: Result := 'DEFAULT '+Text; - cdtTextUpdateTS: Result := 'DEFAULT '+Text+' ON UPDATE CURRENT_TIMESTAMP'; - cdtNull: Result := 'DEFAULT NULL'; - cdtNullUpdateTS: Result := 'DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP'; - cdtCurTS: Result := 'DEFAULT CURRENT_TIMESTAMP'; - cdtCurTSUpdateTS: Result := 'DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'; - cdtAutoInc: Result := 'AUTO_INCREMENT'; - end; -end; - - {** Return compile date/time from passed .exe name Code taken and modified from Michael Puff diff --git a/source/table_editor.pas b/source/table_editor.pas index b8cd5c9b..f98cfb32 100644 --- a/source/table_editor.pas +++ b/source/table_editor.pas @@ -469,7 +469,7 @@ end; function TfrmTableEditor.ComposeAlterStatement: TSQLBatch; var Specs: TStringList; - ColSpec, IndexSQL, SQL, OldColName: String; + ColSpec, IndexSQL, SQL, OldColName, OverrideCollation: String; i: Integer; Results: TDBQuery; Col, PreviousCol: PTableColumn; @@ -558,36 +558,10 @@ begin Mainform.ProgressStep; Col := listColumns.GetNodeData(Node); if Col.Status <> esUntouched then begin - ColSpec := DBObject.Connection.QuoteIdent(Col.Name); - ColSpec := ColSpec + ' ' + Col.DataType.Name; - IsVirtual := (Col.Expression <> '') and (Col.Virtuality <> ''); - if (Col.LengthSet <> '') and Col.DataType.HasLength then - ColSpec := ColSpec + '(' + Col.LengthSet + ')'; - if (Col.DataType.Category in [dtcInteger, dtcReal]) and Col.Unsigned then - ColSpec := ColSpec + ' UNSIGNED'; - if (Col.DataType.Category in [dtcInteger, dtcReal]) and Col.ZeroFill then - ColSpec := ColSpec + ' ZEROFILL'; - if not IsVirtual then begin - if not Col.AllowNull then - ColSpec := ColSpec + ' NOT'; - ColSpec := ColSpec + ' NULL'; - end; - if Col.DefaultType <> cdtNothing then begin - ColSpec := ColSpec + ' ' + GetColumnDefaultClause(Col.DefaultType, Col.DataType.Index, Col.DefaultText); - ColSpec := TrimRight(ColSpec); // Remove whitespace for columns without default value - end; - if IsVirtual then - ColSpec := ColSpec + ' AS ('+Col.Expression+') '+Col.Virtuality; - if Col.Comment <> '' then - ColSpec := ColSpec + ' COMMENT '+esc(Col.Comment); - if Col.Collation <> '' then begin - ColSpec := ColSpec + ' COLLATE '; - // TODO: Is this the only reason why we don't just use Col.SQLCode? - if chkCharsetConvert.Checked then - ColSpec := ColSpec + esc(comboCollation.Text) - else - ColSpec := ColSpec + esc(Col.Collation); - end; + OverrideCollation := ''; + if chkCharsetConvert.Checked then + OverrideCollation := comboCollation.Text; + ColSpec := Col.SQLCode(OverrideCollation); // Server version requirement, see http://dev.mysql.com/doc/refman/4.1/en/alter-table.html if DBObject.Connection.ServerVersionInt >= 40001 then begin if PreviousCol = nil then