@@ -490,6 +490,7 @@ TDBConnection = class(TComponent)
490490 FMaxRowsPerInsert: Int64;
491491 FCaseSensitivity: Integer;
492492 FSQLFunctions: TSQLFunctionList;
493+ FNamedEnums: TStringList;
493494 procedure SetActive (Value : Boolean); virtual ; abstract ;
494495 procedure DoBeforeConnect ; virtual ;
495496 procedure StartSSHTunnel (var FinalHost: String; var FinalPort: Integer);
@@ -624,6 +625,7 @@ TDBConnection = class(TComponent)
624625 function IsHex (Text: String): Boolean;
625626 function Has (Item: TFeatureOrRequirement): Boolean;
626627 property SqlProvider: TSqlProvider read FSqlProvider;
628+ property NamedEnums: TStringList read FNamedEnums;
627629 published
628630 property Active: Boolean read FActive write SetActive default False;
629631 property Database: String read FDatabase write SetDatabase;
@@ -2147,6 +2149,9 @@ constructor TDBConnection.Create(AOwner: TComponent);
21472149 FStringQuoteChar := ' '' ' ;
21482150 FCollationTable := nil ;
21492151 FCharsetTable := nil ;
2152+ FQuoteChar := ' "' ;
2153+ FQuoteChars := ' "[]' ;
2154+ FNamedEnums := TStringList.Create;
21502155end ;
21512156
21522157
@@ -2171,8 +2176,6 @@ constructor TAdoDBConnection.Create(AOwner: TComponent);
21712176 i: Integer;
21722177begin
21732178 inherited ;
2174- FQuoteChar := ' "' ;
2175- FQuoteChars := ' "[]' ;
21762179 SetLength(FDatatypes, Length(MSSQLDatatypes));
21772180 for i:=0 to High(MSSQLDatatypes) do
21782181 FDatatypes[i] := MSSQLDatatypes[i];
@@ -2186,7 +2189,6 @@ constructor TPgConnection.Create(AOwner: TComponent);
21862189 i: Integer;
21872190begin
21882191 inherited ;
2189- FQuoteChar := ' "' ;
21902192 FQuoteChars := ' "' ;
21912193 SetLength(FDatatypes, Length(PostGreSQLDatatypes));
21922194 for i:=0 to High(PostGreSQLDatatypes) do
@@ -2203,8 +2205,6 @@ constructor TSQLiteConnection.Create(AOwner: TComponent);
22032205 i: Integer;
22042206begin
22052207 inherited ;
2206- FQuoteChar := ' "' ;
2207- FQuoteChars := ' "[]' ;
22082208 SetLength(FDatatypes, Length(SQLiteDatatypes));
22092209 for i:=0 to High(SQLiteDatatypes) do
22102210 FDatatypes[i] := SQLiteDatatypes[i];
@@ -2218,8 +2218,6 @@ constructor TInterbaseConnection.Create(AOwner: TComponent);
22182218 i: Integer;
22192219begin
22202220 inherited ;
2221- FQuoteChar := ' "' ;
2222- FQuoteChars := ' "[]' ;
22232221 SetLength(FDatatypes, Length(InterbaseDatatypes));
22242222 for i:=0 to High(InterbaseDatatypes) do
22252223 FDatatypes[i] := InterbaseDatatypes[i];
@@ -2234,6 +2232,7 @@ destructor TDBConnection.Destroy;
22342232 FKeepAliveTimer.Free;
22352233 FFavorites.Free;
22362234 FInformationSchemaObjects.Free;
2235+ FNamedEnums.Free;
22372236 if FOwnsParameters then
22382237 FParameters.Free;
22392238 inherited ;
@@ -2309,7 +2308,7 @@ function TDBConnection.GetDatatypeByName(var DataType: String; DeleteFromSource:
23092308 TypesSorted.Free;
23102309 end ;
23112310
2312- rx.Expression := ' ^ (' +Types+' )\b(\[\])?' ;
2311+ rx.Expression := ' \b (' +Types+' )\b(\[\])?' ;
23132312 Match := rx.Exec(DataType);
23142313 // Prefer a later match which is longer than the one found before.
23152314 // See http://www.heidisql.com/forum.php?t=17061
@@ -3389,8 +3388,8 @@ procedure TDBConnection.DoAfterConnect;
33893388var
33903389 i: Integer;
33913390 TypeOid: String;
3392- SubTypes : TDBQuery;
3393- SubTypesList : TStringList;
3391+ AllEnums : TDBQuery;
3392+ AllEnumsList : TStringList;
33943393 SQLFunctionsFileOrder: String;
33953394 MajorMinorVer, MajorVer: String;
33963395 StartupScript: String;
@@ -3416,19 +3415,26 @@ procedure TDBConnection.DoAfterConnect;
34163415 end ;
34173416 end
34183417
3419- else if ExecRegExprI( ' ^[a-z]$ ' , Datatypes[i].NativeTypes) then begin
3418+ else if ( Datatypes[i].NativeTypes = ' e ' ) and FSqlProvider.Has(qGetEnumTypes ) then begin
34203419 // PG ENUM types populated via 'e'
3421- if FSqlProvider.Has(qGetSubDataTypes) then begin
3422- SubTypes := GetResults(FSqlProvider.GetSql(qGetSubDataTypes, [Datatypes[i].NativeTypes]));
3423- SubTypesList := TStringList.Create;
3424- while not SubTypes.Eof do begin
3425- SubTypesList.Add(SubTypes.Col(' enum_name' ));
3426- SubTypesList.Add(SubTypes.Col(' enum_schema' ) + ' .' + SubTypes.Col(' enum_name' ));
3427- SubTypes.Next;
3428- end ;
3429- SubTypes.Free;
3430- Datatypes[i].Names := Implode(' |' , SubTypesList);
3420+ AllEnums := GetResults(FSqlProvider.GetSql(qGetEnumTypes));
3421+ AllEnumsList := TStringList.Create;
3422+ while not AllEnums.Eof do begin
3423+ AllEnumsList.Add(AllEnums.Col(' enum_name' ));
3424+ AllEnumsList.Add(AllEnums.Col(' enum_schema' ) + ' .' + AllEnums.Col(' enum_name' ));
3425+ FNamedEnums.AddPair(
3426+ AllEnums.Col(' enum_name' ),
3427+ AllEnums.Col(' enum_labels' )
3428+ );
3429+ FNamedEnums.AddPair(
3430+ AllEnums.Col(' enum_schema' ) + ' .' + AllEnums.Col(' enum_name' ),
3431+ AllEnums.Col(' enum_labels' )
3432+ );
3433+ AllEnums.Next;
34313434 end ;
3435+ AllEnums.Free;
3436+ Datatypes[i].Names := Implode(' |' , AllEnumsList);
3437+ AllEnumsList.Free;
34323438 end ;
34333439
34343440 end ;
@@ -9131,19 +9137,33 @@ function TDBQuery.ValueList(Column: Integer): TStringList;
91319137 i: Integer;
91329138begin
91339139 Result := TStringList.Create;
9134- Result.QuoteChar := ' '' ' ;
9135- Result.Delimiter := ' ,' ;
91369140 ColAttr := ColAttributes(Column);
91379141 if Assigned(ColAttr) then case ColAttr.DataType.Index of
9142+
91389143 dbdtEnum, dbdtSet: begin
9139- Result.DelimitedText := ColAttr.LengthSet;
9140- // Take care for escaped ENUM definitions, see issue #799
9144+ // Lool up PostgreSQL enum labels in prefetched list
9145+ i := FConnection.NamedEnums.IndexOfName(ColAttr.LengthSet);
9146+ if i > -1 then begin
9147+ Result.Delimiter := ' |' ;
9148+ Result.DelimitedText := FConnection.NamedEnums.ValueFromIndex[i];
9149+ end
9150+ else begin
9151+ // .. or in MySQL Length/Set
9152+ Result.QuoteChar := ' '' ' ;
9153+ Result.Delimiter := ' ,' ;
9154+ Result.DelimitedText := ColAttr.LengthSet;
9155+ end ;
9156+ // In any case, take care for escaped ENUM definitions, see issue #799
91419157 for i:=0 to Result.Count-1 do begin
91429158 Result[i] := FConnection.UnescapeString(Result[i]);
91439159 end ;
91449160 end ;
9145- dbdtBool:
9161+
9162+ dbdtBool: begin
9163+ Result.Delimiter := ' ,' ;
91469164 Result.DelimitedText := ' true,false' ;
9165+ end ;
9166+
91479167 end ;
91489168end ;
91499169
@@ -10754,25 +10774,29 @@ function TTableColumn.SQLCode(OverrideCollation: String=''; Parts: TColumnParts=
1075410774 end ;
1075510775
1075610776 if InParts(cpType) then begin
10757- case FConnection.Parameters.NetTypeGroup of
10758- ngPgSQL: begin
10759- if DefaultType = cdtAutoInc then
10760- Result := Result + ' SERIAL'
10761- else
10762- Result := Result + DataType.Name ;
10777+
10778+ if FConnection.Parameters.IsAnyPostgreSQL and (DefaultType = cdtAutoInc) then begin
10779+ Result := Result + ' SERIAL' ;
10780+ end
10781+ else begin
10782+
10783+ if (DataType.Index = dbdtEnum) and (FConnection.NamedEnums.IndexOfName(LengthSet) > -1 ) then begin
10784+ Result := Result + LengthSet;
10785+ end
10786+ else begin
10787+ Result := Result + DataType.Name ;
10788+ if (LengthSet <> ' ' ) and DataType.HasLength then
10789+ Result := Result + ' (' + LengthSet + ' )' ;
1076310790 end ;
10764- else Result := Result + DataType.Name ;
10765- end ;
1076610791
10767- if (LengthSet <> ' ' ) and DataType.HasLength then
10768- Result := Result + ' (' + LengthSet + ' )' ;
10769- if (DataType.Category in [dtcInteger, dtcReal]) and Unsigned then
10770- Result := Result + ' UNSIGNED' ;
10771- if (DataType.Category in [dtcInteger, dtcReal]) and ZeroFill then
10772- Result := Result + ' ZEROFILL' ;
10773- if Compressed and FConnection.Parameters.IsMariaDB then
10774- Result := Result + ' /*!100301 COMPRESSED*/' ;
10775- Result := Result + ' ' ; // Add space after each part
10792+ if (DataType.Category in [dtcInteger, dtcReal]) and Unsigned then
10793+ Result := Result + ' UNSIGNED' ;
10794+ if (DataType.Category in [dtcInteger, dtcReal]) and ZeroFill then
10795+ Result := Result + ' ZEROFILL' ;
10796+ if Compressed and FConnection.Parameters.IsMariaDB then
10797+ Result := Result + ' /*!100301 COMPRESSED*/' ;
10798+ Result := Result + ' ' ; // Add space after each part
10799+ end ;
1077610800 end ;
1077710801
1077810802 if InParts(cpAllowNull) and (not IsVirtual) and (not FConnection.Parameters.IsAnyMSSQL) then begin
@@ -10883,8 +10907,11 @@ procedure TTableColumn.ParseDatatype(Source: String);
1088310907 LengthSet := ' ' ;
1088410908 end else begin
1088510909 LengthSet := ' ' ;
10886- if DataType.Index = dbdtEnum then
10887- LengthSet := OrgSource;
10910+ if DataType.Index = dbdtEnum then begin
10911+ // Assign PostgreSQL enum type to LengthSet, so we can provide it in table editor
10912+ // Some enum types are wrapped in double quotes
10913+ LengthSet := OrgSource.Trim([FConnection.QuoteChar]);
10914+ end ;
1088810915 end ;
1088910916 Unsigned := ExecRegExpr(' \bunsigned\b' , Source.ToLowerInvariant);
1089010917 ZeroFill := ExecRegExpr(' \bzerofill\b' , Source.ToLowerInvariant);
@@ -10927,8 +10954,12 @@ function TTableColumn.AutoIncName: String;
1092710954function TTableColumn.FullDataType : String;
1092810955begin
1092910956 Result := DataType.Name ;
10930- if not LengthSet.IsEmpty then
10931- Result := Result + ' (' + LengthSet + ' )' ;
10957+ if not LengthSet.IsEmpty then begin
10958+ if (DataType.Index = dbdtEnum) and (FConnection.NamedEnums.IndexOfName(LengthSet) > -1 ) then
10959+ Result := LengthSet
10960+ else
10961+ Result := Result + ' (' + LengthSet + ' )' ;
10962+ end ;
1093210963end ;
1093310964
1093410965
0 commit comments