mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-06 18:24:26 +08:00
Fix non working addition of new columns in MySQL. See http://www.heidisql.com/forum.php?t=16948
PostgreSQL: Detect all array style types as unknown type, e.g. TEXT[].
This commit is contained in:
@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: HeidiSQL\n"
|
"Project-Id-Version: HeidiSQL\n"
|
||||||
"POT-Creation-Date: 2012-11-05 21:40\n"
|
"POT-Creation-Date: 2012-11-05 21:40\n"
|
||||||
"PO-Revision-Date: 2014-11-13 19:40+0100\n"
|
"PO-Revision-Date: 2014-11-14 18:02+0100\n"
|
||||||
"Last-Translator: Ansgar Becker <anse@heidisql.com>\n"
|
"Last-Translator: Ansgar Becker <anse@heidisql.com>\n"
|
||||||
"Language-Team: English (http://www.transifex.com/projects/p/heidisql/"
|
"Language-Team: English (http://www.transifex.com/projects/p/heidisql/"
|
||||||
"language/en/)\n"
|
"language/en/)\n"
|
||||||
@ -5818,3 +5818,11 @@ msgstr "Unknown datatype oid #%d. Fall back to %s."
|
|||||||
#. Error happening when facing unknown native data types, mainly in PostgreSQL tables and routines. Name of column or argument passed here as a hint for the user.
|
#. Error happening when facing unknown native data types, mainly in PostgreSQL tables and routines. Name of column or argument passed here as a hint for the user.
|
||||||
msgid "Unknown datatype oid #%d for \"%s\". Fall back to %s."
|
msgid "Unknown datatype oid #%d for \"%s\". Fall back to %s."
|
||||||
msgstr "Unknown datatype oid #%d for \"%s\". Fall back to %s."
|
msgstr "Unknown datatype oid #%d for \"%s\". Fall back to %s."
|
||||||
|
|
||||||
|
#. Error happening when facing unknown named data types.
|
||||||
|
msgid "Unknown datatype \"%s\" for \"%s\". Fall back to %s."
|
||||||
|
msgstr "Unknown datatype \"%s\" for \"%s\". Fall back to %s."
|
||||||
|
|
||||||
|
#. Error happening when facing unknown named data types. Name of column or argument passed here as a hint for the user.
|
||||||
|
msgid "Unknown datatype \"%s\". Fall back to %s."
|
||||||
|
msgstr "Unknown datatype \"%s\". Fall back to %s."
|
||||||
|
@ -347,7 +347,6 @@ type
|
|||||||
function ExtractIdentifier(var SQL: String): String;
|
function ExtractIdentifier(var SQL: String): String;
|
||||||
procedure ClearCache(IncludeDBObjects: Boolean);
|
procedure ClearCache(IncludeDBObjects: Boolean);
|
||||||
procedure FetchDbObjects(db: String; var Cache: TDBObjectList); virtual; abstract;
|
procedure FetchDbObjects(db: String; var Cache: TDBObjectList); virtual; abstract;
|
||||||
function NativeToNamedColumnType(NativeType: Integer; Identifier: String=''): TDBDatatype;
|
|
||||||
procedure SetObjectNamesInSelectedDB;
|
procedure SetObjectNamesInSelectedDB;
|
||||||
procedure SetLockedByThread(Value: TThread); virtual;
|
procedure SetLockedByThread(Value: TThread); virtual;
|
||||||
procedure KeepAliveTimerEvent(Sender: TObject);
|
procedure KeepAliveTimerEvent(Sender: TObject);
|
||||||
@ -387,7 +386,8 @@ type
|
|||||||
procedure ParseViewStructure(CreateCode: String; DBObj: TDBObject; Columns: TTableColumnList;
|
procedure ParseViewStructure(CreateCode: String; DBObj: TDBObject; Columns: TTableColumnList;
|
||||||
var Algorithm, Definer, SQLSecurity, CheckOption, SelectCode: String);
|
var Algorithm, Definer, SQLSecurity, CheckOption, SelectCode: String);
|
||||||
procedure ParseRoutineStructure(Obj: TDBObject; Parameters: TRoutineParamList);
|
procedure ParseRoutineStructure(Obj: TDBObject; Parameters: TRoutineParamList);
|
||||||
function GetDatatypeByName(var DataType: String; DeleteFromSource: Boolean): TDBDatatype;
|
function GetDatatypeByName(var DataType: String; DeleteFromSource: Boolean; Identifier: String=''): TDBDatatype;
|
||||||
|
function GetDatatypeByNativeType(NativeType: Integer; Identifier: String=''): TDBDatatype;
|
||||||
function ApplyLimitClause(QueryType, QueryBody: String; Limit, Offset: Int64): String;
|
function ApplyLimitClause(QueryType, QueryBody: String; Limit, Offset: Int64): String;
|
||||||
function LikeClauseTail: String;
|
function LikeClauseTail: String;
|
||||||
property Parameters: TConnectionParameters read FParameters write FParameters;
|
property Parameters: TConnectionParameters read FParameters write FParameters;
|
||||||
@ -1428,12 +1428,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TDBConnection.GetDatatypeByName(var DataType: String; DeleteFromSource: Boolean): TDBDatatype;
|
function TDBConnection.GetDatatypeByName(var DataType: String; DeleteFromSource: Boolean; Identifier: String=''): TDBDatatype;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
Match: Boolean;
|
Match: Boolean;
|
||||||
rx: TRegExpr;
|
rx: TRegExpr;
|
||||||
Types: String;
|
Types, tmp: String;
|
||||||
begin
|
begin
|
||||||
rx := TRegExpr.Create;
|
rx := TRegExpr.Create;
|
||||||
rx.ModifierI := True;
|
rx.ModifierI := True;
|
||||||
@ -1442,18 +1442,62 @@ begin
|
|||||||
Types := FDatatypes[i].Name;
|
Types := FDatatypes[i].Name;
|
||||||
if FDatatypes[i].Names <> '' then
|
if FDatatypes[i].Names <> '' then
|
||||||
Types := Types + '|' + FDatatypes[i].Names;
|
Types := Types + '|' + FDatatypes[i].Names;
|
||||||
rx.Expression := '^(\"?)('+Types+')(\"?)(\s|\()';
|
rx.Expression := '^('+Types+')\b(\[\])?';
|
||||||
Match := rx.Exec(Datatype);
|
Match := rx.Exec(DataType);
|
||||||
if Match then begin
|
if Match then begin
|
||||||
if DeleteFromSource then
|
if (FParameters.NetTypeGroup = ngPgSQL) and (rx.MatchLen[2] > 0) then begin
|
||||||
Delete(DataType, 1, rx.MatchLen[1]+rx.MatchLen[2]+rx.MatchLen[3]);
|
// TODO: detect array style datatypes, e.g. TEXT[]
|
||||||
Result := FDatatypes[i];
|
end else begin
|
||||||
|
if DeleteFromSource then
|
||||||
|
Delete(DataType, 1, rx.MatchLen[1]);
|
||||||
|
Result := FDatatypes[i];
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if (not Match) and (FParameters.NetTypeGroup = ngPgSQL) then begin
|
||||||
|
// Fall back to unknown type
|
||||||
|
Result := Datatypes[0];
|
||||||
|
rx.Expression := '^(\S+)';
|
||||||
|
if rx.Exec(DataType) then
|
||||||
|
tmp := rx.Match[1]
|
||||||
|
else
|
||||||
|
tmp := DataType;
|
||||||
|
if Identifier <> '' then
|
||||||
|
Log(lcError, f_('Unknown datatype "%s" for "%s". Fall back to %s.', [tmp, Identifier, Result.Name]))
|
||||||
|
else
|
||||||
|
Log(lcError, f_('Unknown datatype "%s". Fall back to %s.', [tmp, Result.Name]));
|
||||||
|
end;
|
||||||
|
rx.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TDBConnection.GetDatatypeByNativeType(NativeType: Integer; Identifier: String=''): TDBDatatype;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
rx: TRegExpr;
|
||||||
|
TypeFound: Boolean;
|
||||||
|
begin
|
||||||
|
rx := TRegExpr.Create;
|
||||||
|
TypeFound := False;
|
||||||
|
for i:=0 to High(Datatypes) do begin
|
||||||
|
if Datatypes[i].NativeTypes = '' then
|
||||||
|
Continue;
|
||||||
|
rx.Expression := '\b('+Datatypes[i].NativeTypes+')\b';
|
||||||
|
if rx.Exec(IntToStr(NativeType)) then begin
|
||||||
|
Result := Datatypes[i];
|
||||||
|
TypeFound := True;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
rx.Free;
|
if not TypeFound then begin
|
||||||
if (not Match) and (FParameters.NetTypeGroup = ngPgSQL) then
|
// Fall back to unknown type
|
||||||
Result := FDatatypes[0];
|
Result := Datatypes[0];
|
||||||
|
if Identifier <> '' then
|
||||||
|
Log(lcError, f_('Unknown datatype oid #%d for "%s". Fall back to %s.', [NativeType, Identifier, Result.Name]))
|
||||||
|
else
|
||||||
|
Log(lcError, f_('Unknown datatype oid #%d. Fall back to %s.', [NativeType, Result.Name]));
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -2537,7 +2581,7 @@ end;
|
|||||||
function TDBConnection.GetCreateCode(Database, Schema, Name: String; NodeType: TListNodeType): String;
|
function TDBConnection.GetCreateCode(Database, Schema, Name: String; NodeType: TListNodeType): String;
|
||||||
var
|
var
|
||||||
Cols, Keys, ProcDetails: TDBQuery;
|
Cols, Keys, ProcDetails: TDBQuery;
|
||||||
ConstraintName, MaxLen, ArgDataType: String;
|
ConstraintName, MaxLen, DataType: String;
|
||||||
ColNames, ArgNames, ArgTypes, Arguments: TStringList;
|
ColNames, ArgNames, ArgTypes, Arguments: TStringList;
|
||||||
Rows: TStringList;
|
Rows: TStringList;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
@ -2563,7 +2607,7 @@ begin
|
|||||||
Cols := GetResults('SELECT '+
|
Cols := GetResults('SELECT '+
|
||||||
' DISTINCT a.attname AS column_name, '+
|
' DISTINCT a.attname AS column_name, '+
|
||||||
' a.attnum, '+
|
' a.attnum, '+
|
||||||
' a.atttypid, '+ // Data type oid. See NativeToNamedColumnType()
|
' a.atttypid, '+ // Data type oid. See GetDatatypeByNativeType()
|
||||||
' FORMAT_TYPE(a.atttypid, a.atttypmod) AS data_type, '+
|
' FORMAT_TYPE(a.atttypid, a.atttypmod) AS data_type, '+
|
||||||
' CASE a.attnotnull WHEN false THEN '+EscapeString('YES')+' ELSE '+EscapeString('NO')+' END AS IS_NULLABLE, '+
|
' CASE a.attnotnull WHEN false THEN '+EscapeString('YES')+' ELSE '+EscapeString('NO')+' END AS IS_NULLABLE, '+
|
||||||
' com.description AS column_comment, '+
|
' com.description AS column_comment, '+
|
||||||
@ -2592,7 +2636,9 @@ begin
|
|||||||
while not Cols.Eof do begin
|
while not Cols.Eof do begin
|
||||||
if Cols.ColExists('atttypid') then
|
if Cols.ColExists('atttypid') then
|
||||||
Log(lcDebug, 'Column "'+Cols.Col('COLUMN_NAME')+'" => oid #'+Cols.Col('atttypid'));
|
Log(lcDebug, 'Column "'+Cols.Col('COLUMN_NAME')+'" => oid #'+Cols.Col('atttypid'));
|
||||||
Result := Result + CRLF + #9 + QuoteIdent(Cols.Col('COLUMN_NAME')) + ' ' + UpperCase(Cols.Col('DATA_TYPE'));
|
DataType := Cols.Col('DATA_TYPE');
|
||||||
|
DataType := DataType.ToUpper.DeQuotedString('"');
|
||||||
|
Result := Result + CRLF + #9 + QuoteIdent(Cols.Col('COLUMN_NAME')) + ' ' + DataType;
|
||||||
if not Cols.IsNull('CHARACTER_MAXIMUM_LENGTH') then begin
|
if not Cols.IsNull('CHARACTER_MAXIMUM_LENGTH') then begin
|
||||||
MaxLen := Cols.Col('CHARACTER_MAXIMUM_LENGTH');
|
MaxLen := Cols.Col('CHARACTER_MAXIMUM_LENGTH');
|
||||||
if MaxLen = '-1' then
|
if MaxLen = '-1' then
|
||||||
@ -2724,13 +2770,13 @@ begin
|
|||||||
Arguments := TStringList.Create;
|
Arguments := TStringList.Create;
|
||||||
for i:=0 to ArgNames.Count-1 do begin
|
for i:=0 to ArgNames.Count-1 do begin
|
||||||
if ArgTypes.Count > i then
|
if ArgTypes.Count > i then
|
||||||
ArgDataType := NativeToNamedColumnType(MakeInt(ArgTypes[i]), ArgNames[i]).Name
|
DataType := GetDatatypeByNativeType(MakeInt(ArgTypes[i]), ArgNames[i]).Name
|
||||||
else
|
else
|
||||||
ArgDataType := '';
|
DataType := '';
|
||||||
Arguments.Add(ArgNames[i] + ' ' + ArgDataType);
|
Arguments.Add(ArgNames[i] + ' ' + DataType);
|
||||||
end;
|
end;
|
||||||
Result := Result + '(' + implodestr(', ', Arguments) + ') '+
|
Result := Result + '(' + implodestr(', ', Arguments) + ') '+
|
||||||
'RETURNS '+NativeToNamedColumnType(MakeInt(ProcDetails.Col('prorettype'))).Name+' '+
|
'RETURNS '+GetDatatypeByNativeType(MakeInt(ProcDetails.Col('prorettype'))).Name+' '+
|
||||||
'AS $$ '+ProcDetails.Col('prosrc')+' $$'
|
'AS $$ '+ProcDetails.Col('prosrc')+' $$'
|
||||||
// TODO: 'LANGUAGE SQL IMMUTABLE STRICT'
|
// TODO: 'LANGUAGE SQL IMMUTABLE STRICT'
|
||||||
;
|
;
|
||||||
@ -4246,35 +4292,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TDBConnection.NativeToNamedColumnType(NativeType: Integer; Identifier: String=''): TDBDatatype;
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
rx: TRegExpr;
|
|
||||||
TypeFound: Boolean;
|
|
||||||
begin
|
|
||||||
rx := TRegExpr.Create;
|
|
||||||
TypeFound := False;
|
|
||||||
for i:=0 to High(Datatypes) do begin
|
|
||||||
if Datatypes[i].NativeTypes = '' then
|
|
||||||
Continue;
|
|
||||||
rx.Expression := '\b('+Datatypes[i].NativeTypes+')\b';
|
|
||||||
if rx.Exec(IntToStr(NativeType)) then begin
|
|
||||||
Result := Datatypes[i];
|
|
||||||
TypeFound := True;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
if not TypeFound then begin
|
|
||||||
// Fall back to unknown type
|
|
||||||
Result := Datatypes[0];
|
|
||||||
if Identifier <> '' then
|
|
||||||
Log(lcError, f_('Unknown datatype oid #%d for "%s". Fall back to %s.', [NativeType, Identifier, Result.Name]))
|
|
||||||
else
|
|
||||||
Log(lcError, f_('Unknown datatype oid #%d. Fall back to %s.', [NativeType, Result.Name]));
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TDBConnection.SetObjectNamesInSelectedDB;
|
procedure TDBConnection.SetObjectNamesInSelectedDB;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
@ -4476,7 +4493,7 @@ begin
|
|||||||
Col.LengthCustomized := False;
|
Col.LengthCustomized := False;
|
||||||
|
|
||||||
// Datatype
|
// Datatype
|
||||||
Col.DataType := GetDatatypeByName(ColSpec, True);
|
Col.DataType := GetDatatypeByName(ColSpec, True, Col.Name);
|
||||||
Col.OldDataType := Col.DataType;
|
Col.OldDataType := Col.DataType;
|
||||||
|
|
||||||
// Length / Set
|
// Length / Set
|
||||||
@ -4726,7 +4743,7 @@ begin
|
|||||||
Col.Name := Results.Col('COLUMN_NAME');
|
Col.Name := Results.Col('COLUMN_NAME');
|
||||||
Col.AllowNull := UpperCase(Results.Col('IS_NULLABLE')) = 'YES';
|
Col.AllowNull := UpperCase(Results.Col('IS_NULLABLE')) = 'YES';
|
||||||
DataType := Results.Col('DATA_TYPE');
|
DataType := Results.Col('DATA_TYPE');
|
||||||
Col.DataType := GetDatatypeByName(DataType, False);
|
Col.DataType := GetDatatypeByName(DataType, False, Col.Name);
|
||||||
if Results.ColExists('COLUMN_TYPE') then begin
|
if Results.ColExists('COLUMN_TYPE') then begin
|
||||||
// Use MySQL's proprietary column_type - the only way to get SET and ENUM values
|
// Use MySQL's proprietary column_type - the only way to get SET and ENUM values
|
||||||
if rx.Exec(Results.Col('COLUMN_TYPE')) then begin
|
if rx.Exec(Results.Col('COLUMN_TYPE')) then begin
|
||||||
@ -5241,7 +5258,7 @@ begin
|
|||||||
FColumnOrgNames.Add(FColumnNames[FColumnNames.Count-1]);
|
FColumnOrgNames.Add(FColumnNames[FColumnNames.Count-1]);
|
||||||
FieldTypeOID := PQftype(LastResult, i);
|
FieldTypeOID := PQftype(LastResult, i);
|
||||||
TypeFound := False;
|
TypeFound := False;
|
||||||
FColumnTypes[i] := FConnection.NativeToNamedColumnType(FieldTypeOID, FColumnNames[FColumnNames.Count-1]);
|
FColumnTypes[i] := FConnection.GetDatatypeByNativeType(FieldTypeOID, FColumnNames[FColumnNames.Count-1]);
|
||||||
end;
|
end;
|
||||||
rx.Free;
|
rx.Free;
|
||||||
FRecNo := -1;
|
FRecNo := -1;
|
||||||
|
@ -1505,7 +1505,7 @@ begin
|
|||||||
FTreeSelect.Font.Size := FCellFont.Size;
|
FTreeSelect.Font.Size := FCellFont.Size;
|
||||||
|
|
||||||
// Find and select current datatype in tree
|
// Find and select current datatype in tree
|
||||||
dt := FTableColumn.Connection.GetDataTypeByName(FCellText, False);
|
dt := FTableColumn.Connection.GetDataTypeByName(FCellText, False, FTableColumn.Name);
|
||||||
CatNode := FTreeSelect.GetFirst;
|
CatNode := FTreeSelect.GetFirst;
|
||||||
while Assigned(CatNode) do begin
|
while Assigned(CatNode) do begin
|
||||||
// Since recent update to VT 5.2.1 we need to initialize root nodes by hand for some reason:
|
// Since recent update to VT 5.2.1 we need to initialize root nodes by hand for some reason:
|
||||||
@ -1629,7 +1629,7 @@ begin
|
|||||||
FMemoHelp.Width := Min(250, FTreeSelect.Left);
|
FMemoHelp.Width := Min(250, FTreeSelect.Left);
|
||||||
FMemoHelp.Left := FTreeSelect.Left - FMemoHelp.Width + (Integer(FTreeSelect.Indent) Div 2);
|
FMemoHelp.Left := FTreeSelect.Left - FMemoHelp.Width + (Integer(FTreeSelect.Indent) Div 2);
|
||||||
FMemoHelp.Top := FTreeSelect.Top + R.Top + 3;
|
FMemoHelp.Top := FTreeSelect.Top + R.Top + 3;
|
||||||
FMemoHelp.Text := FTableColumn.Connection.GetDatatypeByName(NodeText, False).Description;
|
FMemoHelp.Text := FTableColumn.Connection.GetDatatypeByName(NodeText, False, FTableColumn.Name).Description;
|
||||||
// Calc height of memo
|
// Calc height of memo
|
||||||
bmp := TBitMap.Create;
|
bmp := TBitMap.Create;
|
||||||
bmp.Canvas.Font.Assign(FMemoHelp.Font);
|
bmp.Canvas.Font.Assign(FMemoHelp.Font);
|
||||||
|
@ -1190,7 +1190,7 @@ begin
|
|||||||
Col.Name := NewText;
|
Col.Name := NewText;
|
||||||
end;
|
end;
|
||||||
2: begin // Data type
|
2: begin // Data type
|
||||||
Col.DataType := DBObject.Connection.GetDatatypeByName(NewText, False);
|
Col.DataType := DBObject.Connection.GetDatatypeByName(NewText, False, Col.Name);
|
||||||
// Reset length/set for column types which don't support that
|
// Reset length/set for column types which don't support that
|
||||||
if not Col.DataType.HasLength then
|
if not Col.DataType.HasLength then
|
||||||
Col.LengthSet := '';
|
Col.LengthSet := '';
|
||||||
|
Reference in New Issue
Block a user