Issue #885: Move types of table keys from global scope constants to class constants in TTableKey definition, to make them stable against mix-ups

This commit is contained in:
Ansgar Becker
2020-02-15 12:51:08 +01:00
parent efc143809b
commit 40908f1bef
3 changed files with 43 additions and 42 deletions

View File

@@ -2,6 +2,7 @@
const
// Line breaks
// TODO: use sLineBreak instead
CRLF = #13#10;
LB_UNIX = #10;
LB_MAC = #13;
@@ -102,12 +103,6 @@ const
MsgInvalidColumn: String = 'Column #%d not available. Query returned %d columns and %d rows.';
SPortableLockFile: String = 'portable.lock';
PKEY = 'PRIMARY';
KEY = 'KEY';
UKEY = 'UNIQUE';
FKEY = 'FULLTEXT';
SKEY = 'SPATIAL';
SYNCOMPLETION_PATTERN = '\image{%d}\hspace{5}\color{clGrayText}%s\column{}\color{clWindowText}%s\color{clGrayText}%s';
HELPERNODE_COLUMNS = 0;

View File

@@ -62,6 +62,12 @@ type
end;
TTableKey = class(TPersistent)
const
PRIMARY = 'PRIMARY';
KEY = 'KEY';
UNIQUE = 'UNIQUE';
FULLTEXT = 'FULLTEXT';
SPATIAL = 'SPATIAL';
private
FConnection: TDBConnection;
function GetImageIndex: Integer;
@@ -4821,7 +4827,7 @@ begin
NewKey.Name := KeyQuery.Col('CONSTRAINT_NAME');
NewKey.OldName := NewKey.Name;
if KeyQuery.Col('CONSTRAINT_TYPE').ToLowerInvariant.StartsWith('primary') then
NewKey.IndexType := 'PRIMARY'
NewKey.IndexType := TTableKey.PRIMARY
else
NewKey.IndexType := KeyQuery.Col('CONSTRAINT_TYPE');
NewKey.OldIndexType := NewKey.IndexType;
@@ -4850,13 +4856,13 @@ begin
NewKey.Name := KeyQuery.Col('Key_name');
NewKey.OldName := NewKey.Name;
if NewKey.Name.ToLowerInvariant = 'primary' then
NewKey.IndexType := 'PRIMARY'
NewKey.IndexType := TTableKey.PRIMARY
else if KeyQuery.Col('Non_unique') = '0' then
NewKey.IndexType := 'UNIQUE'
NewKey.IndexType := TTableKey.UNIQUE
else if KeyQuery.Col('Index_type').ToLowerInvariant = 'fulltext' then
NewKey.IndexType := 'FULLTEXT'
NewKey.IndexType := TTableKey.FULLTEXT
else
NewKey.IndexType := 'KEY';
NewKey.IndexType := TTableKey.KEY;
// Todo: spatial keys
NewKey.OldIndexType := NewKey.IndexType;
if ExecRegExpr('(BTREE|HASH)', KeyQuery.Col('Index_type')) then
@@ -4888,7 +4894,7 @@ begin
' ),'+
' ndx_cols AS ('+
' SELECT pg_class.relname, UNNEST(i.indkey) AS col_ndx,'+
' CASE i.indisprimary WHEN true THEN '+EscapeString('PRIMARY')+' ELSE CASE i.indisunique WHEN true THEN '+EscapeString('UNIQUE')+' ELSE '+EscapeString('KEY')+' END END AS CONSTRAINT_TYPE,'+
' CASE i.indisprimary WHEN true THEN '+EscapeString(TTableKey.PRIMARY)+' ELSE CASE i.indisunique WHEN true THEN '+EscapeString(TTableKey.UNIQUE)+' ELSE '+EscapeString(TTableKey.KEY)+' END END AS CONSTRAINT_TYPE,'+
' pg_class.oid'+
' FROM pg_class'+
' JOIN pg_index i ON (pg_class.oid = i.indexrelid)'+
@@ -4954,7 +4960,7 @@ begin
Result.Add(NewKey);
NewKey.Name := 'PRIMARY';
NewKey.OldName := NewKey.Name;
NewKey.IndexType := 'PRIMARY';
NewKey.IndexType := TTableKey.PRIMARY;
NewKey.OldIndexType := NewKey.IndexType;
end;
NewKey.Columns.Add(ColQuery.Col('name'));
@@ -4969,7 +4975,7 @@ begin
Result.Add(NewKey);
NewKey.Name := KeyQuery.Col('name');
NewKey.OldName := NewKey.Name;
NewKey.IndexType := IfThen(KeyQuery.Col('unique')='0', 'KEY', 'UNIQUE');
NewKey.IndexType := IfThen(KeyQuery.Col('unique')='0', TTableKey.KEY, TTableKey.UNIQUE);
NewKey.OldIndexType := NewKey.IndexType;
ColQuery := GetResults('SELECT * FROM pragma_index_info('+EscapeString(NewKey.Name)+')');
while not ColQuery.Eof do begin
@@ -5948,13 +5954,13 @@ begin
// Find best key for updates
// 1. round: find a primary key
for Key in Keys do begin
if Key.IndexType = PKEY then
if Key.IndexType = TTableKey.PRIMARY then
Result.Assign(Key.Columns);
end;
if Result.Count = 0 then begin
// no primary key available -> 2. round: find a unique key
for Key in Keys do begin
if Key.IndexType = UKEY then begin
if Key.IndexType = TTableKey.UNIQUE then begin
// We found a UNIQUE key - better than nothing. Check if one of the key
// columns allows NULLs which makes it dangerous to use in UPDATES + DELETES.
AllowsNull := False;
@@ -8906,11 +8912,11 @@ end;
function TTableKey.GetImageIndex: Integer;
begin
// Detect key icon index for specified index
if IndexType = PKEY then Result := ICONINDEX_PRIMARYKEY
else if IndexType = KEY then Result := ICONINDEX_INDEXKEY
else if IndexType = UKEY then Result := ICONINDEX_UNIQUEKEY
else if IndexType = FKEY then Result := ICONINDEX_FULLTEXTKEY
else if IndexType = SKEY then Result := ICONINDEX_SPATIALKEY
if IndexType = TTableKey.PRIMARY then Result := ICONINDEX_PRIMARYKEY
else if IndexType = TTableKey.KEY then Result := ICONINDEX_INDEXKEY
else if IndexType = TTableKey.UNIQUE then Result := ICONINDEX_UNIQUEKEY
else if IndexType = TTableKey.FULLTEXT then Result := ICONINDEX_FULLTEXTKEY
else if IndexType = TTableKey.SPATIAL then Result := ICONINDEX_SPATIALKEY
else Result := -1;
end;
@@ -8922,10 +8928,10 @@ begin
// Supress SQL error trying index creation with 0 column
if Columns.Count = 0 then
Exit;
if IndexType = PKEY then
if IndexType = TTableKey.PRIMARY then
Result := Result + 'PRIMARY KEY '
else begin
if IndexType <> KEY then
if IndexType <> TTableKey.KEY then
Result := Result + IndexType + ' ';
Result := Result + 'INDEX ' + FConnection.QuoteIdent(Name) + ' ';
end;

View File

@@ -700,7 +700,7 @@ begin
// Drop indexes, also changed indexes, which will be readded below
for i:=0 to DeletedKeys.Count-1 do begin
Mainform.ProgressStep;
if DeletedKeys[i] = PKEY then
if DeletedKeys[i] = TTableKey.PRIMARY then
IndexSQL := 'PRIMARY KEY'
else
IndexSQL := 'INDEX ' + Conn.QuoteIdent(DeletedKeys[i]);
@@ -710,7 +710,7 @@ begin
for i:=0 to FKeys.Count-1 do begin
Mainform.ProgressStep;
if FKeys[i].Modified and (not FKeys[i].Added) then begin
if FKeys[i].OldIndexType = PKEY then
if FKeys[i].OldIndexType = TTableKey.PRIMARY then
IndexSQL := 'PRIMARY KEY'
else
IndexSQL := 'INDEX ' + Conn.QuoteIdent(FKeys[i].OldName);
@@ -1139,7 +1139,7 @@ begin
// Do not allow NULL, and force NOT NULL, on primary key columns
Result := True;
for i:=0 to FKeys.Count-1 do begin
if (FKeys[i].IndexType = PKEY) and (FKeys[i].Columns.IndexOf(Col.Name) > -1) then begin
if (FKeys[i].IndexType = TTableKey.PRIMARY) and (FKeys[i].Columns.IndexOf(Col.Name) > -1) then begin
if Col.AllowNull then begin
Col.AllowNull := False;
Col.Status := esModified;
@@ -1236,7 +1236,7 @@ begin
Col := Sender.GetNodeData(Node);
// Bold font for primary key columns
for i:=0 to FKeys.Count-1 do begin
if (FKeys[i].IndexType = PKEY) and (FKeys[i].Columns.IndexOf(Col.Name) > -1) then begin
if (FKeys[i].IndexType = TTableKey.PRIMARY) and (FKeys[i].Columns.IndexOf(Col.Name) > -1) then begin
TargetCanvas.Font.Style := TargetCanvas.Font.Style + [fsBold];
break;
end;
@@ -1535,7 +1535,7 @@ begin
TblKey := TTableKey.Create(DBObject.Connection);
TblKey.Name := _('Index')+' '+IntToStr(FKeys.Count+1);
TblKey.OldName := TblKey.Name;
TblKey.IndexType := KEY;
TblKey.IndexType := TTableKey.KEY;
TblKey.OldIndexType := TblKey.IndexType;
TblKey.Added := True;
FKeys.Add(TblKey);
@@ -1576,7 +1576,7 @@ begin
end;
if not ColExists then begin
NewCol := Column.Name;
if (TblKey.IndexType <> FKEY) and (Column.DataType.Index in [dtTinyText, dtText, dtMediumText, dtLongText, dtTinyBlob, dtBlob, dtMediumBlob, dtLongBlob]) then
if (TblKey.IndexType <> TTableKey.FULLTEXT) and (Column.DataType.Index in [dtTinyText, dtText, dtMediumText, dtLongText, dtTinyBlob, dtBlob, dtMediumBlob, dtLongBlob]) then
PartLength := '100';
break;
end;
@@ -1672,7 +1672,7 @@ begin
0: begin
TblKey := FKeys[Node.Index];
case Column of
0: if TblKey.IndexType = PKEY then
0: if TblKey.IndexType = TTableKey.PRIMARY then
CellText := TblKey.IndexType + ' KEY' // Fixed name "PRIMARY KEY", cannot be changed
else
CellText := TblKey.Name;
@@ -1766,7 +1766,7 @@ begin
Allowed := False;
if VT.GetNodeLevel(Node) = 0 then begin
// Disallow renaming primary key
if (Column <> 0) or (VT.Text[Node, 1] <> PKEY) then
if (Column <> 0) or (VT.Text[Node, 1] <> TTableKey.PRIMARY) then
Allowed := True
end else case Column of
0: Allowed := True;
@@ -1800,7 +1800,7 @@ begin
// Index type pulldown
EnumEditor := TEnumEditorLink.Create(VT, True);
EnumEditor.ValueList := TStringList.Create;
EnumEditor.ValueList.CommaText := PKEY +','+ KEY +','+ UKEY +','+ FKEY +','+ SKEY;
EnumEditor.ValueList.CommaText := TTableKey.PRIMARY +','+ TTableKey.KEY +','+ TTableKey.UNIQUE +','+ TTableKey.FULLTEXT +','+ TTableKey.SPATIAL;
EditLink := EnumEditor;
end else if (Level = 0) and (Column = 2) then begin
// Algorithm pulldown
@@ -1839,8 +1839,8 @@ begin
0: TblKey.Name := NewText;
1: begin
TblKey.IndexType := NewText;
if NewText = PKEY then
TblKey.Name := PKEY;
if NewText = TTableKey.PRIMARY then
TblKey.Name := TTableKey.PRIMARY;
end;
2: TblKey.Algorithm := NewText;
end;
@@ -1968,7 +1968,7 @@ begin
TblKey.Columns.Insert(ColPos, ColName);
PartLength := '';
if (TblKey.IndexType <> FKEY) and (Col.DataType.Index in [dtTinyText, dtText, dtMediumText, dtLongText, dtTinyBlob, dtBlob, dtMediumBlob, dtLongBlob]) then
if (TblKey.IndexType <> TTableKey.FULLTEXT) and (Col.DataType.Index in [dtTinyText, dtText, dtMediumText, dtLongText, dtTinyBlob, dtBlob, dtMediumBlob, dtLongBlob]) then
PartLength := '100';
TblKey.Subparts.Insert(ColPos, PartLength);
IndexNode.States := IndexNode.States + [vsHasChildren, vsExpanded];
@@ -2096,9 +2096,9 @@ begin
// Auto create submenu items for "Add to index" ...
PrimaryKeyExists := False;
for i:=0 to FKeys.Count-1 do begin
if FKeys[i].IndexType = PKEY then begin
if FKeys[i].IndexType = TTableKey.PRIMARY then begin
PrimaryKeyExists := True;
IndexName := PKEY;
IndexName := TTableKey.PRIMARY;
end else
IndexName := FKeys[i].Name + ' ('+FKeys[i].IndexType+')';
Item := AddItem(menuAddToIndex, IndexName, FKeys[i].ImageIndex);
@@ -2118,12 +2118,12 @@ begin
menuAddToIndex.Enabled := menuAddToIndex.Count > 0;
// ... and for item "Create index"
Item := AddItem(menuCreateIndex, PKEY, ICONINDEX_PRIMARYKEY);
Item := AddItem(menuCreateIndex, TTableKey.PRIMARY, ICONINDEX_PRIMARYKEY);
Item.Enabled := not PrimaryKeyExists;
AddItem(menuCreateIndex, KEY, ICONINDEX_INDEXKEY);
AddItem(menuCreateIndex, UKEY, ICONINDEX_UNIQUEKEY);
AddItem(menuCreateIndex, FKEY, ICONINDEX_FULLTEXTKEY);
AddItem(menuCreateIndex, SKEY, ICONINDEX_SPATIALKEY);
AddItem(menuCreateIndex, TTableKey.KEY, ICONINDEX_INDEXKEY);
AddItem(menuCreateIndex, TTableKey.UNIQUE, ICONINDEX_UNIQUEKEY);
AddItem(menuCreateIndex, TTableKey.FULLTEXT, ICONINDEX_FULLTEXTKEY);
AddItem(menuCreateIndex, TTableKey.SPATIAL, ICONINDEX_SPATIALKEY);
end;