Browse Source

* Restructured Prepare/Unprepare, removed CloseStatement
* Fixed a mem-leak in TIBConnection

git-svn-id: trunk@916 -

joost 20 years ago
parent
commit
7bfeb0b97e

+ 24 - 16
fcl/db/sqldb/interbase/ibconnection.pp

@@ -20,8 +20,8 @@ type
     protected
     protected
     Status               : array [0..19] of ISC_STATUS;
     Status               : array [0..19] of ISC_STATUS;
     Statement            : pointer;
     Statement            : pointer;
-    FFieldFlag           : array of shortint;
-    FinFieldFlag         : array of shortint;
+    FFieldFlag           : PByte;
+    FinFieldFlag         : PByte;
     SQLDA                : PXSQLDA;
     SQLDA                : PXSQLDA;
     in_SQLDA             : PXSQLDA;
     in_SQLDA             : PXSQLDA;
     ParamBinding         : array of integer;
     ParamBinding         : array of integer;
@@ -59,8 +59,8 @@ type
     Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
     Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
     Function AllocateTransactionHandle : TSQLHandle; override;
     Function AllocateTransactionHandle : TSQLHandle; override;
 
 
-    procedure CloseStatement(cursor : TSQLCursor); override;
     procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); override;
     procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); override;
+    procedure UnPrepareStatement(cursor : TSQLCursor); override;
     procedure FreeFldBuffers(cursor : TSQLCursor); override;
     procedure FreeFldBuffers(cursor : TSQLCursor); override;
     procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); override;
     procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); override;
     procedure AddFieldDefs(cursor: TSQLCursor;FieldDefs : TfieldDefs); override;
     procedure AddFieldDefs(cursor: TSQLCursor;FieldDefs : TfieldDefs); override;
@@ -389,6 +389,7 @@ begin
   curs := TIBCursor.create;
   curs := TIBCursor.create;
   curs.sqlda := nil;
   curs.sqlda := nil;
   curs.statement := nil;
   curs.statement := nil;
+  curs.FPrepared := False;
   AllocSQLDA(curs.SQLDA,1);
   AllocSQLDA(curs.SQLDA,1);
   AllocSQLDA(curs.in_SQLDA,1);
   AllocSQLDA(curs.in_SQLDA,1);
   result := curs;
   result := curs;
@@ -401,6 +402,8 @@ begin
     begin
     begin
     reAllocMem(SQLDA,0);
     reAllocMem(SQLDA,0);
     reAllocMem(in_SQLDA,0);
     reAllocMem(in_SQLDA,0);
+    reAllocMem(FFieldFlag,0);
+    reAllocMem(FInFieldFlag,0);
     end;
     end;
   FreeAndNil(cursor);
   FreeAndNil(cursor);
 end;
 end;
@@ -411,16 +414,6 @@ begin
   result := TIBTrans.create;
   result := TIBTrans.create;
 end;
 end;
 
 
-procedure TIBConnection.CloseStatement(cursor : TSQLCursor);
-begin
-  with cursor as TIBcursor do
-    begin
-    if isc_dsql_free_statement(@Status, @Statement, DSQL_Drop) <> 0 then
-      CheckError('FreeStatement', Status);
-    Statement := nil;
-    end;
-end;
-
 procedure TIBConnection.PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams);
 procedure TIBConnection.PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams);
 
 
 var dh    : pointer;
 var dh    : pointer;
@@ -430,7 +423,6 @@ var dh    : pointer;
     i     : integer;
     i     : integer;
 
 
 begin
 begin
-//  ObtainSQLStatementType(cursor,buf);
   with cursor as TIBcursor do
   with cursor as TIBcursor do
     begin
     begin
     dh := GetHandle;
     dh := GetHandle;
@@ -463,6 +455,7 @@ begin
 
 
     if isc_dsql_prepare(@Status, @tr, @Statement, 0, @Buf[1], Dialect, nil) <> 0 then
     if isc_dsql_prepare(@Status, @tr, @Statement, 0, @Buf[1], Dialect, nil) <> 0 then
       CheckError('PrepareStatement', Status);
       CheckError('PrepareStatement', Status);
+    FPrepared := True;
     if assigned(AParams) and (AParams.count > 0) then
     if assigned(AParams) and (AParams.count > 0) then
       begin
       begin
       AllocSQLDA(in_SQLDA,Length(ParamBinding));
       AllocSQLDA(in_SQLDA,Length(ParamBinding));
@@ -471,7 +464,7 @@ begin
       if in_SQLDA^.SQLD > in_SQLDA^.SQLN then
       if in_SQLDA^.SQLD > in_SQLDA^.SQLN then
         DatabaseError(SParameterCountIncorrect,self);
         DatabaseError(SParameterCountIncorrect,self);
       {$R-}
       {$R-}
-      SetLength(FinFieldFlag,in_SQLDA^.SQLD);
+      ReAllocMem(FInFieldFlag,SQLDA^.SQLD+1);
       for x := 0 to in_SQLDA^.SQLD - 1 do with in_SQLDA^.SQLVar[x] do
       for x := 0 to in_SQLDA^.SQLD - 1 do with in_SQLDA^.SQLVar[x] do
         begin
         begin
         if ((SQLType and not 1) = SQL_VARYING) then
         if ((SQLType and not 1) = SQL_VARYING) then
@@ -484,6 +477,7 @@ begin
       end;
       end;
     if FStatementType = stselect then
     if FStatementType = stselect then
       begin
       begin
+      FPrepared := False;
       if isc_dsql_describe(@Status, @Statement, 1, SQLDA) <> 0 then
       if isc_dsql_describe(@Status, @Statement, 1, SQLDA) <> 0 then
         CheckError('PrepareSelect', Status);
         CheckError('PrepareSelect', Status);
       if SQLDA^.SQLD > SQLDA^.SQLN then
       if SQLDA^.SQLD > SQLDA^.SQLN then
@@ -493,13 +487,15 @@ begin
           CheckError('PrepareSelect', Status);
           CheckError('PrepareSelect', Status);
         end;
         end;
       {$R-}
       {$R-}
-      SetLength(FFieldFlag,SQLDA^.SQLD);
+      ReAllocMem(FFieldFlag,SQLDA^.SQLD+1);
       for x := 0 to SQLDA^.SQLD - 1 do with SQLDA^.SQLVar[x] do
       for x := 0 to SQLDA^.SQLD - 1 do with SQLDA^.SQLVar[x] do
         begin
         begin
         if ((SQLType and not 1) = SQL_VARYING) then
         if ((SQLType and not 1) = SQL_VARYING) then
           SQLData := AllocMem(SQLDA^.SQLVar[x].SQLLen+2)
           SQLData := AllocMem(SQLDA^.SQLVar[x].SQLLen+2)
+//          ReAllocMem(SQLData,SQLDA^.SQLVar[x].SQLLen+2)
         else
         else
           SQLData := AllocMem(SQLDA^.SQLVar[x].SQLLen);
           SQLData := AllocMem(SQLDA^.SQLVar[x].SQLLen);
+//             ReAllocMem(SQLData,SQLDA^.SQLVar[x].SQLLen);
         SQLInd  := @FFieldFlag[x];
         SQLInd  := @FFieldFlag[x];
         end;
         end;
       {$R+}
       {$R+}
@@ -507,6 +503,18 @@ begin
     end;
     end;
 end;
 end;
 
 
+procedure TIBConnection.UnPrepareStatement(cursor : TSQLCursor);
+
+begin
+  with cursor as TIBcursor do
+    begin
+    if isc_dsql_free_statement(@Status, @Statement, DSQL_Drop) <> 0 then
+      CheckError('FreeStatement', Status);
+    Statement := nil;
+    FPrepared := False;
+    end;
+end;
+
 procedure TIBConnection.FreeFldBuffers(cursor : TSQLCursor);
 procedure TIBConnection.FreeFldBuffers(cursor : TSQLCursor);
 var
 var
   x  : shortint;
   x  : shortint;

+ 11 - 21
fcl/db/sqldb/mysql/mysql4conn.pas

@@ -54,7 +54,6 @@ Type
     Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
     Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
     Function AllocateTransactionHandle : TSQLHandle; override;
     Function AllocateTransactionHandle : TSQLHandle; override;
 
 
-    procedure CloseStatement(cursor : TSQLCursor); override;
     procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); override;
     procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); override;
     procedure FreeFldBuffers(cursor : TSQLCursor); override;
     procedure FreeFldBuffers(cursor : TSQLCursor); override;
     procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction;AParams : TParams); override;
     procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction;AParams : TParams); override;
@@ -218,26 +217,6 @@ begin
   Result:=TMySQLTransaction.Create;
   Result:=TMySQLTransaction.Create;
 end;
 end;
 
 
-procedure TMySQLConnection.CloseStatement(cursor: TSQLCursor);
-
-Var
-  C : TMySQLCursor;
-
-begin
-  C:=Cursor as TMysqlCursor;
-  if c.FStatementType=stSelect then
-    c.FNeedData:=False;
-  If (C.FRes<>Nil) then
-    begin
-    C.FRes:=Nil;
-    end;
-  if (c.FQMySQL <> Nil) then
-    begin
-    mysql_close(c.FQMySQL);
-    c.FQMySQL:=Nil;
-    end;
-end;
-
 procedure TMySQLConnection.PrepareStatement(cursor: TSQLCursor;
 procedure TMySQLConnection.PrepareStatement(cursor: TSQLCursor;
   ATransaction: TSQLTransaction; buf: string;AParams : TParams);
   ATransaction: TSQLTransaction; buf: string;AParams : TParams);
 begin
 begin
@@ -261,6 +240,17 @@ Var
 
 
 begin
 begin
   C:=Cursor as TMysqlCursor;
   C:=Cursor as TMysqlCursor;
+  if c.FStatementType=stSelect then
+    c.FNeedData:=False;
+  If (C.FRes<>Nil) then
+    begin
+    C.FRes:=Nil;
+    end;
+  if (c.FQMySQL <> Nil) then
+    begin
+    mysql_close(c.FQMySQL);
+    c.FQMySQL:=Nil;
+    end;
   If (C.FRes<>Nil) then
   If (C.FRes<>Nil) then
     begin
     begin
     Mysql_free_result(C.FRes);
     Mysql_free_result(C.FRes);

+ 15 - 22
fcl/db/sqldb/postgres/pqconnection.pp

@@ -45,7 +45,6 @@ type
     Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
     Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
     Function AllocateTransactionHandle : TSQLHandle; override;
     Function AllocateTransactionHandle : TSQLHandle; override;
 
 
-    procedure CloseStatement(cursor : TSQLCursor); override;
     procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); override;
     procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); override;
     procedure FreeFldBuffers(cursor : TSQLCursor); override;
     procedure FreeFldBuffers(cursor : TSQLCursor); override;
     procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); override;
     procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); override;
@@ -420,26 +419,6 @@ begin
     end;
     end;
 end;
 end;
 
 
-procedure TPQConnection.CloseStatement(cursor : TSQLCursor);
-
-begin
-  with cursor as TPQCursor do
-   if (PQresultStatus(res) <> PGRES_FATAL_ERROR) then //Don't try to do anything if the transaction has already encountered an error.
-    begin
-    if FStatementType = stselect then
-      begin
-      Res := pqexec(tr,pchar('CLOSE slctst' + name + nr));
-      if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
-        begin
-        pqclear(res);
-        DatabaseError(SErrClearSelection + ' (PostgreSQL: ' + PQerrorMessage(tr) + ')',self)
-        end
-      end;
-    pqclear(baseres);
-    pqclear(res);
-    end;
-end;
-
 procedure TPQConnection.UnPrepareStatement(cursor : TSQLCursor);
 procedure TPQConnection.UnPrepareStatement(cursor : TSQLCursor);
 
 
 begin
 begin
@@ -459,7 +438,21 @@ end;
 procedure TPQConnection.FreeFldBuffers(cursor : TSQLCursor);
 procedure TPQConnection.FreeFldBuffers(cursor : TSQLCursor);
 
 
 begin
 begin
-// Do nothing
+  with cursor as TPQCursor do
+   if (PQresultStatus(res) <> PGRES_FATAL_ERROR) then //Don't try to do anything if the transaction has already encountered an error.
+    begin
+    if FStatementType = stselect then
+      begin
+      Res := pqexec(tr,pchar('CLOSE slctst' + name + nr));
+      if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
+        begin
+        pqclear(res);
+        DatabaseError(SErrClearSelection + ' (PostgreSQL: ' + PQerrorMessage(tr) + ')',self)
+        end
+      end;
+    pqclear(baseres);
+    pqclear(res);
+    end;
 end;
 end;
 
 
 procedure TPQConnection.Execute(cursor: TSQLCursor;atransaction:tSQLtransaction;AParams : TParams);
 procedure TPQConnection.Execute(cursor: TSQLCursor;atransaction:tSQLtransaction;AParams : TParams);

+ 18 - 23
fcl/db/sqldb/sqldb.pp

@@ -41,6 +41,7 @@ type
   TSQLCursor = Class(TSQLHandle)
   TSQLCursor = Class(TSQLHandle)
   public
   public
     FPrepared      : Boolean;
     FPrepared      : Boolean;
+    FInitFieldDef  : Boolean;
     FStatementType : TStatementType;
     FStatementType : TStatementType;
   end;
   end;
 
 
@@ -86,7 +87,6 @@ type
     procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); virtual; abstract;
     procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); virtual; abstract;
     function Fetch(cursor : TSQLCursor) : boolean; virtual; abstract;
     function Fetch(cursor : TSQLCursor) : boolean; virtual; abstract;
     procedure AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs); virtual; abstract;
     procedure AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs); virtual; abstract;
-    procedure CloseStatement(cursor : TSQLCursor); virtual; abstract;
     procedure UnPrepareStatement(cursor : TSQLCursor); virtual; abstract;
     procedure UnPrepareStatement(cursor : TSQLCursor); virtual; abstract;
 
 
     procedure FreeFldBuffers(cursor : TSQLCursor); virtual; abstract;
     procedure FreeFldBuffers(cursor : TSQLCursor); virtual; abstract;
@@ -173,7 +173,6 @@ type
     FParseSQL            : boolean;
     FParseSQL            : boolean;
 //    FSchemaInfo          : TSchemaInfo;
 //    FSchemaInfo          : TSchemaInfo;
 
 
-    procedure CloseStatement;
     procedure FreeFldBuffers;
     procedure FreeFldBuffers;
     procedure InitUpdates(SQL : string);
     procedure InitUpdates(SQL : string);
     function GetIndexDefs : TIndexDefs;
     function GetIndexDefs : TIndexDefs;
@@ -335,7 +334,7 @@ begin
 
 
     PrepareStatement(cursor,Transaction,SQL,Nil);
     PrepareStatement(cursor,Transaction,SQL,Nil);
     execute(cursor,Transaction, Nil);
     execute(cursor,Transaction, Nil);
-    CloseStatement(Cursor);
+    UnPrepareStatement(Cursor);
   finally;
   finally;
     DeAllocateCursorHandle(Cursor);
     DeAllocateCursorHandle(Cursor);
   end;
   end;
@@ -504,6 +503,7 @@ begin
   if (Database <> Value) then
   if (Database <> Value) then
     begin
     begin
     UnPrepare;
     UnPrepare;
+    if assigned(FCursor) then (Database as TSQLConnection).DeAllocateCursorHandle(FCursor);
     db := value as tsqlconnection;
     db := value as tsqlconnection;
     inherited setdatabase(value);
     inherited setdatabase(value);
     if assigned(value) and (Transaction = nil) and (Assigned(db.Transaction)) then
     if assigned(value) and (Transaction = nil) and (Assigned(db.Transaction)) then
@@ -511,12 +511,6 @@ begin
     end;
     end;
 end;
 end;
 
 
-procedure TSQLQuery.CloseStatement;
-begin
-  if assigned(FCursor) then
-    (Database as tsqlconnection).CloseStatement(FCursor);
-end;
-
 Function TSQLQuery.IsPrepared : Boolean;
 Function TSQLQuery.IsPrepared : Boolean;
 
 
 begin
 begin
@@ -543,7 +537,8 @@ begin
   if Value and not FParseSQL then DatabaseErrorFmt(SNoParseSQL,['Filtering ']);
   if Value and not FParseSQL then DatabaseErrorFmt(SNoParseSQL,['Filtering ']);
   if (Filtered <> Value) and Active then
   if (Filtered <> Value) and Active then
     begin
     begin
-    CloseStatement;
+    FreeFldBuffers;
+    (Database as tsqlconnection).UnPrepareStatement(FCursor);
     FIsEOF := False;
     FIsEOF := False;
     inherited internalclose;
     inherited internalclose;
 
 
@@ -578,8 +573,9 @@ begin
     if not Db.Connected then db.Open;
     if not Db.Connected then db.Open;
     if not sqltr.Active then sqltr.StartTransaction;
     if not sqltr.Active then sqltr.StartTransaction;
 
 
-    if assigned(fcursor) then FreeAndNil(fcursor);
-    FCursor := Db.AllocateCursorHandle;
+//    if assigned(fcursor) then FreeAndNil(fcursor);
+    if not assigned(fcursor) then
+      FCursor := Db.AllocateCursorHandle;
 
 
     FSQLBuf := TrimRight(FSQL.Text);
     FSQLBuf := TrimRight(FSQL.Text);
     
     
@@ -593,8 +589,11 @@ begin
     else
     else
       Db.PrepareStatement(Fcursor,sqltr,FSQLBuf,FParams);
       Db.PrepareStatement(Fcursor,sqltr,FSQLBuf,FParams);
 
 
-    if (FCursor.FStatementType = stSelect) and not ReadOnly then
-      InitUpdates(FSQLBuf);
+    if (FCursor.FStatementType = stSelect) then
+      begin
+      FCursor.FInitFieldDef := True;
+      if not ReadOnly then InitUpdates(FSQLBuf);
+      end;
     end;
     end;
 end;
 end;
 
 
@@ -603,10 +602,7 @@ procedure TSQLQuery.UnPrepare;
 begin
 begin
   CheckInactive;
   CheckInactive;
   if IsPrepared then with Database as TSQLConnection do
   if IsPrepared then with Database as TSQLConnection do
-    begin
     UnPrepareStatement(FCursor);
     UnPrepareStatement(FCursor);
-    DeAllocateCursorHandle(FCursor);
-    end;
 end;
 end;
 
 
 procedure TSQLQuery.FreeFldBuffers;
 procedure TSQLQuery.FreeFldBuffers;
@@ -641,8 +637,8 @@ end;
 
 
 procedure TSQLQuery.InternalClose;
 procedure TSQLQuery.InternalClose;
 begin
 begin
-  FreeFldBuffers;
-  CloseStatement;
+  if StatementType = stSelect then FreeFldBuffers;
+  if not IsPrepared then (database as TSQLconnection).UnPrepareStatement(FCursor);
   if DefaultFields then
   if DefaultFields then
     DestroyFields;
     DestroyFields;
   FIsEOF := False;
   FIsEOF := False;
@@ -789,15 +785,13 @@ procedure TSQLQuery.InternalOpen;
 var tel         : integer;
 var tel         : integer;
     f           : TField;
     f           : TField;
     s           : string;
     s           : string;
-    WasPrepared : boolean;
 begin
 begin
   try
   try
-    WasPrepared := IsPrepared;
     Prepare;
     Prepare;
     if FCursor.FStatementType in [stSelect] then
     if FCursor.FStatementType in [stSelect] then
       begin
       begin
       Execute;
       Execute;
-      if not WasPrepared then InternalInitFieldDefs; // if query was prepared before opening, fields are already created
+      if FCursor.FInitFieldDef then InternalInitFieldDefs;
       if DefaultFields then
       if DefaultFields then
         begin
         begin
         CreateFields;
         CreateFields;
@@ -836,7 +830,7 @@ begin
     Prepare;
     Prepare;
     Execute;
     Execute;
   finally
   finally
-    CloseStatement;
+    if not IsPrepared then (database as TSQLConnection).UnPrepareStatement(Fcursor);
   end;
   end;
 end;
 end;
 
 
@@ -859,6 +853,7 @@ destructor TSQLQuery.Destroy;
 begin
 begin
   if Active then Close;
   if Active then Close;
   UnPrepare;
   UnPrepare;
+  if assigned(FCursor) then (Database as TSQLConnection).DeAllocateCursorHandle(FCursor);
   FreeAndNil(FSQL);
   FreeAndNil(FSQL);
   FreeAndNil(FIndexDefs);
   FreeAndNil(FIndexDefs);
   inherited Destroy;
   inherited Destroy;