Browse Source

Merged revisions 9921,10052,10082,10129-10130,10137-10138,10140-10146,10148-10153,10160-10161,10168,10170,10172,10176-10178,10180,10183-10184,10187-10188,10191-10192,10200-10201,10203-10204,10206,10232,10234,10238-10239,10243,10251,10253-10254,10264,10266,10271,10273,10276-10279,10286-10294,10298,10300,10307,10309,10313,10319,10340-10347,10349-10350,10352-10361 via svnmerge from
svn+ssh://[email protected]/FPC/svn/fpc/trunk

........
r9921 | joost | 2008-01-26 13:24:15 +0100 (Sat, 26 Jan 2008) | 1 line

* Updated script te create testsuite-database
........
r10052 | joost | 2008-01-27 16:03:50 +0100 (Sun, 27 Jan 2008) | 1 line

* Some refactoring and added TestSetBlobAsBlobParam
........
r10307 | joost | 2008-02-11 23:06:00 +0100 (Mon, 11 Feb 2008) | 2 lines

* Moved FCurrentRecBuf from the index to TBufDataset itself
* Add new (inserted) records to all indexes
........
r10340 | joost | 2008-02-16 19:58:08 +0100 (Sat, 16 Feb 2008) | 1 line

* Fixed mem-leak
........
r10341 | joost | 2008-02-16 22:08:54 +0100 (Sat, 16 Feb 2008) | 1 line

* Patch from Jesus Reyes to set a default for ParseSQL (bug 10798)
........
r10342 | joost | 2008-02-16 22:18:18 +0100 (Sat, 16 Feb 2008) | 4 lines

Patch from Luiz Americo:
* Replace StrPas by String
* Removes unnecessary code
* Format surrounding code
........
r10344 | joost | 2008-02-16 23:07:44 +0100 (Sat, 16 Feb 2008) | 1 line

* Implemented Port property (bug 10533)
........
r10345 | joost | 2008-02-16 23:34:49 +0100 (Sat, 16 Feb 2008) | 1 line

* Patch from Martin Schreiber to fix AV when using postgres 7.x
........
r10346 | joost | 2008-02-16 23:43:30 +0100 (Sat, 16 Feb 2008) | 1 line

* Set the default alignment of TNumericFields to taRightJustify. (Patch from Jesus Reyes, bug #9456)
........
r10347 | joost | 2008-02-17 15:19:46 +0100 (Sun, 17 Feb 2008) | 1 line

* Set the FFirstRecBuf of the default index to nil when the dataset is closed. (Fixes test TestExceptOnsecClose)
........
r10349 | joost | 2008-02-17 21:52:16 +0100 (Sun, 17 Feb 2008) | 1 line

* Fix+test bug #10345
........
r10350 | joost | 2008-02-17 22:14:26 +0100 (Sun, 17 Feb 2008) | 1 line

* Fixed bug #8464
........
r10357 | joost | 2008-02-18 23:42:55 +0100 (Mon, 18 Feb 2008) | 1 line

* Patch from Luiz Americo for bug #10777
........
r10361 | joost | 2008-02-19 20:32:52 +0100 (Tue, 19 Feb 2008) | 1 line

* Do not pass Self to TDataset.SetDataEvent directly. Just to be sure that setting it to something else will not give any problems. (bug 9503)
........

git-svn-id: branches/fixes_2_2@10685 -

joost 17 years ago
parent
commit
871165146a

+ 30 - 23
packages/fcl-db/src/base/bufdataset.pas

@@ -126,7 +126,6 @@ type
     FRecordArray    : array of Pointer;
     FLastRecInd     : integer;
 {$ELSE}
-    FCurrentRecBuf  : PBufRecLinkItem;
     FLastRecBuf     : PBufRecLinkItem;
     FFirstRecBuf    : PBufRecLinkItem;
 {$ENDIF ARRAYBUF}
@@ -145,6 +144,7 @@ type
 
     FIndexesCount   : integer;
     FCurrentIndex   : PBufIndex;
+    FCurrentRecBuf  : PBufRecLinkItem;
 
     FFilterBuffer   : pchar;
     FBRecordCount   : integer;
@@ -491,7 +491,7 @@ begin
 
 // Set FirstRecBuf and FCurrentRecBuf
   AIndex.FFirstRecBuf:=FIndexes[0].FFirstRecBuf;
-  AIndex.FCurrentRecBuf:=AIndex.FFirstRecBuf;
+  FCurrentRecBuf:=AIndex.FFirstRecBuf;
 // Link in the FLastRecBuf that belongs to this index
   PCurRecLinkItem[AIndex.IndNr].next:=AIndex.FLastRecBuf;
   AIndex.FLastRecBuf[AIndex.IndNr].prior:=PCurRecLinkItem;
@@ -653,8 +653,8 @@ begin
     begin
     FFirstRecBuf := pointer(IntAllocRecordBuffer);
     FLastRecBuf := FFirstRecBuf;
-    FCurrentRecBuf := FLastRecBuf;
     end;
+  FCurrentRecBuf := FCurrentIndex^. FLastRecBuf;
 {$ELSE}
   for IndexNr:=0 to FIndexesCount-1 do with FIndexes[IndexNr] do
     begin
@@ -699,15 +699,17 @@ begin
       FCurrentRecBuf := FCurrentRecBuf[IndNr].next;
       FreeRecordBuffer(pc);
       end;
+    FFirstRecBuf:=nil;
 {$ENDIF}
     end;
 
-  for r := 0 to FIndexesCount-1 do with FIndexes[r] do
+  for r := 1 to FIndexesCount-1 do with FIndexes[r] do
     begin
 {$IFDEF ARRAYBUF}
     FreeRecordBuffer(FRecordArray[FLastRecInd]);
     SetLength(FRecordArray,FInitialBuffers);
 {$ELSE}
+    FreeRecordBuffer(pointer(FLastRecBuf));
     FFirstRecBuf:= nil;
 {$ENDIF}
     end;
@@ -964,7 +966,6 @@ begin
   for i := 0 to FIndexesCount-1 do
     if SameText(FIndexes[i].Name,AValue) then
       begin
-      FIndexes[i].FCurrentRecBuf := FCurrentIndex^.FCurrentRecBuf;
       FCurrentIndex:=@FIndexes[i];
       if active then Resync([rmCenter]);
       exit;
@@ -987,7 +988,7 @@ begin
 {$IFDEF ARRAYBUF}
   FCurrentIndex^.FCurrentRecInd:=GetRecordFromBookmark(PBufBookmark(Buffer + FRecordSize)^);
 {$ELSE}
-  FCurrentIndex^.FCurrentRecBuf := PBufBookmark(Buffer + FRecordSize)^.BookmarkData;
+  FCurrentRecBuf := PBufBookmark(Buffer + FRecordSize)^.BookmarkData;
 {$ENDIF}
 end;
 
@@ -1026,7 +1027,7 @@ begin
 {$IFDEF ARRAYBUF}
   FCurrentIndex^.FCurrentRecInd:=GetRecordFromBookmark(PBufBookmark(ABookmark)^);
 {$ELSE}
-  FCurrentIndex^.FCurrentRecBuf := pointer(ABookmark^);
+  FCurrentRecBuf := pointer(ABookmark^);
 {$ENDIF}
 end;
 
@@ -1215,7 +1216,7 @@ begin
       if not ((x=1) and (FIndexes[1].FieldsName='')) then
         begin
         BuildIndex(FIndexes[x]);
-        FIndexes[x].FCurrentRecBuf:=FIndexes[x].FFirstRecBuf;
+        FCurrentRecBuf:=FCurrentIndex^.FFirstRecBuf;
         end;
       end;
     Exit;
@@ -1367,10 +1368,10 @@ begin
   InternalSetToRecord(ActiveBuffer);
 {$IFNDEF ARRAYBUF}
   // Remove the record from all active indexes
-  RemoveRecordFromIndex(FIndexes[0].FCurrentRecBuf,FIndexes[0]);
+  RemoveRecordFromIndex(FCurrentRecBuf,FIndexes[0]);
   if FCurrentIndex=@FIndexes[1] then StartInd := 1 else StartInd := 2;
   for i := StartInd to FIndexesCount-1 do
-    RemoveRecordFromIndex(FIndexes[i].FCurrentRecBuf,FIndexes[i]);
+    RemoveRecordFromIndex(FCurrentRecBuf,FIndexes[i]);
 {$ENDIF}
 
   if not GetRecordUpdateBuffer then
@@ -1547,7 +1548,7 @@ begin
 {$ELSE}
   CheckBrowseMode;
 
-  StoreRecBuf := FCurrentIndex^.FCurrentRecBuf;
+  StoreRecBuf := FCurrentRecBuf;
 
   r := 0;
   FailedCount := 0;
@@ -1615,7 +1616,7 @@ begin
       SetLength(FUpdateBlobBuffers,0);
       end;
 
-    FCurrentIndex^.FCurrentRecBuf := StoreRecBuf;
+    FCurrentRecBuf := StoreRecBuf;
     Resync([]);
   end;
 {$ENDIF}
@@ -1666,7 +1667,7 @@ begin
     begin
     if GetBookmarkFlag(ActiveBuffer) = bfEOF then
       // Append
-      with FCurrentIndex^ do
+      with FIndexes[0] do
 {$IFDEF ARRAYBUF}
         FCurrentRecInd := FLastRecInd
 {$ELSE}
@@ -1678,7 +1679,7 @@ begin
       // inserted
       InternalSetToRecord(ActiveBuffer);
 
-    with FCurrentIndex^ do
+    with FIndexes[0] do
       begin
 {$IFDEF ARRAYBUF}
       inc(FLastRecInd);
@@ -1687,9 +1688,15 @@ begin
       Move(FRecordArray[FCurrentRecInd],FRecordArray[FCurrentRecInd+1],sizeof(Pointer)*(FLastRecInd-FCurrentRecInd));
       FRecordArray[FCurrentRecInd]:=pointer(IntAllocRecordBuffer);
 {$ELSE}
-    // Create the new record buffer
-      AddRecordToIndex(PBufRecLinkItem(IntAllocRecordBuffer),FCurrentRecBuf,FCurrentIndex^);
-      FCurrentRecBuf := FCurrentRecBuf^.prior;
+      // Create the new record buffer
+      AddRecordToIndex(PBufRecLinkItem(IntAllocRecordBuffer),FCurrentRecBuf,FIndexes[0]);
+      FCurrentRecBuf := FCurrentRecBuf[IndNr].prior;
+      // Add the record to the other indexes
+      for i := 1 to FIndexesCount-1 do if ((i>1) or (@FIndexes[i]=FCurrentIndex)) then
+        begin
+        AddRecordToIndex(FCurrentRecBuf,FIndexes[i].FLastRecBuf,FIndexes[i]);
+        end;
+
 {$ENDIF}
       end;
 
@@ -1699,7 +1706,7 @@ begin
 {$IFDEF ARRAYBUF}
       BookmarkData := FCurrentIndex^.FCurrentRecInd;
 {$ELSE}
-      BookmarkData := FCurrentIndex^.FCurrentRecBuf;
+      BookmarkData := FCurrentRecBuf;
 {$ENDIF}
       BookmarkFlag := bfInserted;
       end;
@@ -1714,15 +1721,15 @@ begin
     FCurrentUpdateBuffer := length(FUpdateBuffer);
     SetLength(FUpdateBuffer,FCurrentUpdateBuffer+1);
 
+{$IFDEF ARRAYBUF}
     with FCurrentIndex^ do
       begin
-{$IFDEF ARRAYBUF}
       FUpdateBuffer[FCurrentUpdateBuffer].Bookmark.BookmarkData := FCurrentRecInd;
       FUpdateBuffer[FCurrentUpdateBuffer].Bookmark.BookMarkBuf := FRecordArray[FCurrentRecInd];
+      end;
 {$ELSE}
-      FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData := FCurrentRecBuf;
+    FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData := FCurrentRecBuf;
 {$ENDIF}
-      end;
 
     if state = dsEdit then
       begin
@@ -1740,8 +1747,8 @@ begin
       FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind := ukInsert;
     end;
 
-  with FCurrentIndex^ do
 {$IFDEF ARRAYBUF}
+  with FIndexes[0] do
     move(ActiveBuffer^,FRecordArray[FCurrentRecInd]^,FRecordSize);
 {$ELSE}
     CurrBuff := pchar(FCurrentRecBuf);
@@ -2103,7 +2110,7 @@ begin
     begin
     FIndexes[FIndexesCount-1].FFirstRecBuf := pointer(IntAllocRecordBuffer);
     FIndexes[FIndexesCount-1].FLastRecBuf := FIndexes[FIndexesCount-1].FFirstRecBuf;
-    FIndexes[FIndexesCount-1].FCurrentRecBuf := FIndexes[FIndexesCount-1].FLastRecBuf;
+    FCurrentRecBuf := FIndexes[FIndexesCount-1].FLastRecBuf;
     BuildIndex(FIndexes[FIndexesCount-1]);
     end
 {$IFNDEF ARRAYBUF}

+ 2 - 0
packages/fcl-db/src/base/db.pas

@@ -214,6 +214,7 @@ type
     procedure Add(const AName: string; ADataType: TFieldType); overload;
     Function AddFieldDef : TFieldDef;
     procedure Assign(FieldDefs: TFieldDefs); overload;
+    function Find(const AName: string): TFieldDef;
 //    procedure Clear;
 //    procedure Delete(Index: Longint);
     procedure Update; overload;
@@ -501,6 +502,7 @@ type
   public
     constructor Create(AOwner: TComponent); override;
   published
+    property Alignment default taRightJustify;
     property DisplayFormat: string read FDisplayFormat write SetDisplayFormat;
     property EditFormat: string read FEditFormat write SetEditFormat;
   end;

+ 1 - 1
packages/fcl-db/src/base/dsparams.inc

@@ -296,7 +296,7 @@ begin
             else
             begin
               ParamNameStart:=p;
-              while not (p^ in (SQLDelimiterCharacters+[#0,'=','+','-','*','\','/','[',']'])) do
+              while not (p^ in (SQLDelimiterCharacters+[#0,'=','+','-','*','\','/','[',']','|'])) do
                 Inc(p);
               ParamName:=Copy(ParamNameStart,1,p-ParamNameStart);
             end;

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

@@ -134,6 +134,7 @@ Type
     property KeepConnection;
     property LoginPrompt;
     property Params;
+    property Port stored false;
     property OnLogin;
   end;
 
@@ -213,12 +214,12 @@ end;
 procedure TConnectionName.ConnectMySQL(var HMySQL : PMySQL;H,U,P : pchar);
 
 Var
-  Port : Cardinal;
+  APort : Cardinal;
 
 begin
   HMySQL := mysql_init(HMySQL);
-  Port:=Abs(StrToIntDef(Params.Values['Port'],0));
-  HMySQL:=mysql_real_connect(HMySQL,PChar(H),PChar(U),Pchar(P),Nil,Port,Nil,0);
+  APort:=Abs(StrToIntDef(Params.Values['Port'],0));
+  HMySQL:=mysql_real_connect(HMySQL,PChar(H),PChar(U),Pchar(P),Nil,APort,Nil,0);
   If (HMySQL=Nil) then
     MySQlError(Nil,SErrServerConnectFailed,Self);
 end;

+ 2 - 1
packages/fcl-db/src/sqldb/postgres/pqconnection.pp

@@ -364,7 +364,8 @@ begin
     DatabaseError(sErrConnectionFailed + ' (PostgreSQL: ' + msg + ')',self);
     end;
 // This does only work for pg>=8.0, so timestamps won't work with earlier versions of pg which are compiled with integer_datetimes on
-  FIntegerDatetimes := pqparameterstatus(FSQLDatabaseHandle,'integer_datetimes') = 'on';
+  if PQparameterStatus<>nil then
+    FIntegerDatetimes := pqparameterstatus(FSQLDatabaseHandle,'integer_datetimes') = 'on';
 end;
 
 procedure TPQConnection.DoInternalDisconnect;

+ 18 - 2
packages/fcl-db/src/sqldb/sqldb.pp

@@ -85,7 +85,9 @@ type
     FHostName            : string;
     FCharSet             : string;
     FRole                : String;
-
+    
+    function GetPort: cardinal;
+    procedure Setport(const AValue: cardinal);
   protected
     FConnOptions         : TConnOptions;
     procedure GetDBInfo(const SchemaType : TSchemaType; const SchemaObjectName, ReturnField : string; List: TStrings);
@@ -119,6 +121,7 @@ type
     function GetSchemaInfoSQL(SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string; virtual;
     procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction : TSQLTransaction); virtual; abstract;
     function RowsAffected(cursor: TSQLCursor): TRowsCount; virtual;
+    property port: cardinal read GetPort write Setport;
   public
     property Handle: Pointer read GetHandle;
     destructor Destroy; override;
@@ -297,7 +300,7 @@ type
     property UpdateMode : TUpdateMode read FUpdateMode write SetUpdateMode;
     property UsePrimaryKeyAsKey : boolean read FUsePrimaryKeyAsKey write SetUsePrimaryKeyAsKey;
     property StatementType : TStatementType read GetStatementType;
-    property ParseSQL : Boolean read FParseSQL write SetParseSQL;
+    property ParseSQL : Boolean read FParseSQL write SetParseSQL default true;
     Property DataSource : TDatasource Read GetDataSource Write SetDatasource;
     property ServerFilter: string read FServerFilterText write SetServerFilterText;
     property ServerFiltered: Boolean read FServerFiltered write SetServerFiltered default False;
@@ -543,6 +546,19 @@ begin
   end;
 end;
 
+function TSQLConnection.GetPort: cardinal;
+begin
+  result := StrToIntDef(Params.Values['Port'],0);
+end;
+
+procedure TSQLConnection.Setport(const AValue: cardinal);
+begin
+  if AValue<>0 then
+    params.Values['Port']:=IntToStr(AValue)
+  else with params do if IndexOfName('Port') > -1 then
+    Delete(IndexOfName('Port'));
+end;
+
 procedure TSQLConnection.GetDBInfo(const SchemaType : TSchemaType; const SchemaObjectName, ReturnField : string; List: TStrings);
 
 var qry : TCustomSQLQuery;

+ 52 - 45
packages/fcl-db/src/sqlite/customsqliteds.pas

@@ -288,24 +288,24 @@ function Num2SqlStr(APChar: PChar): String;
 begin
   if APChar = nil then
   begin
-    Result:=NullString;
+    Result := NullString;
     Exit;
   end;
-  Result:=StrPas(APChar);
+  Result := String(APChar);
 end;
 
 function Char2SqlStr(APChar: PChar): String;
 begin
   if APChar = nil then
   begin
-    Result:=NullString;
+    Result := NullString;
     Exit;
   end;
   //todo: create custom routine to directly transform PChar -> SQL str
-  Result:=StrPas(APChar);
-  if Pos('''',Result) > 0 then
-    Result:=AnsiReplaceStr(Result,'''','''''');
-  Result:=''''+Result+'''';
+  Result := String(APChar);
+  if Pos('''', Result) > 0 then
+    Result := AnsiReplaceStr(Result, '''', '''''');
+  Result := '''' + Result + '''';
 end;
 
 // TDSStream
@@ -313,14 +313,14 @@ end;
 constructor TDSStream.Create(const ActiveItem: PDataRecord; FieldIndex:Integer);
 begin
   inherited Create;
-  FPosition:=0;
-  FActiveItem:=ActiveItem;
-  FFieldIndex:=FieldIndex;
-  FFieldRow:=ActiveItem^.Row[FieldIndex];
+  //FPosition := 0;
+  FActiveItem := ActiveItem;
+  FFieldIndex := FieldIndex;
+  FFieldRow := ActiveItem^.Row[FieldIndex];
   if FFieldRow <> nil then
-    FRowSize:=StrLen(FFieldRow)
-  else
-    FRowSize:=0;  
+    FRowSize := StrLen(FFieldRow);
+  //else
+  //  FRowSize := 0;  
 end;  
 
 function TDSStream.Seek(Offset: Longint; Origin: Word): Longint;
@@ -585,36 +585,36 @@ end;
 function TCustomSqliteDataset.GetFieldData(Field: TField; Buffer: Pointer;
   NativeFormat: Boolean): Boolean;
 var
-  ValError:Word;
-  FieldRow:PChar;
+  ValError: Word;
+  FieldRow: PChar;
 begin
-  FieldRow:=PPDataRecord(ActiveBuffer)^^.Row[Field.FieldNo - 1];
+  FieldRow := PPDataRecord(ActiveBuffer)^^.Row[Field.FieldNo - 1];
   Result := FieldRow <> nil;  
   if Result and (Buffer <> nil) then //supports GetIsNull
   begin
     case Field.Datatype of
     ftString:
       begin
-        Move(FieldRow^,PChar(Buffer)^,StrLen(FieldRow)+1);
+        Move(FieldRow^, PChar(Buffer)^, StrLen(FieldRow) + 1);
       end;
-    ftInteger,ftAutoInc:
+    ftInteger, ftAutoInc:
       begin
-        Val(StrPas(FieldRow),LongInt(Buffer^),ValError);
-        Result:= ValError = 0;  
+        Val(String(FieldRow), LongInt(Buffer^), ValError);
+        Result := ValError = 0;  
       end;
-    ftBoolean,ftWord:
+    ftBoolean, ftWord:
       begin
-        Val(StrPas(FieldRow),Word(Buffer^),ValError);
-        Result:= ValError = 0;
+        Val(String(FieldRow), Word(Buffer^), ValError);
+        Result := ValError = 0;
       end;    
-    ftFloat,ftDateTime,ftTime,ftDate,ftCurrency:
+    ftFloat, ftDateTime, ftTime, ftDate, ftCurrency:
       begin
-        Val(StrPas(FieldRow),Double(Buffer^),ValError);
-        Result:= ValError = 0; 
+        Val(String(FieldRow), Double(Buffer^), ValError);
+        Result := ValError = 0; 
       end;
     ftLargeInt:
       begin
-        Val(StrPas(FieldRow),Int64(Buffer^),ValError);
+        Val(String(FieldRow), Int64(Buffer^), ValError);
         Result:= ValError = 0;
       end;        
     end;
@@ -757,24 +757,24 @@ end;
 
 procedure TCustomSqliteDataset.InternalDelete;
 var
-  TempItem:PDataRecord;
-  ValError,TempInteger:Integer;
+  TempItem: PDataRecord;
+  ValError, TempInteger: Integer;
 begin
   Dec(FRecordCount);
-  TempItem:=PPDataRecord(ActiveBuffer)^;
-  TempItem^.Next^.Previous:=TempItem^.Previous;
-  TempItem^.Previous^.Next:=TempItem^.Next;
+  TempItem := PPDataRecord(ActiveBuffer)^;
+  TempItem^.Next^.Previous := TempItem^.Previous;
+  TempItem^.Previous^.Next := TempItem^.Next;
   if FCurrentItem = TempItem then
   begin
     if FCurrentItem^.Previous <> FBeginItem then
-      FCurrentItem:= FCurrentItem^.Previous
+      FCurrentItem := FCurrentItem^.Previous
     else
-      FCurrentItem:= FCurrentItem^.Next;  
+      FCurrentItem := FCurrentItem^.Next;  
   end; 
   // Dec FNextAutoInc (only if deleted item is the last record)  
   if FAutoIncFieldNo <> -1 then
   begin
-    Val(StrPas(TempItem^.Row[FAutoIncFieldNo]),TempInteger,ValError);
+    Val(String(TempItem^.Row[FAutoIncFieldNo]), TempInteger, ValError);
     if (ValError = 0) and (TempInteger = (FNextAutoInc - 1)) then
       Dec(FNextAutoInc);
   end;    
@@ -1046,10 +1046,12 @@ begin
     if MatchRecord then
     begin
       Result := TempItem;
-      if DoResync then
+      if DoResync and (TempItem <> PPDataRecord(ActiveBuffer)^) then
       begin
+        DoBeforeScroll;
         FCurrentItem := TempItem;
         Resync([]);
+        DoAfterScroll;
       end;
       Break;//while
     end;
@@ -1180,17 +1182,22 @@ end;
 
 procedure TCustomSqliteDataset.SetRecNo(Value: Integer);
 var
-  Counter:Integer;
-  TempItem:PDataRecord;
+  Counter: Integer;
+  TempItem: PDataRecord;
 begin
   if (Value > FRecordCount) or (Value <= 0) then
     DatabaseError('Record Number Out Of Range',Self);
   CheckBrowseMode;
-  TempItem:=FBeginItem;
+  TempItem := FBeginItem;
   for Counter := 1 to Value do
-    TempItem:=TempItem^.Next;
-  FCurrentItem:=TempItem;
-  Resync([]);
+    TempItem := TempItem^.Next;
+  if TempItem <> PPDataRecord(ActiveBuffer)^ then
+  begin
+    DoBeforeScroll;
+    FCurrentItem := TempItem;
+    Resync([]);
+    DoAfterScroll;
+  end;
 end;
 
 // Specific functions 
@@ -1351,7 +1358,7 @@ begin
     begin
       TempItem:=PDataRecord(FDeletedItems.List^[iItems]);
       SqlTemp:=SqlTemp+(TemplateStr+
-        StrPas(TempItem^.Row[FPrimaryKeyNo])+';');
+        String(TempItem^.Row[FPrimaryKeyNo])+';');
       FreeItem(TempItem);
       inc(StatementsCounter);
       //ApplyUpdates each 400 statements
@@ -1379,7 +1386,7 @@ begin
       iFields:=Fields.Count - 1;
       ASqlLine:=ASqlLine + (Fields[iFields].FieldName +' = '+
         FGetSqlStr[iFields](PDataRecord(FUpdatedItems[iItems])^.Row[iFields])+
-        WhereKeyNameEqual+StrPas(PDataRecord(FUpdatedItems[iItems])^.Row[FPrimaryKeyNo])+';');
+        WhereKeyNameEqual+String(PDataRecord(FUpdatedItems[iItems])^.Row[FPrimaryKeyNo])+';');
       SqlTemp:=SqlTemp + ASqlLine;
       inc(StatementsCounter);
       //ApplyUpdates each 400 statements

+ 18 - 18
packages/fcl-db/src/sqlite/sqlite3ds.pas

@@ -105,15 +105,15 @@ function GetAutoIncValue(NextValue: Pointer; Columns: Integer; ColumnValues: PPC
 var
   CodeError, TempInt: Integer;
 begin
-  TempInt:=-1;
+  TempInt := -1;
   if ColumnValues[0] <> nil then
   begin
-    Val(StrPas(ColumnValues[0]),TempInt,CodeError);
+    Val(String(ColumnValues[0]), TempInt, CodeError);
     if CodeError <> 0 then
-      DatabaseError('SqliteDs - Error trying to get last autoinc value');
+      DatabaseError('TSqlite3Dataset: Error trying to get last autoinc value');
   end;
-  Integer(NextValue^):=Succ(TempInt);
-  Result:=1;
+  Integer(NextValue^) := Succ(TempInt);
+  Result := 1;
 end;
 
 { TSqlite3Dataset }
@@ -174,10 +174,10 @@ begin
   SetLength(FGetSqlStr,ColumnCount);
   for i := 0 to ColumnCount - 1 do
   begin
-   ColumnStr := UpperCase(StrPas(sqlite3_column_decltype(vm,i)));
+   ColumnStr := UpperCase(String(sqlite3_column_decltype(vm,i)));
    if (ColumnStr = 'INTEGER') or (ColumnStr = 'INT') then
    begin
-     if AutoIncrementKey and (UpperCase(StrPas(sqlite3_column_name(vm,i))) = UpperCase(PrimaryKey)) then
+     if AutoIncrementKey and (UpperCase(String(sqlite3_column_name(vm,i))) = UpperCase(PrimaryKey)) then
      begin
        AType := ftAutoInc;
        FAutoIncFieldNo := i;
@@ -224,9 +224,9 @@ begin
      AType := ftString;
    end;
    if AType = ftString then
-     FieldDefs.Add(StrPas(sqlite3_column_name(vm,i)), AType, dsMaxStringSize)
+     FieldDefs.Add(String(sqlite3_column_name(vm,i)), AType, dsMaxStringSize)
    else
-     FieldDefs.Add(StrPas(sqlite3_column_name(vm,i)), AType);  
+     FieldDefs.Add(String(sqlite3_column_name(vm,i)), AType);  
    //Set the pchar2sql function
    if AType in [ftString,ftMemo] then
      FGetSqlStr[i]:=@Char2SqlStr
@@ -315,7 +315,7 @@ end;
 
 function TSqlite3Dataset.GetSqliteVersion: String;
 begin
-  Result:=StrPas(sqlite3_version());
+  Result := String(sqlite3_version());
 end;
 
 function TSqlite3Dataset.QuickQuery(const ASql:String;const AStrList: TStrings;FillObjects:Boolean):String;
@@ -326,30 +326,30 @@ var
   begin
     while FReturnCode = SQLITE_ROW do
     begin
-      AStrList.Add(StrPas(sqlite3_column_text(vm,0)));
-      FReturnCode:=sqlite3_step(vm);
+      AStrList.Add(String(sqlite3_column_text(vm,0)));
+      FReturnCode := sqlite3_step(vm);
     end;
   end;
   procedure FillStringsAndObjects;
   begin
     while FReturnCode = SQLITE_ROW do
     begin
-      AStrList.AddObject(StrPas(sqlite3_column_text(vm,0)),TObject(PtrInt(sqlite3_column_int(vm,1))));
-      FReturnCode:=sqlite3_step(vm);
+      AStrList.AddObject(String(sqlite3_column_text(vm,0)), TObject(PtrInt(sqlite3_column_int(vm,1))));
+      FReturnCode := sqlite3_step(vm);
     end;
   end;    
 begin
   if FSqliteHandle = nil then
     GetSqliteHandle;
-  Result:='';
-  FReturnCode:=sqlite3_prepare(FSqliteHandle,Pchar(ASql),-1,@vm,nil);
+  Result := '';
+  FReturnCode := sqlite3_prepare(FSqliteHandle,Pchar(ASql), -1, @vm, nil);
   if FReturnCode <> SQLITE_OK then
     DatabaseError(ReturnString,Self);
     
-  FReturnCode:=sqlite3_step(vm);
+  FReturnCode := sqlite3_step(vm);
   if (FReturnCode = SQLITE_ROW) and (sqlite3_column_count(vm) > 0) then
   begin
-    Result:=StrPas(sqlite3_column_text(vm,0));
+    Result := String(sqlite3_column_text(vm,0));
     if AStrList <> nil then
     begin   
       if FillObjects and (sqlite3_column_count(vm) > 1) then

+ 23 - 23
packages/fcl-db/src/sqlite/sqliteds.pas

@@ -72,15 +72,15 @@ function GetAutoIncValue(NextValue: Pointer; Columns: Integer; ColumnValues: PPC
 var
   CodeError, TempInt: Integer;
 begin
-  TempInt:=-1;
+  TempInt := -1;
   if ColumnValues[0] <> nil then
   begin
-    Val(StrPas(ColumnValues[0]),TempInt,CodeError);
+    Val(String(ColumnValues[0]), TempInt, CodeError);
     if CodeError <> 0 then
-      DatabaseError('SqliteDs - Error trying to get last autoinc value');
+      DatabaseError('TSqliteDataset: Error trying to get last autoinc value');
   end;
-  Integer(NextValue^):=Succ(TempInt);
-  Result:=1;
+  Integer(NextValue^) := Succ(TempInt);
+  Result := 1;
 end;
 
 { TSqliteDataset }
@@ -103,7 +103,7 @@ begin
   Result := sqlite_open(PChar(FFileName), 0, @ErrorStr);
   if Result = nil then
   begin
-    DatabaseError('Error opening "' + FFileName +'": ' + StrPas(ErrorStr));
+    DatabaseError('Error opening "' + FFileName +'": ' + String(ErrorStr));
     sqlite_freemem(ErrorStr);
   end;
 end;
@@ -133,11 +133,11 @@ begin
   // If the field contains another type, may have problems
   for i := 0 to ColumnCount - 1 do
   begin
-    ColumnStr := UpperCase(StrPas(ColumnNames[i + ColumnCount]));
+    ColumnStr := UpperCase(String(ColumnNames[i + ColumnCount]));
     if (ColumnStr = 'INTEGER') or (ColumnStr = 'INT') then
     begin
       if AutoIncrementKey and
-           (UpperCase(StrPas(ColumnNames[i])) = UpperCase(PrimaryKey)) then
+           (UpperCase(String(ColumnNames[i])) = UpperCase(PrimaryKey)) then
       begin
         AType := ftAutoInc;
         FAutoIncFieldNo := i;
@@ -184,9 +184,9 @@ begin
       AType := ftString;
     end;    
     if AType = ftString then
-      FieldDefs.Add(StrPas(ColumnNames[i]), AType, dsMaxStringSize)
+      FieldDefs.Add(String(ColumnNames[i]), AType, dsMaxStringSize)
     else
-      FieldDefs.Add(StrPas(ColumnNames[i]), AType);  
+      FieldDefs.Add(String(ColumnNames[i]), AType);  
     //Set the pchar2sql function
     if AType in [ftString,ftMemo] then
       FGetSqlStr[i]:=@Char2SqlStr
@@ -308,26 +308,26 @@ end;
 
 function TSqliteDataset.GetSqliteEncoding: String;
 begin
-  Result:=StrPas(sqlite_encoding);
+  Result := String(sqlite_encoding);
 end;
   
 function TSqliteDataset.GetSqliteVersion: String;
 begin
-  Result:=StrPas(sqlite_version);
+  Result := String(sqlite_version);
 end;
 
 function TSqliteDataset.QuickQuery(const ASql:String;const AStrList: TStrings;FillObjects:Boolean):String;
 var
-  vm:Pointer;
-  ColumnNames,ColumnValues:PPChar;
-  ColCount:Integer;
+  vm: Pointer;
+  ColumnNames, ColumnValues: PPChar;
+  ColCount: Integer;
   
   procedure FillStrings;
   begin
     while FReturnCode = SQLITE_ROW do
     begin
-      AStrList.Add(StrPas(ColumnValues[0]));
-      FReturnCode:=sqlite_step(vm,@ColCount,@ColumnValues,@ColumnNames);
+      AStrList.Add(String(ColumnValues[0]));
+      FReturnCode := sqlite_step(vm, @ColCount, @ColumnValues, @ColumnNames);
     end;
   end;
   procedure FillStringsAndObjects;
@@ -335,22 +335,22 @@ var
     while FReturnCode = SQLITE_ROW do
     begin
       // I know, this code is really dirty!!
-      AStrList.AddObject(StrPas(ColumnValues[0]),TObject(PtrInt(StrToInt(StrPas(ColumnValues[1])))));
-      FReturnCode:=sqlite_step(vm,@ColCount,@ColumnValues,@ColumnNames);
+      AStrList.AddObject(String(ColumnValues[0]), TObject(PtrInt(StrToInt(String(ColumnValues[1])))));
+      FReturnCode:=sqlite_step(vm, @ColCount, @ColumnValues, @ColumnNames);
     end;
   end;    
 begin
   if FSqliteHandle = nil then
     GetSqliteHandle;
-  Result:='';
-  FReturnCode:=sqlite_compile(FSqliteHandle,Pchar(ASql),nil,@vm,nil);
+  Result := '';
+  FReturnCode := sqlite_compile(FSqliteHandle, PChar(ASql), nil, @vm, nil);
   if FReturnCode <> SQLITE_OK then
     DatabaseError(ReturnString,Self);
     
-  FReturnCode:=sqlite_step(vm,@ColCount,@ColumnValues,@ColumnNames);
+  FReturnCode := sqlite_step(vm, @ColCount, @ColumnValues, @ColumnNames);
   if (FReturnCode = SQLITE_ROW) and (ColCount > 0) then
   begin
-    Result:=StrPas(ColumnValues[0]);
+    Result := String(ColumnValues[0]);
     if AStrList <> nil then
     begin   
       if FillObjects and (ColCount > 1) then

+ 4 - 0
packages/fcl-db/tests/testbasics.pas

@@ -74,6 +74,10 @@ begin
   AssertEquals(     'select * from table where id = ?',
     params.ParseSQL('select * from table where id = :id',true,true,true,psInterbase));
 
+// Test bug 10345
+  AssertEquals(     'select email from table where upper(email) like ''%''||?||''%''',
+    params.ParseSQL('select email from table where upper(email) like ''%''||:email||''%''',true,true,true,psInterbase));
+
 // Test escape-sequences:
   AssertEquals(     'select * from table where ''id '''' = :id''',
     params.ParseSQL('select * from table where ''id '''' = :id''',true,False,True,psPostgreSQL));

+ 122 - 72
tests/utils/tests.sql

@@ -1,88 +1,138 @@
+
+SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
+
 CREATE TABLE TESTS (
-  T_ID   INTEGER NOT NULL AUTO_INCREMENT,
-  T_NAME VARCHAR(80) NOT NULL,
-  T_FULLNAME VARCHAR(255) NOT NULL,
-  T_CPU VARCHAR(20),
-  T_OS VARCHAR(30),
-  T_VERSION VARCHAR(10),
-  T_ADDDATE DATE NOT NULL,
-  T_GRAPH CHAR(1) NOT NULL DEFAULT '-',
-  T_INTERACTIVE CHAR(1) NOT NULL DEFAULT '-',
-  T_RESULT INTEGER NOT NULL DEFAULT 0,
-  T_FAIL CHAR(1) NOT NULL DEFAULT '-',
-  T_RECOMPILE CHAR(1) NOT NULL DEFAULT '-',
-  T_NORUN CHAR(1) NOT NULL DEFAULT '-',
-  T_NEEDLIBRARY CHAR(1) NOT NULL DEFAULT '-',
-  T_KNOWNRUNERROR INTEGER NOT NULL DEFAULT 0,
-  T_KNOWN CHAR(1) NOT NULL DEFAULT '-',
-  T_NOTE VARCHAR(255),
-  T_DESCRIPTION TEXT,
-  T_SOURCE TEXT,
-  T_OPTS VARCHAR(255),
-  UNIQUE TESTNAME (T_NAME),
-  PRIMARY KEY PK_TEST (T_ID)
+  T_ID   int(11) NOT NULL auto_increment,
+  T_NAME varchar(40) default NULL,
+  T_CPU varchar(20) default NULL,
+  T_OS varchar(30) default NULL,
+  T_VERSION varchar(10) default NULL,
+  T_ADDDATE date NOT NULL default '0000-00-00',
+  T_GRAPH char(1) NOT NULL default '-',
+  T_INTERACTIVE char(1) NOT NULL default '-',
+  T_RESULT int(11) NOT NULL default '0',
+  T_FAIL char(1) NOT NULL default '-',
+  T_RECOMPILE char(1) NOT NULL default '-',
+  T_NORUN char(1) NOT NULL default '-',
+  T_NEEDLIBRARY char(1) NOT NULL default '-',
+  T_KNOWNRUNERROR int(11) NOT NULL default '0',
+  T_KNOWN char(1) NOT NULL default '-',
+  T_NOTE varchar(255) default NULL,
+  T_DESCRIPTION text,
+  T_SOURCE text,
+  T_OPTS varchar(255) default NULL,
+  PRIMARY KEY  (T_ID),
+  UNIQUE KEY T_NAME (T_NAME)
 );
 
 CREATE TABLE TESTRESULTS (
-  TR_ID INTEGER NOT NULL AUTO_INCREMENT,
-  TR_TEST_FK INTEGER NOT NULL,
-  TR_DATE TIMESTAMP NOT NULL,
-  TR_CPU_FK INTEGER,
-  TR_OS_FK INTEGER,
-  TR_VERSION_FK INTEGER,
-  TR_OK CHAR(1) NOT NULL DEFAULT '-',
-  TR_SKIP CHAR(1) NOT NULL DEFAULT '-',
-  TR_RESULT INT NOT NULL DEFAULT 0,
-  TR_LOG TEXT,
-  PRIMARY KEY (TR_ID),
-  INDEX TR_IDATE (TR_DATE)
+  TR_ID int(11) NOT NULL auto_increment,
+  TR_TESTRUN_FK int(11) NOT NULL default '0',
+  TR_TEST_FK int(11) default NULL,
+  TR_OK char(1) NOT NULL default '-',
+  TR_SKIP char(1) NOT NULL default '-',
+  TR_RESULT int(11) NOT NULL default '0',
+  TR_LOG text,
+  PRIMARY KEY  (TR_ID),
+  UNIQUE KEY TR_TESTCOMP (TR_TESTRUN_FK,TR_TEST_FK),
+  KEY I_TRTESTRUN (TR_TESTRUN_FK),
+  KEY I_TRTEST (TR_TEST_FK)
 );
 
-CREATE TABLE TESTOS (
-  TO_ID INTEGER NOT NULL AUTO_INCREMENT,
-  TO_NAME VARCHAR(10),
-  PRIMARY KEY (TO_ID),
-  UNIQUE TR_INAME (TO_NAME)
+CREATE TABLE TESTRUN (
+  TU_ID int(11) NOT NULL auto_increment,
+  TU_DATE timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+  TU_CPU_FK int(11) NOT NULL default '0',
+  TU_OS_FK int(11) NOT NULL default '0',
+  TU_VERSION_FK int(11) NOT NULL default '0',
+  TU_CATEGORY_FK int(11) NOT NULL default '1',
+  TU_FAILEDTOCOMPILE int(11) NOT NULL default '0',
+  TU_SUCCESSFULLYFAILED int(11) NOT NULL default '0',
+  TU_FAILEDTOFAIL int(11) NOT NULL default '0',
+  TU_SUCCESFULLYCOMPILED int(11) NOT NULL default '0',
+  TU_FAILEDTORUN int(11) NOT NULL default '0',
+  TU_KNOWNPROBLEM int(11) NOT NULL default '0',
+  TU_SUCCESSFULLYRUN int(11) NOT NULL default '0',
+  TU_SKIPPEDGRAPHTEST int(11) NOT NULL default '0',
+  TU_SKIPPEDINTERACTIVETEST int(11) NOT NULL default '0',
+  TU_KNOWNBUG int(11) NOT NULL default '0',
+  TU_COMPILERVERIONTOOLOW int(11) NOT NULL default '0',
+  TU_COMPILERVERIONTOOHIGH int(11) NOT NULL default '0',
+  TU_OTHERCPU int(11) NOT NULL default '0',
+  TU_OTHERTARGET int(11) NOT NULL default '0',
+  TU_UNIT int(11) NOT NULL default '0',
+  TU_SKIPPINGRUNTEST int(11) NOT NULL default '0',
+  TU_SUBMITTER varchar(128) NOT NULL default '',
+  TU_MACHINE varchar(128) NOT NULL default '',
+  TU_COMMENT varchar(255) NOT NULL default '',
+  PRIMARY KEY  (TU_ID),
+  UNIQUE KEY TU_OVERVIEW (TU_ID,TU_CPU_FK,TU_OS_FK,TU_VERSION_FK,TU_DATE),
+  KEY TU_IDATE (TU_DATE)
 );
 
+CREATE TABLE `TESTCATEGORY` (
+  TCAT_ID int(11) NOT NULL auto_increment,
+  TCAT_NAME varchar(20) default NULL,
+  PRIMARY KEY  (`TCAT_ID`),
+  UNIQUE KEY `TCAT_NAME` (`TCAT_NAME`)
+) AUTO_INCREMENT=3 ;
+
+CREATE TABLE TESTOS (
+  TO_ID int(11) NOT NULL auto_increment,
+  TO_NAME varchar(10) default NULL,
+  PRIMARY KEY  (`TO_ID`),
+  UNIQUE KEY `TR_INAME` (`TO_NAME`)
+) AUTO_INCREMENT=18 ;
+
 CREATE TABLE TESTVERSION (
-  TV_ID INTEGER NOT NULL AUTO_INCREMENT,
-  TV_VERSION VARCHAR(10),
-  TV_RELEASEDATE TIMESTAMP,
-  PRIMARY KEY (TV_ID),
-  UNIQUE TR_INAME (TV_VERSION)
-);
+  TV_ID int(11) NOT NULL auto_increment,
+  TV_VERSION varchar(10) default NULL,
+  TV_RELEASEDATE timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+  PRIMARY KEY  (TV_ID),
+  UNIQUE KEY TR_INAME (TV_VERSION)
+) AUTO_INCREMENT=7;
 
 CREATE TABLE TESTCPU (
-  TC_ID INTEGER NOT NULL AUTO_INCREMENT,
-  TC_NAME VARCHAR(10),
-  PRIMARY KEY (TC_ID),
-  UNIQUE TC_INAME (TC_NAME)
-);
+  TC_ID int(11) NOT NULL auto_increment,
+  TC_NAME varchar(10) default NULL,
+  PRIMARY KEY  (TC_ID),
+  UNIQUE KEY TC_INAME (TC_NAME)
+) AUTO_INCREMENT=10 ;
 
-INSERT INTO TESTOS (TO_NAME) VALUES ('linux');
-INSERT INTO TESTOS (TO_NAME) VALUES ('win32');
-INSERT INTO TESTOS (TO_NAME) VALUES ('go32v2');
-INSERT INTO TESTOS (TO_NAME) VALUES ('os2');
-INSERT INTO TESTOS (TO_NAME) VALUES ('freebsd');
-INSERT INTO TESTOS (TO_NAME) VALUES ('netbsd');
-INSERT INTO TESTOS (TO_NAME) VALUES ('openbsd');
-INSERT INTO TESTOS (TO_NAME) VALUES ('amiga');
-INSERT INTO TESTOS (TO_NAME) VALUES ('atari');
-INSERT INTO TESTOS (TO_NAME) VALUES ('qnx');
-INSERT INTO TESTOS (TO_NAME) VALUES ('beos');
-INSERT INTO TESTOS (TO_NAME) VALUES ('sunos');
+INSERT INTO TESTCATEGORY VALUES (1, 'Compiler/RTL');
+INSERT INTO TESTCATEGORY VALUES (2, 'DB');
 
-INSERT INTO TESTCPU (TC_NAME) VALUES ('i386');
-INSERT INTO TESTCPU (TC_NAME) VALUES ('ppc');
-INSERT INTO TESTCPU (TC_NAME) VALUES ('m68k');
-INSERT INTO TESTCPU (TC_NAME) VALUES ('sparc');
+INSERT INTO TESTCPU VALUES (1, 'i386');
+INSERT INTO TESTCPU VALUES (6, 'arm');
+INSERT INTO TESTCPU VALUES (3, 'm68k');
+INSERT INTO TESTCPU VALUES (4, 'sparc');
+INSERT INTO TESTCPU VALUES (5, 'powerpc');
+INSERT INTO TESTCPU VALUES (7, 'x86_64');
+INSERT INTO TESTCPU VALUES (8, 'All');
+INSERT INTO TESTCPU VALUES (9, 'powerpc64');
 
-INSERT INTO TESTVERSION (TV_VERSION) VALUES ('1.0.6');
-INSERT INTO TESTVERSION (TV_VERSION) VALUES ('1.0.7');
-INSERT INTO TESTVERSION (TV_VERSION) VALUES ('1.0.8');
-INSERT INTO TESTVERSION (TV_VERSION) VALUES ('1.1.0');
-INSERT INTO TESTVERSION (TV_VERSION) VALUES ('1.1');
+INSERT INTO TESTOS VALUES (1, 'linux');
+INSERT INTO TESTOS VALUES (2, 'win32');
+INSERT INTO TESTOS VALUES (3, 'go32v2');
+INSERT INTO TESTOS VALUES (4, 'os2');
+INSERT INTO TESTOS VALUES (5, 'freebsd');
+INSERT INTO TESTOS VALUES (6, 'netbsd');
+INSERT INTO TESTOS VALUES (7, 'openbsd');
+INSERT INTO TESTOS VALUES (8, 'amiga');
+INSERT INTO TESTOS VALUES (9, 'atari');
+INSERT INTO TESTOS VALUES (10, 'qnx');
+INSERT INTO TESTOS VALUES (11, 'beos');
+INSERT INTO TESTOS VALUES (12, 'solaris');
+INSERT INTO TESTOS VALUES (13, 'darwin');
+INSERT INTO TESTOS VALUES (14, 'macos');
+INSERT INTO TESTOS VALUES (15, 'All');
+INSERT INTO TESTOS VALUES (16, 'win64');
+INSERT INTO TESTOS VALUES (17, 'wince');
 
+INSERT INTO TESTVERSION VALUES (1, '2.0.4', '2006-08-22 22:38:20');
+INSERT INTO TESTVERSION VALUES (2, '2.0.5', '2006-08-22 22:38:20');
+INSERT INTO TESTVERSION VALUES (3, '2.3.1', '2007-03-04 23:40:07');
+INSERT INTO TESTVERSION VALUES (4, '2.1.2', '2007-03-19 10:49:30');
+INSERT INTO TESTVERSION VALUES (5, '2.1.3', '2007-03-19 10:49:47');
+INSERT INTO TESTVERSION VALUES (6, '2.1.4', '2007-03-19 10:50:03');
 
-