Browse Source

* TSQLQuery.StatementType should not be published
* Quote fieldnames in ApplyUpdates for connections which needs this + test (bug 9661)
* Do not try to update the indexdefinitions if the TableName is unknown
* Try to obtain the TableName even if the dataset is readonly

git-svn-id: trunk@9119 -

joost 18 years ago
parent
commit
9080909740

+ 1 - 1
packages/fcl-db/src/sqldb/interbase/ibconnection.pp

@@ -162,7 +162,7 @@ constructor TIBConnection.Create(AOwner : TComponent);
 
 begin
   inherited;
-  FConnOptions := FConnOptions + [sqSupportParams] + [sqEscapeRepeat];
+  FConnOptions := FConnOptions + [sqSupportParams] + [sqEscapeRepeat] + [sqQuoteFieldnames];
   FBLobSegmentSize := 80;
   FDialect := -1;
   FDBDialect := -1;

+ 1 - 1
packages/fcl-db/src/sqldb/mysql/mysqlconn.inc

@@ -838,7 +838,7 @@ begin
   qry.database := Self;
   with qry do
     begin
-    ReadOnly := True;
+    ParseSQL := False;
     sql.clear;
     sql.add('show index from ' +  TableName);
     open;

+ 27 - 28
packages/fcl-db/src/sqldb/sqldb.pp

@@ -23,7 +23,7 @@ interface
 uses SysUtils, Classes, DB, bufdataset;
 
 type TSchemaType = (stNoSchema, stTables, stSysTables, stProcedures, stColumns, stProcedureParams, stIndexes, stPackages);
-     TConnOption = (sqSupportParams,sqEscapeSlash,sqEscapeRepeat);
+     TConnOption = (sqSupportParams,sqEscapeSlash,sqEscapeRepeat,sqQuoteFieldnames);
      TConnOptions= set of TConnOption;
 
      TRowsCount = LargeInt;
@@ -185,7 +185,6 @@ type
     FParams              : TParams;
     FusePrimaryKeyAsKey  : Boolean;
     FSQLBuf              : String;
-    FFromPart            : String;
     FWhereStartPos       : integer;
     FWhereStopPos        : integer;
     FParseSQL            : boolean;
@@ -200,7 +199,6 @@ type
     FInsertQry           : TCustomSQLQuery;
 
     procedure FreeFldBuffers;
-    procedure InitUpdates(ASQL : string);
     function GetIndexDefs : TIndexDefs;
     function GetStatementType : TStatementType;
     procedure SetReadOnly(AValue : Boolean);
@@ -337,7 +335,6 @@ type
     property Params;
     property UpdateMode;
     property UsePrimaryKeyAsKey;
-    property StatementType;
     property ParseSQL;
     Property DataSource;
     property ServerFilter;
@@ -887,10 +884,7 @@ begin
       Db.PrepareStatement(Fcursor,sqltr,FSQLBuf,FParams);
 
     if (FCursor.FStatementType = stSelect) then
-      begin
       FCursor.FInitFieldDef := True;
-      if not ReadOnly then InitUpdates(FSQLBuf);
-      end;
     end;
 end;
 
@@ -987,6 +981,7 @@ Var
   EndOfComment            : Boolean;
   BracketCount            : Integer;
   ConnOptions             : TConnOptions;
+  FFromPart               : String;
 
 begin
   PSQL:=Pchar(ASQL);
@@ -1071,9 +1066,21 @@ begin
                          ParsePart := ppBogus;
                          StrLength := CurrentP-PStatementPart;
                          end;
-                       Setlength(FFromPart,StrLength);
-                       Move(PStatementPart^,FFromPart[1],(StrLength));
-                       FFrompart := trim(FFrompart);
+                       if FCursor.FStatementType = stSelect then
+                         begin
+                         Setlength(FFromPart,StrLength);
+                         Move(PStatementPart^,FFromPart[1],(StrLength));
+                         FFrompart := trim(FFrompart);
+                       
+                         if pos(',',FFromPart) > 0 then
+                           FUpdateable := False // select-statements from more then one table are not updateable
+                         else
+                           begin
+                           FUpdateable := True;
+                           FTableName := FFromPart;
+                           end;
+                         end;
+
                        FWhereStartPos := PStatementPart-PSQL+StrLength+1;
                        PStatementPart := CurrentP;
                        end;
@@ -1103,20 +1110,6 @@ begin
     end
 end;
 
-procedure TCustomSQLQuery.InitUpdates(ASQL : string);
-
-
-begin
-  if pos(',',FFromPart) > 0 then
-    FUpdateable := False // select-statements from more then one table are not updateable
-  else
-    begin
-    FUpdateable := True;
-    FTableName := FFromPart;
-    end;
-
-end;
-
 procedure TCustomSQLQuery.InternalOpen;
 
   procedure InitialiseModifyQuery(var qry : TCustomSQLQuery; aSQL: TSTringList);
@@ -1288,19 +1281,21 @@ end;
 Procedure TCustomSQLQuery.UpdateIndexDefs;
 
 begin
-  if assigned(DataBase) then
+  if assigned(DataBase) and (FTableName<>'') then
     TSQLConnection(DataBase).UpdateIndexDefs(FIndexDefs,FTableName);
 end;
 
 Procedure TCustomSQLQuery.ApplyRecUpdate(UpdateKind : TUpdateKind);
 
+var FieldNamesQuoteChar : char;
+
   procedure UpdateWherePart(var sql_where : string;x : integer);
 
   begin
     if (pfInKey in Fields[x].ProviderFlags) or
        ((FUpdateMode = upWhereAll) and (pfInWhere in Fields[x].ProviderFlags)) or
        ((FUpdateMode = UpWhereChanged) and (pfInWhere in Fields[x].ProviderFlags) and (fields[x].value <> fields[x].oldvalue)) then
-      sql_where := sql_where + '(' + fields[x].FieldName + '= :OLD_' + fields[x].FieldName + ') and ';
+      sql_where := sql_where + '(' + FieldNamesQuoteChar + fields[x].FieldName + FieldNamesQuoteChar + '= :OLD_' + fields[x].FieldName + ') and ';
   end;
 
   function ModifyRecQuery : string;
@@ -1317,7 +1312,7 @@ Procedure TCustomSQLQuery.ApplyRecUpdate(UpdateKind : TUpdateKind);
       UpdateWherePart(sql_where,x);
 
       if (pfInUpdate in Fields[x].ProviderFlags) then
-        sql_set := sql_set + fields[x].FieldName + '=:' + fields[x].FieldName + ',';
+        sql_set := sql_set +FieldNamesQuoteChar + fields[x].FieldName + FieldNamesQuoteChar +'=:' + fields[x].FieldName + ',';
       end;
 
     if length(sql_set) = 0 then DatabaseError(sNoUpdateFields,self);
@@ -1341,7 +1336,7 @@ Procedure TCustomSQLQuery.ApplyRecUpdate(UpdateKind : TUpdateKind);
       begin
       if (not fields[x].IsNull) and (pfInUpdate in Fields[x].ProviderFlags) then
         begin
-        sql_fields := sql_fields + fields[x].FieldName + ',';
+        sql_fields := sql_fields + FieldNamesQuoteChar + fields[x].FieldName + FieldNamesQuoteChar + ',';
         sql_values := sql_values + ':' + fields[x].FieldName + ',';
         end;
       end;
@@ -1373,6 +1368,10 @@ var qry : TCustomSQLQuery;
     Fld : TField;
     
 begin
+  if sqQuoteFieldnames in TSQLConnection(DataBase).ConnOptions then
+    FieldNamesQuoteChar := '"'
+  else
+    FieldNamesQuoteChar := ' ';
     case UpdateKind of
       ukModify : begin
                  qry := FUpdateQry;

+ 42 - 0
packages/fcl-db/tests/testsqlfieldtypes.pas

@@ -27,6 +27,7 @@ type
     procedure RunTest; override;
   published
     procedure TestInsertLargeStrFields; // bug 9600
+    procedure TestNumericNames; // Bug9661
     procedure Test11Params;
     procedure TestRowsAffected; // bug 9758
     procedure TestStringsReplace;
@@ -896,6 +897,47 @@ begin
     end;
 end;
 
+procedure TTestFieldTypes.TestNumericNames;
+begin
+  with TSQLDBConnector(DBConnector) do
+    begin
+    if sqQuoteFieldnames in Connection.ConnOptions then
+      Connection.ExecuteDirect('create table FPDEV2 (         ' +
+                                '  "2ID" INT NOT NULL            , ' +
+                                '  "3TEST" VARCHAR(10),     ' +
+                                '  PRIMARY KEY ("2ID")           ' +
+                                ')                            ')
+    else
+      Connection.ExecuteDirect('create table FPDEV2 (         ' +
+                                '  2ID INT NOT NULL            , ' +
+                                '  3TEST VARCHAR(10),     ' +
+                                '  PRIMARY KEY (2ID)           ' +
+                                ')                            ');
+// Firebird/Interbase need a commit after a DDL statement. Not necessary for the other connections
+    TSQLDBConnector(DBConnector).Transaction.CommitRetaining;
+    with query do
+      begin
+      SQL.Text:='select * from FPDEV2';
+      Open;
+      Edit;
+      fieldbyname('2ID').AsInteger:=1;
+      fieldbyname('3TEST').AsString:='3test';
+      Post;
+      ApplyUpdates(0);
+      close;
+      open;
+      AssertEquals('3test',FieldByName('3TEST').AsString);
+      Edit;
+      fieldbyname('3TEST').AsString:='test3';
+      Post;
+      ApplyUpdates(0);
+      open;
+      AssertEquals('test3',FieldByName('3TEST').AsString);
+      close;
+      end;
+    end;
+end;
+
 procedure TTestFieldTypes.TestRowsAffected;
 begin
   with TSQLDBConnector(DBConnector) do