Browse Source

--- Merging r24629 into '.':
U packages/postgres/src/postgres3dyn.pp
U packages/postgres/src/dllistdyn.pp
--- Merging r24689 into '.':
U packages/fcl-db/src/dbase/dbf_common.pas
--- Merging r24694 into '.':
U packages/fcl-db/src/sqldb/sqldb.pp
--- Merging r24695 into '.':
U packages/fcl-db/src/dbase/dbf_wtil.pas
--- Merging r24702 into '.':
G packages/fcl-db/src/sqldb/sqldb.pp
--- Merging r24703 into '.':
G packages/fcl-db/src/sqldb/sqldb.pp
--- Merging r24705 into '.':
G packages/fcl-db/src/sqldb/sqldb.pp
--- Merging r24732 into '.':
G packages/fcl-db/src/sqldb/sqldb.pp
--- Merging r24919 into '.':
U packages/odbc/src/odbcsql.inc
--- Merging r24932 into '.':
U packages/fcl-db/src/sqldb/mssql/mssqlconn.pp
U packages/dblib/src/dblib.pp

# revisions: 24629,24689,24694,24695,24702,24703,24705,24732,24919,24932
r24629 | michael | 2013-05-29 14:41:50 +0200 (Wed, 29 May 2013) | 1 line
Changed paths:
M /trunk/packages/postgres/src/dllistdyn.pp
M /trunk/packages/postgres/src/postgres3dyn.pp

* Patch from Ludo Brands to fix 24497
r24689 | marco | 2013-06-01 11:27:13 +0200 (Sat, 01 Jun 2013) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/dbase/dbf_common.pas

* fix some winapi calls to their -A equivalent. For FPC_UNICODE_RTL
r24694 | michael | 2013-06-01 12:02:11 +0200 (Sat, 01 Jun 2013) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/sqldb/sqldb.pp

* First implementation of TSQLStatement
r24695 | michael | 2013-06-01 12:16:08 +0200 (Sat, 01 Jun 2013) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/dbase/dbf_wtil.pas

* Fix compilation on Unix (oem A version)
r24702 | michael | 2013-06-01 12:55:30 +0200 (Sat, 01 Jun 2013) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/sqldb/sqldb.pp

* Activated Action for TSQLTransaction
r24703 | michael | 2013-06-01 12:56:24 +0200 (Sat, 01 Jun 2013) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/sqldb/sqldb.pp

* TSQLStatement.RowsAffected
r24705 | michael | 2013-06-01 14:29:18 +0200 (Sat, 01 Jun 2013) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/sqldb/sqldb.pp

* Implemented CheckParams for TSQLStatement, TSQLQuery. It disables check for parameter names
r24732 | michael | 2013-06-01 19:07:52 +0200 (Sat, 01 Jun 2013) | 1 line
Changed paths:
M /trunk/packages/fcl-db/src/sqldb/sqldb.pp

* Fix cursor mem leak
r24919 | michael | 2013-06-21 11:23:40 +0200 (Fri, 21 Jun 2013) | 1 line
Changed paths:
M /trunk/packages/odbc/src/odbcsql.inc

* Patch from Laco to define SQL_IDENTIFIER_CASE
r24932 | michael | 2013-06-22 15:50:44 +0200 (Sat, 22 Jun 2013) | 1 line
Changed paths:
M /trunk/packages/dblib/src/dblib.pp
M /trunk/packages/fcl-db/src/sqldb/mssql/mssqlconn.pp

* Patch from Ludo Brands to implement InstanceName (Bug ID 24635)

git-svn-id: branches/fixes_2_6@25111 -

marco 12 years ago
parent
commit
dd7ded484b

+ 17 - 4
packages/dblib/src/dblib.pp

@@ -69,19 +69,32 @@ const
   DBTDS_72     = 10; // Microsoft SQL Server 2005
   DBTDS_73     = 11; // Microsoft SQL Server 2008
 
-  //from sqlfront.h:
+  //from sqlfront.h ,   sybdb.h for freetds
   DBSETHOST=1;
   DBSETUSER=2;
   DBSETPWD=3;
-  DBSETAPP=4;
+  DBSETAPP={$IFDEF freetds}5{$ELSE}4{$ENDIF};
+  {$IFDEF freetds}
+  DBSETHID=     4;
+  DBSETBCP=	6;
+  DBSETNATLANG=	7;
+  DBSETNOSHORT=	8;
+  DBSETHIER=	9;
+  DBSETCHARSET=	10;
+  DBSETPACKET=	11;
+  DBSETENCRYPT=	12;
+  DBSETLABELED=	13;
+  DBSETDBNAME=	14;
+   {$ELSE}
   DBSETID=5;
   DBSETLANG=6;
   DBSETSECURE=7;
+  DBSET_LOGINTIME=10;
+  DBSETFALLBACK=12;
+  {$ENDIF}
   //These two are defined by Microsoft for dbsetlversion():
   DBVER42={$IFDEF freetds}DBVERSION_42{$ELSE}8{$ENDIF};
   DBVER60={$IFDEF freetds}DBVERSION_71{$ELSE}9{$ENDIF};
-  DBSET_LOGINTIME=10;
-  DBSETFALLBACK=12;
   //dboptions:
   DBNOAUTOFREE = {$IFDEF freetds}15{$ELSE}8{$ENDIF};
   DBTEXTLIMIT  = {$IFDEF freetds}7{$ELSE}4{$ENDIF};

+ 2 - 2
packages/fcl-db/src/dbase/dbf_common.pas

@@ -373,10 +373,10 @@ begin
   Result := Length;
 {$ifndef WINCE}
   if (FromCP = GetOEMCP) and (ToCP = GetACP) then
-    OemToCharBuff(Src, Dest, Length)
+    OemToCharBuffA(Src, Dest, Length)
   else
   if (FromCP = GetACP) and (ToCP = GetOEMCP) then
-    CharToOemBuff(Src, Dest, Length)
+    CharToOemBuffA(Src, Dest, Length)
   else
 {$endif}
   if FromCP = ToCP then

+ 4 - 4
packages/fcl-db/src/dbase/dbf_wtil.pas

@@ -253,8 +253,8 @@ function GetOEMCP: Cardinal;
 function GetACP: Cardinal;
 function OemToChar(lpszSrc: PChar; lpszDst: PChar): BOOL;
 function CharToOem(lpszSrc: PChar; lpszDst: PChar): BOOL;
-function OemToCharBuff(lpszSrc: PChar; lpszDst: PChar; cchDstLength: DWORD): BOOL;
-function CharToOemBuff(lpszSrc: PChar; lpszDst: PChar; cchDstLength: DWORD): BOOL;
+function OemToCharBuffA(lpszSrc: PChar; lpszDst: PChar; cchDstLength: DWORD): BOOL;
+function CharToOemBuffA(lpszSrc: PChar; lpszDst: PChar; cchDstLength: DWORD): BOOL;
 function MultiByteToWideChar(CodePage: DWORD; dwFlags: DWORD; const lpMultiByteStr: LPCSTR; cchMultiByte: Integer; lpWideCharStr: LPWSTR; cchWideChar: Integer): Integer;
 function WideCharToMultiByte(CodePage: DWORD; dwFlags: DWORD; lpWideCharStr: LPWSTR; cchWideChar: Integer; lpMultiByteStr: LPSTR; cchMultiByte: Integer; lpDefaultChar: LPCSTR; lpUsedDefaultChar: PBOOL): Integer;
 function CompareString(Locale: LCID; dwCmpFlags: DWORD; lpString1: PChar; cchCount1: Integer; lpString2: PChar; cchCount2: Integer): Integer;
@@ -588,7 +588,7 @@ begin
   Result := true;
 end;
 
-function OemToCharBuff(lpszSrc: PChar; lpszDst: PChar; cchDstLength: DWORD): BOOL;
+function OemToCharBuffA(lpszSrc: PChar; lpszDst: PChar; cchDstLength: DWORD): BOOL;
 begin
   if lpszDst <> lpszSrc then
     StrLCopy(lpszDst, lpszSrc, cchDstLength);
@@ -598,7 +598,7 @@ begin
   Result := true;
 end;
 
-function CharToOemBuff(lpszSrc: PChar; lpszDst: PChar; cchDstLength: DWORD): BOOL;
+function CharToOemBuffA(lpszSrc: PChar; lpszDst: PChar; cchDstLength: DWORD): BOOL;
 begin
   if lpszDst <> lpszSrc then
     StrLCopy(lpszDst, lpszSrc, cchDstLength);

+ 6 - 1
packages/fcl-db/src/sqldb/mssql/mssqlconn.pp

@@ -30,7 +30,8 @@
       CharSet - if you use Microsoft DB-Lib and set to 'UTF-8' then char/varchar fields will be UTF8Encoded/Decoded
                 if you use FreeTDS DB-Lib then you must compile with iconv support (requires libiconv2.dll) or cast char/varchar to nchar/nvarchar in SELECTs
       Params - "AutoCommit=true" - if you don't want explicitly commit/rollback transactions
-               "TextSize=16777216 - set maximum size of text/image data returned
+               "TextSize=16777216" - set maximum size of text/image data returned
+               "ApplicationName=YourAppName" Set the app name for the connection. MSSQL 2000 and higher only
 }
 unit mssqlconn;
 
@@ -193,6 +194,7 @@ const
   SBeginTransaction = 'BEGIN TRANSACTION';
   SAutoCommit = 'AUTOCOMMIT';
   STextSize   = 'TEXTSIZE';
+  SAppName   = 'APPLICATIONNAME';
 
 
 var
@@ -428,6 +430,9 @@ begin
   else
     dbsetlcharset(FDBLogin, PChar(CharSet));
 
+  if Params.IndexOfName(SAppName) <> -1 then
+    dbsetlname(FDBLogin, PChar(Params.Values[SAppName]), DBSETAPP);
+
   //dbsetlname(FDBLogin, PChar(TIMEOUT_IGNORE), DBSET_LOGINTIME);
   dbsetlogintime(10);
 

+ 400 - 61
packages/fcl-db/src/sqldb/sqldb.pp

@@ -22,12 +22,24 @@ interface
 
 uses SysUtils, Classes, DB, bufdataset, sqlscript;
 
-type TSchemaType = (stNoSchema, stTables, stSysTables, stProcedures, stColumns, stProcedureParams, stIndexes, stPackages, stSchemata);
-     TConnOption = (sqSupportParams,sqEscapeSlash,sqEscapeRepeat);
-     TConnOptions= set of TConnOption;
-     TConnInfoType=(citAll=-1, citServerType, citServerVersion, citServerVersionString, citClientName, citClientVersion);
+type
+  TSchemaType = (stNoSchema, stTables, stSysTables, stProcedures, stColumns, stProcedureParams, stIndexes, stPackages, stSchemata);
+  TConnOption = (sqSupportParams,sqEscapeSlash,sqEscapeRepeat);
+  TConnOptions= set of TConnOption;
+  TConnInfoType=(citAll=-1, citServerType, citServerVersion, citServerVersionString, citClientName, citClientVersion);
+  TStatementType = (stUnknown, stSelect, stInsert, stUpdate, stDelete,
+    stDDL, stGetSegment, stPutSegment, stExecProcedure,
+    stStartTrans, stCommit, stRollback, stSelectForUpd);
+
+  TRowsCount = LargeInt;
 
-     TRowsCount = LargeInt;
+  TSQLStatementInfo = Record
+    StatementType : TStatementType;
+    TableName : String;
+    Updateable : Boolean;
+    WhereStartPos ,
+    WhereStopPos : integer;
+  end;
 
 type
   TSQLConnection = class;
@@ -37,9 +49,6 @@ type
   TSQLScript = class;
 
 
-  TStatementType = (stUnknown, stSelect, stInsert, stUpdate, stDelete,
-    stDDL, stGetSegment, stPutSegment, stExecProcedure,
-    stStartTrans, stCommit, stRollback, stSelectForUpd);
 
   TDBEventType = (detCustom, detPrepare, detExecute, detFetch, detCommit,detRollBack);
   TDBEventTypes = set of TDBEventType;
@@ -99,6 +108,7 @@ type
     FRole                : String;
 
     function GetPort: cardinal;
+    function GetStatementInfo(const ASQL: string; Full: Boolean; ASchema : TSchemaType): TSQLStatementInfo;
     procedure SetPort(const AValue: cardinal);
   protected
     FConnOptions         : TConnOptions;
@@ -197,15 +207,76 @@ type
     property Handle: Pointer read GetHandle;
     procedure EndTransaction; override;
   published
-    property Action : TCommitRollbackAction read FAction write FAction;
+    property Action : TCommitRollbackAction read FAction write FAction Default caRollBack;
     property Database;
     property Params : TStringList read FParams write SetParams;
   end;
 
+  { TCustomSQLStatement }
+
+  TCustomSQLStatement = Class(TComponent)
+  Private
+    FCheckParams: Boolean;
+    FCursor : TSQLCursor;
+    FDatabase: TSQLConnection;
+    FParams: TParams;
+    FSQL: TStrings;
+    FSQLBuf : String;
+    FTransaction: TSQLTransaction;
+    FDatasource : TDatasource;
+    FParseSQL: Boolean;
+    procedure OnChangeSQL(Sender : TObject);
+    procedure SetDatabase(AValue: TSQLConnection);
+    procedure SetDataSource(AValue: TDatasource);
+    procedure SetParams(AValue: TParams);
+    procedure SetSQL(AValue: TStrings);
+    procedure SetTransaction(AValue: TSQLTransaction);
+    Function GetPrepared : Boolean;
+  Protected
+    Function GetSchemaType : TSchemaType; virtual;
+    Function IsSelectable : Boolean ; virtual;
+    Procedure DoExecute; virtual;
+    procedure DoPrepare; virtual;
+    procedure DoUnPrepare; virtual;
+    Function CreateParams : TParams; virtual;
+    Function LogEvent(EventType : TDBEventType) : Boolean;
+    Procedure Log(EventType : TDBEventType; Const Msg : String); virtual;
+    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
+    Property Cursor : TSQLCursor read FCursor;
+    Property Database : TSQLConnection Read FDatabase Write SetDatabase;
+    Property Transaction : TSQLTransaction Read FTransaction Write SetTransaction;
+    Property SQL : TStrings Read FSQL Write SetSQL;
+    Property Params : TParams Read FParams Write SetParams;
+    Property Datasource : TDatasource Read FDataSource Write SetDataSource;
+    Property ParseSQL : Boolean Read FParseSQL Write FParseSQL;
+    Property CheckParams : Boolean Read FCheckParams Write FCheckParams default true;
+  Public
+    constructor Create(AOwner : TComponent); override;
+    destructor Destroy; override;
+    Procedure Prepare;
+    Procedure Execute;
+    Procedure Unprepare;
+    function ParamByName(Const AParamName : String) : TParam;
+    function RowsAffected: TRowsCount; virtual;
+    Property Prepared : boolean read GetPrepared;
+  end;
+
+  TSQLStatement = Class(TCustomSQLStatement)
+  Published
+    Property Database;
+    Property Transaction;
+    Property SQL;
+    Property Params;
+    Property Datasource;
+    Property ParseSQL;
+    Property CheckParams;
+  end;
+
 { TCustomSQLQuery }
 
   TCustomSQLQuery = class (TCustomBufDataset)
   private
+    FCheckParams: Boolean;
     FCursor              : TSQLCursor;
     FUpdateable          : boolean;
     FTableName           : string;
@@ -333,6 +404,7 @@ type
     property UsePrimaryKeyAsKey : boolean read FUsePrimaryKeyAsKey write SetUsePrimaryKeyAsKey default true;
     property StatementType : TStatementType read GetStatementType;
     property ParseSQL : Boolean read FParseSQL write SetParseSQL default true;
+    Property CheckParams : Boolean Read FCheckParams Write FCheckParams 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;
@@ -388,6 +460,7 @@ type
     property UpdateMode;
     property UsePrimaryKeyAsKey;
     property ParseSQL;
+    Property CheckParams;
     Property DataSource;
     property ServerFilter;
     property ServerFiltered;
@@ -541,6 +614,245 @@ begin
   result := Format('%.2d:%.2d:%.2d.%.3d',[hour,minute,second,millisecond]);
 end;
 
+{ TCustomSQLStatement }
+
+procedure TCustomSQLStatement.OnChangeSQL(Sender: TObject);
+
+var
+  ConnOptions : TConnOptions;
+  NewParams: TParams;
+
+begin
+  UnPrepare;
+  if not CheckParams then
+    exit;
+  if assigned(DataBase) then
+    ConnOptions:=DataBase.ConnOptions
+  else
+    ConnOptions := [sqEscapeRepeat,sqEscapeSlash];
+  NewParams := CreateParams;
+  try
+    NewParams.ParseSQL(FSQL.Text, True, sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions, psInterbase);
+    NewParams.AssignValues(FParams);
+    FParams.Assign(NewParams);
+  finally
+    NewParams.Free;
+  end;
+end;
+
+procedure TCustomSQLStatement.SetDatabase(AValue: TSQLConnection);
+begin
+  if FDatabase=AValue then Exit;
+  UnPrepare;
+  If Assigned(FDatabase) then
+    FDatabase.RemoveFreeNotification(Self);
+  FDatabase:=AValue;
+  If Assigned(FDatabase) then
+    begin
+    FDatabase.FreeNotification(Self);
+    if (Transaction=nil) and (Assigned(FDatabase.Transaction)) then
+      transaction := FDatabase.Transaction;
+    OnChangeSQL(Self);
+    end;
+end;
+
+procedure TCustomSQLStatement.SetDataSource(AValue: TDatasource);
+
+begin
+  if FDatasource=AValue then Exit;
+  If Assigned(FDatasource) then
+    FDatasource.RemoveFreeNotification(Self);
+  FDatasource:=AValue;
+  If Assigned(FDatasource) then
+    FDatasource.FreeNotification(Self);
+end;
+
+procedure TCustomSQLStatement.SetParams(AValue: TParams);
+begin
+  if FParams=AValue then Exit;
+  FParams.Assign(AValue);
+end;
+
+procedure TCustomSQLStatement.SetSQL(AValue: TStrings);
+begin
+  if FSQL=AValue then Exit;
+  FSQL.Assign(AValue);
+end;
+
+procedure TCustomSQLStatement.SetTransaction(AValue: TSQLTransaction);
+begin
+  if FTransaction=AValue then Exit;
+  UnPrepare;
+  if Assigned(FTransaction) then
+    FTransaction.RemoveFreeNotification(Self);
+  FTransaction:=AValue;
+  if Assigned(FTransaction) then
+    begin
+    FTransaction.FreeNotification(Self);
+    If (Database=Nil) then
+      Database:=Transaction.Database as TSQLConnection;
+    end;
+end;
+
+procedure TCustomSQLStatement.DoExecute;
+begin
+  If (FParams.Count>0) and Assigned(FDatasource) then
+    ; // FMasterLink.CopyParamsFromMaster(False);
+  If LogEvent(detExecute) then
+    Log(detExecute,FSQLBuf);
+  Database.Execute(FCursor,Transaction, FParams);
+end;
+
+function TCustomSQLStatement.GetPrepared: Boolean;
+begin
+  Result := Assigned(FCursor) and FCursor.FPrepared;
+end;
+
+function TCustomSQLStatement.CreateParams: TParams;
+begin
+  Result:=TParams.Create(Nil);
+end;
+
+function TCustomSQLStatement.LogEvent(EventType: TDBEventType): Boolean;
+begin
+  Result:=Assigned(Database) and Database.LogEvent(EventType);
+end;
+
+procedure TCustomSQLStatement.Log(EventType: TDBEventType; const Msg: String);
+Var
+  M : String;
+
+begin
+  If LogEvent(EventType) then
+    begin
+    If (Name<>'') then
+      M:=Name
+    else
+      M:=ClassName;
+    Database.Log(EventType,M+' : '+Msg);
+    end;
+end;
+
+procedure TCustomSQLStatement.Notification(AComponent: TComponent;
+  Operation: TOperation);
+begin
+  inherited Notification(AComponent, Operation);
+  if (operation=opRemove) then
+    If (AComponent=FTransaction) then
+      FTransaction:=Nil
+    else if (AComponent=FDatabase) then
+      FDatabase:=Nil;
+end;
+
+constructor TCustomSQLStatement.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FSQL:=TStringList.Create;
+  TStringList(FSQL).OnChange:=@OnChangeSQL;
+  FParams:=CreateParams;
+  FCheckParams:=True;
+  FParseSQL:=True;
+end;
+
+destructor TCustomSQLStatement.Destroy;
+begin
+  UnPrepare;
+  Transaction:=Nil;
+  Database:=Nil;
+  FreeAndNil(Fparams);
+  FreeAndNil(FSQL);
+  inherited Destroy;
+end;
+
+function TCustomSQLStatement.GetSchemaType: TSchemaType;
+
+begin
+  Result:=stNoSchema
+end;
+
+function TCustomSQLStatement.IsSelectable: Boolean;
+begin
+  Result:=False;
+end;
+
+procedure TCustomSQLStatement.DoPrepare;
+
+var
+  StmType: TStatementType;
+
+begin
+  FSQLBuf := TrimRight(FSQL.Text);
+  if (FSQLBuf='') then
+    DatabaseError(SErrNoStatement);
+  StmType:=Database.GetStatementInfo(FSQLBuf,ParseSQL,GetSchemaType).StatementType;
+  if not assigned(FCursor) then
+    FCursor:=Database.AllocateCursorHandle;
+  FCursor.FSelectable:=False;
+  FCursor.FStatementType:=StmType;
+  FCursor.FSchemaType:=GetSchemaType;
+  If LogEvent(detPrepare) then
+    Log(detPrepare,FSQLBuf);
+  Database.PrepareStatement(FCursor,Transaction,FSQLBuf,FParams);
+end;
+
+procedure TCustomSQLStatement.Prepare;
+
+begin
+  if Prepared then exit;
+  if not assigned(Database) then
+    DatabaseError(SErrDatabasenAssigned);
+  if not assigned(Transaction) then
+    DatabaseError(SErrTransactionnSet);
+  if not Database.Connected then
+    Database.Open;
+  if not Transaction.Active then
+    Transaction.StartTransaction;
+  DoPrepare;
+end;
+
+procedure TCustomSQLStatement.Execute;
+begin
+  try
+    Prepare;
+    DoExecute;
+  finally
+    if (not Prepared) and (assigned(database)) and (assigned(FCursor))
+      then database.UnPrepareStatement(FCursor);
+  end;
+end;
+
+procedure TCustomSQLStatement.DoUnPrepare;
+
+begin
+  If Assigned(FCursor) then
+    If Assigned(Database) then
+      begin
+      DataBase.UnPrepareStatement(FCursor);
+      DataBase.DeAllocateCursorHandle(FCursor);
+      end
+    else // this should never happen. It means a cursor handle leaks in the DB itself.
+      FreeAndNil(FCursor);
+end;
+
+procedure TCustomSQLStatement.Unprepare;
+begin
+  if Prepared then
+    DoUnprepare;
+end;
+
+function TCustomSQLStatement.ParamByName(const AParamName: String): TParam;
+begin
+  Result:=FParams.ParamByName(AParamName);
+end;
+
+function TCustomSQLStatement.RowsAffected: TRowsCount;
+begin
+  Result := -1;
+  if not Assigned(Database) then
+    Exit;
+  Result:=Database.RowsAffected(FCursor);
+end;
+
 { TSQLConnection }
 
 function TSQLConnection.StrToStatementType(s : string) : TStatementType;
@@ -660,21 +972,24 @@ begin
     DatabaseError(SErrConnTransactionnSet);
 
   qry := TCustomSQLQuery.Create(nil);
-  qry.transaction := Transaction;
-  qry.database := Self;
-  with qry do
-    begin
-    ParseSQL := False;
-    SetSchemaInfo(ASchemaType,ASchemaObjectName,'');
-    open;
-    AList.Clear;
-    while not eof do
+  try
+    qry.transaction := Transaction;
+    qry.database := Self;
+    with qry do
       begin
-      AList.Append(trim(fieldbyname(AReturnField).asstring));
-      Next;
+      ParseSQL := False;
+      SetSchemaInfo(ASchemaType,ASchemaObjectName,'');
+      open;
+      AList.Clear;
+      while not eof do
+        begin
+        AList.Append(trim(fieldbyname(AReturnField).asstring));
+        Next;
+        end;
       end;
-    end;
-  qry.free;
+  finally
+    qry.free;
+  end;  
 end;
 
 function TSQLConnection.RowsAffected(cursor: TSQLCursor): TRowsCount;
@@ -821,7 +1136,17 @@ end;
 procedure TSQLTransaction.EndTransaction;
 
 begin
-  rollback;
+  Case Action of
+    caNone : ;
+    caCommit :
+      Commit;
+    caCommitRetaining :
+      CommitRetaining;
+    caRollback :
+      RollBack;
+    caRollbackRetaining :
+      RollbackRetaining;
+  end;
 end;
 
 procedure TSQLTransaction.SetParams(const AValue: TStringList);
@@ -908,11 +1233,12 @@ constructor TSQLTransaction.Create(AOwner : TComponent);
 begin
   inherited Create(AOwner);
   FParams := TStringList.Create;
+  Action:=caRollBack;
 end;
 
 destructor TSQLTransaction.Destroy;
 begin
-  Rollback;
+  EndTransaction;
   FreeAndNil(FParams);
   inherited Destroy;
 end;
@@ -965,7 +1291,7 @@ var ConnOptions : TConnOptions;
 begin
   UnPrepare;
   FSchemaType:=stNoSchema;
-  if (FSQL <> nil) then
+  if (FSQL <> nil) and CheckParams then
     begin
     if assigned(DataBase) then
       ConnOptions := TSQLConnection(DataBase).ConnOptions
@@ -985,7 +1311,7 @@ begin
     end;
 end;
 
-function TCustomSQLQuery.ParamByName(Const AParamName : String) : TParam;
+function TCustomSQLQuery.ParamByName(const AParamName: String): TParam;
 
 begin
   Result:=Params.ParamByName(AParamName);
@@ -997,7 +1323,7 @@ begin
   CheckInactive;
 end;
 
-Procedure TCustomSQLQuery.SetTransaction(Value : TDBTransaction);
+procedure TCustomSQLQuery.SetTransaction(Value: TDBTransaction);
 
 begin
   UnPrepare;
@@ -1025,13 +1351,13 @@ begin
     end;
 end;
 
-Function TCustomSQLQuery.IsPrepared : Boolean;
+function TCustomSQLQuery.IsPrepared: Boolean;
 
 begin
   Result := Assigned(FCursor) and FCursor.FPrepared;
 end;
 
-Function TCustomSQLQuery.AddFilter(SQLstr : string) : string;
+function TCustomSQLQuery.AddFilter(SQLstr: string): string;
 
 begin
   if (FWhereStartPos > 0) and (FWhereStopPos > 0) then
@@ -1070,7 +1396,7 @@ begin
   First;
 end;
 
-Procedure TCustomSQLQuery.SetActive (Value : Boolean);
+procedure TCustomSQLQuery.SetActive(Value: Boolean);
 
 begin
   inherited SetActive(Value);
@@ -1246,8 +1572,25 @@ begin
   end;
 end;
 
+
+
 function TCustomSQLQuery.SQLParser(const ASQL : string) : TStatementType;
 
+Var
+  I : TSQLStatementInfo;
+
+begin
+  I:=(Database as TSQLConnection).GetStatementInfo(ASQL,ParseSQL,FSchemaType);
+  FTableName:=I.TableName;
+  FUpdateable:=I.Updateable;
+  FWhereStartPos:=I.WhereStartPos;
+  FWhereStopPos:=I.WhereStopPos;
+  Result:=I.StatementType;
+end;
+
+Function TSQLConnection.GetStatementInfo(const ASQL : string; Full : Boolean; ASchema : TSchemaType) : TSQLStatementInfo;
+
+
 type TParsePart = (ppStart,ppWith,ppSelect,ppTableName,ppFrom,ppWhere,ppGroup,ppOrder,ppBogus);
      TPhraseSeparator = (sepNone, sepWhiteSpace, sepComma, sepComment, sepParentheses, sepDoubleQuote, sepEnd);
      TKeyword = (kwWITH, kwSELECT, kwINSERT, kwUPDATE, kwDELETE, kwFROM, kwJOIN, kwWHERE, kwGROUP, kwORDER, kwUNION, kwROWS, kwLIMIT, kwUnknown);
@@ -1262,7 +1605,6 @@ var
   S                       : string;
   ParsePart               : TParsePart;
   BracketCount            : Integer;
-  ConnOptions             : TConnOptions;
   Separator               : TPhraseSeparator;
   Keyword, K              : TKeyword;
 
@@ -1273,13 +1615,10 @@ begin
   CurrentP := PSQL-1;
   PhraseP := PSQL;
 
-  FTableName := '';
-  FUpdateable := False;
-
-  FWhereStartPos := 0;
-  FWhereStopPos := 0;
-
-  ConnOptions := TSQLConnection(DataBase).ConnOptions;
+  Result.TableName := '';
+  Result.Updateable := False;
+  Result.WhereStartPos := 0;
+  Result.WhereStopPos := 0;
 
   repeat
     begin
@@ -1338,24 +1677,24 @@ begin
 
         case ParsePart of
           ppStart  : begin
-                     Result := TSQLConnection(Database).StrToStatementType(s);
+                     Result.StatementType := StrToStatementType(s);
                      case Keyword of
                        kwWITH  : ParsePart := ppWith;
                        kwSELECT: ParsePart := ppSelect;
                        else      break;
                      end;
-                     if not FParseSQL then break;
+                     if not Full then break;
                      end;
           ppWith   : begin
                      // WITH [RECURSIVE] CTE_name [ ( column_names ) ] AS ( CTE_query_definition ) [, ...]
                      //  { SELECT | INSERT | UPDATE | DELETE } ...
                      case Keyword of
-                       kwSELECT: Result := stSelect;
-                       kwINSERT: Result := stInsert;
-                       kwUPDATE: Result := stUpdate;
-                       kwDELETE: Result := stDelete;
+                       kwSELECT: Result.StatementType := stSelect;
+                       kwINSERT: Result.StatementType := stInsert;
+                       kwUPDATE: Result.StatementType := stUpdate;
+                       kwDELETE: Result.StatementType := stDelete;
                      end;
-                     if Result <> stUnknown then break;
+                     if Result.StatementType <> stUnknown then break;
                      end;
           ppSelect : begin
                      if Keyword = kwFROM then
@@ -1366,11 +1705,11 @@ begin
                      // Meta-data requests are never updateable
                      //  and select-statements from more then one table
                      //  and/or derived tables are also not updateable
-                     if (FSchemaType = stNoSchema) and
+                     if (ASchema = stNoSchema) and
                         (Separator in [sepWhitespace, sepComment, sepDoubleQuote, sepEnd]) then
                        begin
-                       FTableName := s;
-                       FUpdateable := True;
+                       Result.TableName := s;
+                       Result.Updateable := True;
                        end;
                      ParsePart := ppFrom;
                      end;
@@ -1385,15 +1724,15 @@ begin
                          else     ParsePart := ppBogus;
                        end;
 
-                       FWhereStartPos := PhraseP-PSQL+1;
+                       Result.WhereStartPos := PhraseP-PSQL+1;
                        PStatementPart := CurrentP;
                        end
                      else
                      // joined table or user_defined_function (...)
                      if (Keyword = kwJOIN) or (Separator in [sepComma, sepParentheses]) then
                        begin
-                       FTableName := '';
-                       FUpdateable := False;
+                       Result.TableName := '';
+                       Result.Updateable := False;
                        end;
                      end;
           ppWhere  : begin
@@ -1401,16 +1740,16 @@ begin
                         (Separator = sepEnd) then
                        begin
                        ParsePart := ppBogus;
-                       FWhereStartPos := PStatementPart-PSQL;
+                       Result.WhereStartPos := PStatementPart-PSQL;
                        if (Separator = sepEnd) then
-                         FWhereStopPos := CurrentP-PSQL+1
+                         Result.WhereStopPos := CurrentP-PSQL+1
                        else
-                         FWhereStopPos := PhraseP-PSQL+1;
+                         Result.WhereStopPos := PhraseP-PSQL+1;
                        end
                      else if (Keyword = kwUNION) then
                        begin
                        ParsePart := ppBogus;
-                       FUpdateable := False;
+                       Result.Updateable := False;
                        end;
                      end;
         end; {case}
@@ -1532,7 +1871,7 @@ begin
   FServerIndexDefs := TServerIndexDefs.Create(Self);
 
   FParseSQL := True;
-
+  CheckParams:=True;
   FServerFiltered := False;
   FServerFilterText := '';
 
@@ -1602,7 +1941,7 @@ begin
     end;
 end;
 
-Procedure TCustomSQLQuery.UpdateServerIndexDefs;
+procedure TCustomSQLQuery.UpdateServerIndexDefs;
 
 begin
   FServerIndexDefs.Clear;
@@ -1610,7 +1949,7 @@ begin
     TSQLConnection(DataBase).UpdateIndexDefs(ServerIndexDefs,FTableName);
 end;
 
-Procedure TCustomSQLQuery.ApplyRecUpdate(UpdateKind : TUpdateKind);
+procedure TCustomSQLQuery.ApplyRecUpdate(UpdateKind: TUpdateKind);
 
 var FieldNamesQuoteChars : TQuoteChars;
 
@@ -1750,7 +2089,7 @@ begin
 end;
 
 
-Function TCustomSQLQuery.GetCanModify: Boolean;
+function TCustomSQLQuery.GetCanModify: Boolean;
 
 begin
   // the test for assigned(FCursor) is needed for the case that the dataset isn't opened
@@ -1829,7 +2168,7 @@ begin
   FInsertSQL.Assign(AValue);
 end;
 
-Procedure TCustomSQLQuery.SetDataSource(AValue : TDatasource);
+procedure TCustomSQLQuery.SetDataSource(AValue: TDatasource);
 
 Var
   DS : TDatasource;
@@ -1854,7 +2193,7 @@ begin
     end;
 end;
 
-Function TCustomSQLQuery.GetDataSource : TDatasource;
+function TCustomSQLQuery.GetDataSource: TDatasource;
 
 begin
   If Assigned(FMasterLink) then

+ 8 - 8
packages/odbc/src/odbcsql.inc

@@ -811,7 +811,6 @@ const
 #define SQL_CURSOR_COMMIT_BEHAVIOR          23
 #define SQL_DATA_SOURCE_READ_ONLY           25
 #define SQL_DEFAULT_TXN_ISOLATION           26
-#define SQL_IDENTIFIER_CASE                 28
 #define SQL_MAX_COLUMN_NAME_LEN             30
 #define SQL_MAXIMUM_COLUMN_NAME_LENGTH          SQL_MAX_COLUMN_NAME_LEN
 #define SQL_MAX_CURSOR_NAME_LEN             31
@@ -828,6 +827,7 @@ const
   SQL_SERVER_NAME                     = 13;
   SQL_DBMS_NAME                       = 17;
   SQL_DBMS_VER                        = 18;
+  SQL_IDENTIFIER_CASE                 = 28;
   SQL_IDENTIFIER_QUOTE_CHAR           = 29;
   SQL_SCROLL_CONCURRENCY              = 43;
   SQL_TXN_CAPABLE                     = 46;
@@ -928,13 +928,13 @@ const
 /* SQL_GETDATA_EXTENSIONS bitmasks */
 #define SQL_GD_ANY_COLUMN                   0x00000001L
 #define SQL_GD_ANY_ORDER                    0x00000002L
-
-/* SQL_IDENTIFIER_CASE values */
-#define SQL_IC_UPPER                        1
-#define SQL_IC_LOWER                        2
-#define SQL_IC_SENSITIVE                    3
-#define SQL_IC_MIXED                        4
-
+}
+{ SQL_IDENTIFIER_CASE values }
+  SQL_IC_UPPER                       = 1;
+  SQL_IC_LOWER                       = 2;
+  SQL_IC_SENSITIVE                   = 3;
+  SQL_IC_MIXED                       = 4;
+{
 /* SQL_OJ_CAPABILITIES bitmasks */
 /* NB: this means 'outer join', not what  you may be thinking */
 

+ 42 - 27
packages/postgres/src/dllistdyn.pp

@@ -38,6 +38,7 @@ Procedure InitialiseDllist(libpath:string);
 Procedure ReleaseDllist;
 
 var DllistLibraryHandle : TLibHandle;
+var libpgCriticalSection: TRTLCriticalSection;
 
 implementation
 
@@ -46,40 +47,50 @@ var RefCount : integer;
 Procedure InitialiseDllist(libpath:string);
 
 begin
-  inc(RefCount);
-  if RefCount = 1 then
-    begin
-    DllistLibraryHandle := loadlibrary(libpath);
-    if DllistLibraryHandle = nilhandle then
+  EnterCriticalsection(libpgCriticalSection);
+  try
+    inc(RefCount);
+    if RefCount = 1 then
       begin
-      RefCount := 0;
-      Raise EInOutError.Create('Can not load PosgreSQL client. Is it installed? ('+libpath+')');
+      DllistLibraryHandle := loadlibrary(libpath);
+      if DllistLibraryHandle = nilhandle then
+        begin
+        RefCount := 0;
+        Raise EInOutError.Create('Can not load PosgreSQL client. Is it installed? ('+libpath+')');
+        end;
+
+      pointer(DLNewList) := GetProcedureAddress(DllistLibraryHandle,'DLNewList');
+      pointer(DLFreeList) := GetProcedureAddress(DllistLibraryHandle,'DLFreeList');
+      pointer( DLNewElem) := GetProcedureAddress(DllistLibraryHandle,' DLNewElem');
+      pointer(DLFreeElem) := GetProcedureAddress(DllistLibraryHandle,'DLFreeElem');
+      pointer( DLGetHead) := GetProcedureAddress(DllistLibraryHandle,' DLGetHead');
+      pointer( DLGetTail) := GetProcedureAddress(DllistLibraryHandle,' DLGetTail');
+      pointer( DLRemTail) := GetProcedureAddress(DllistLibraryHandle,' DLRemTail');
+      pointer( DLGetPred) := GetProcedureAddress(DllistLibraryHandle,' DLGetPred');
+      pointer( DLGetSucc) := GetProcedureAddress(DllistLibraryHandle,' DLGetSucc');
+      pointer(DLRemove) := GetProcedureAddress(DllistLibraryHandle,'DLRemove');
+      pointer(DLAddHead) := GetProcedureAddress(DllistLibraryHandle,'DLAddHead');
+      pointer(DLAddTail) := GetProcedureAddress(DllistLibraryHandle,'DLAddTail');
+      pointer( DLRemHead) := GetProcedureAddress(DllistLibraryHandle,' DLRemHead');
       end;
-
-    pointer(DLNewList) := GetProcedureAddress(DllistLibraryHandle,'DLNewList');
-    pointer(DLFreeList) := GetProcedureAddress(DllistLibraryHandle,'DLFreeList');
-    pointer( DLNewElem) := GetProcedureAddress(DllistLibraryHandle,' DLNewElem');
-    pointer(DLFreeElem) := GetProcedureAddress(DllistLibraryHandle,'DLFreeElem');
-    pointer( DLGetHead) := GetProcedureAddress(DllistLibraryHandle,' DLGetHead');
-    pointer( DLGetTail) := GetProcedureAddress(DllistLibraryHandle,' DLGetTail');
-    pointer( DLRemTail) := GetProcedureAddress(DllistLibraryHandle,' DLRemTail');
-    pointer( DLGetPred) := GetProcedureAddress(DllistLibraryHandle,' DLGetPred');
-    pointer( DLGetSucc) := GetProcedureAddress(DllistLibraryHandle,' DLGetSucc');
-    pointer(DLRemove) := GetProcedureAddress(DllistLibraryHandle,'DLRemove');
-    pointer(DLAddHead) := GetProcedureAddress(DllistLibraryHandle,'DLAddHead');
-    pointer(DLAddTail) := GetProcedureAddress(DllistLibraryHandle,'DLAddTail');
-    pointer( DLRemHead) := GetProcedureAddress(DllistLibraryHandle,' DLRemHead');
-    end;
+  finally
+    LeaveCriticalsection(libpgCriticalSection);
+  end;
 end;
 
 Procedure ReleaseDllist;
 
 begin
-  if RefCount > 0 then dec(RefCount);
-  if RefCount = 0 then
-    begin
-    if not UnloadLibrary(DllistLibraryHandle) then inc(RefCount);
-    end;
+  EnterCriticalsection(libpgCriticalSection);
+  try
+    if RefCount > 0 then dec(RefCount);
+    if RefCount = 0 then
+      begin
+      if not UnloadLibrary(DllistLibraryHandle) then inc(RefCount);
+      end;
+  finally
+    LeaveCriticalsection(libpgCriticalSection);
+  end;
 end;
 
 // This function is also defined in Dllist!
@@ -89,4 +100,8 @@ begin
 end;
 
 
+initialization
+  InitCriticalSection(libpgCriticalSection);
+finalization
+  DoneCriticalsection(libpgCriticalSection);
 end.

+ 147 - 132
packages/postgres/src/postgres3dyn.pp

@@ -239,152 +239,167 @@ var
 procedure InitialisePostgres3;
 
 begin
-  if (RefCount<>0) then
-      // pretend to load whatever is already loaded, so we do not get a library name conflict.
-    inc(Refcount)
-  else
-    InitialisePostgres3(pqlib)
+  EnterCriticalsection(libpgCriticalSection);
+  try
+    if (RefCount<>0) then
+        // pretend to load whatever is already loaded, so we do not get a library name conflict.
+      inc(Refcount)
+    else
+      InitialisePostgres3(pqlib)
+  finally
+    LeaveCriticalsection(libpgCriticalSection);
+  end;
 end;
 
 
 function InitialisePostgres3(Const libpath : ansistring) : Integer;
 
 begin
-  inc(RefCount);
-  Result:=Refcount;
-  if RefCount = 1 then
-    begin
-    Postgres3LibraryHandle := loadlibrary(libpath);
-    if Postgres3LibraryHandle = nilhandle then
+  EnterCriticalsection(libpgCriticalSection);
+  try
+    inc(RefCount);
+    Result:=Refcount;
+    if RefCount = 1 then
       begin
-      RefCount := 0;
-      Raise EInOutError.CreateFmt(SErrLoadFailed,[libpath]);
-      end;
+      Postgres3LibraryHandle := loadlibrary(libpath);
+      if Postgres3LibraryHandle = nilhandle then
+        begin
+        RefCount := 0;
+        Raise EInOutError.CreateFmt(SErrLoadFailed,[libpath]);
+        end;
 
-    Postgres3LoadedLibrary:=libpath;
-    pointer(PQconnectStart) := GetProcedureAddress(Postgres3LibraryHandle,'PQconnectStart');
-    pointer(PQconnectPoll) := GetProcedureAddress(Postgres3LibraryHandle,'PQconnectPoll');
-    pointer(PQconnectdb) := GetProcedureAddress(Postgres3LibraryHandle,'PQconnectdb');
-    pointer(PQsetdbLogin) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetdbLogin');
-    pointer(PQfinish) := GetProcedureAddress(Postgres3LibraryHandle,'PQfinish');
-    pointer(PQconndefaults) := GetProcedureAddress(Postgres3LibraryHandle,'PQconndefaults');
-    pointer(PQconninfoFree) := GetProcedureAddress(Postgres3LibraryHandle,'PQconninfoFree');
-    pointer(PQresetStart) := GetProcedureAddress(Postgres3LibraryHandle,'PQresetStart');
-    pointer(PQresetPoll) := GetProcedureAddress(Postgres3LibraryHandle,'PQresetPoll');
-    pointer(PQreset) := GetProcedureAddress(Postgres3LibraryHandle,'PQreset');
-    pointer(PQrequestCancel) := GetProcedureAddress(Postgres3LibraryHandle,'PQrequestCancel');
-    pointer(PQdb) := GetProcedureAddress(Postgres3LibraryHandle,'PQdb');
-    pointer(PQuser) := GetProcedureAddress(Postgres3LibraryHandle,'PQuser');
-    pointer(PQpass) := GetProcedureAddress(Postgres3LibraryHandle,'PQpass');
-    pointer(PQhost) := GetProcedureAddress(Postgres3LibraryHandle,'PQhost');
-    pointer(PQport) := GetProcedureAddress(Postgres3LibraryHandle,'PQport');
-    pointer(PQtty) := GetProcedureAddress(Postgres3LibraryHandle,'PQtty');
-    pointer(PQoptions) := GetProcedureAddress(Postgres3LibraryHandle,'PQoptions');
-    pointer(PQstatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQstatus');
-    pointer(PQtransactionStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQtransactionStatus');
-    pointer(PQparameterStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQparameterStatus');
-    pointer(PQprotocolVersion) := GetProcedureAddress(Postgres3LibraryHandle,'PQprotocolVersion');
-    pointer(PQserverVersion) := GetProcedureAddress(Postgres3LibraryHandle,'PQserverVersion');
-    pointer(PQerrorMessage) := GetProcedureAddress(Postgres3LibraryHandle,'PQerrorMessage');
-    pointer(PQsocket) := GetProcedureAddress(Postgres3LibraryHandle,'PQsocket');
-    pointer(PQbackendPID) := GetProcedureAddress(Postgres3LibraryHandle,'PQbackendPID');
-    pointer(PQclientEncoding) := GetProcedureAddress(Postgres3LibraryHandle,'PQclientEncoding');
-    pointer(PQsetClientEncoding) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetClientEncoding');
-{$ifdef USE_SSL}
-    pointer(PQgetssl) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetssl');
-{$endif}
-    pointer(PQsetErrorVerbosity) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetErrorVerbosity');
-    pointer(PQtrace) := GetProcedureAddress(Postgres3LibraryHandle,'PQtrace');
-    pointer(PQuntrace) := GetProcedureAddress(Postgres3LibraryHandle,'PQuntrace');
-    pointer(PQsetNoticeReceiver) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetNoticeReceiver');
-    pointer(PQsetNoticeProcessor) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetNoticeProcessor');
-    pointer(PQexec) := GetProcedureAddress(Postgres3LibraryHandle,'PQexec');
-    pointer(PQexecParams) := GetProcedureAddress(Postgres3LibraryHandle,'PQexecParams');
-    pointer(PQexecPrepared) := GetProcedureAddress(Postgres3LibraryHandle,'PQexecPrepared');
-    pointer(PQPrepare) := GetProcedureAddress(Postgres3LibraryHandle,'PQprepare');
-    pointer(PQdescribePrepared) := GetProcedureAddress(Postgres3LibraryHandle,'PQdescribePrepared');
-    pointer(PQsendQuery) := GetProcedureAddress(Postgres3LibraryHandle,'PQsendQuery');
-    pointer(PQsendQueryParams) := GetProcedureAddress(Postgres3LibraryHandle,'PQsendQueryParams');
-    pointer(PQsendQueryPrepared) := GetProcedureAddress(Postgres3LibraryHandle,'PQsendQueryPrepared');
-    pointer(PQgetResult) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetResult');
-    pointer(PQisBusy) := GetProcedureAddress(Postgres3LibraryHandle,'PQisBusy');
-    pointer(PQconsumeInput) := GetProcedureAddress(Postgres3LibraryHandle,'PQconsumeInput');
-    pointer(PQnotifies) := GetProcedureAddress(Postgres3LibraryHandle,'PQnotifies');
-    pointer(PQputCopyData) := GetProcedureAddress(Postgres3LibraryHandle,'PQputCopyData');
-    pointer(PQputCopyEnd) := GetProcedureAddress(Postgres3LibraryHandle,'PQputCopyEnd');
-    pointer(PQgetCopyData) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetCopyData');
-    pointer(PQgetline) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetline');
-    pointer(PQputline) := GetProcedureAddress(Postgres3LibraryHandle,'PQputline');
-    pointer(PQgetlineAsync) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetlineAsync');
-    pointer(PQputnbytes) := GetProcedureAddress(Postgres3LibraryHandle,'PQputnbytes');
-    pointer(PQendcopy) := GetProcedureAddress(Postgres3LibraryHandle,'PQendcopy');
-    pointer(PQsetnonblocking) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetnonblocking');
-    pointer(PQisnonblocking) := GetProcedureAddress(Postgres3LibraryHandle,'PQisnonblocking');
-    pointer(PQflush) := GetProcedureAddress(Postgres3LibraryHandle,'PQflush');
-    pointer(PQfn) := GetProcedureAddress(Postgres3LibraryHandle,'PQfn');
-    pointer(PQresultStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQresultStatus');
-    pointer(PQresStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQresStatus');
-    pointer(PQresultErrorMessage) := GetProcedureAddress(Postgres3LibraryHandle,'PQresultErrorMessage');
-    pointer(PQresultErrorField) := GetProcedureAddress(Postgres3LibraryHandle,'PQresultErrorField');
-    pointer(PQntuples) := GetProcedureAddress(Postgres3LibraryHandle,'PQntuples');
-    pointer(PQnfields) := GetProcedureAddress(Postgres3LibraryHandle,'PQnfields');
-    pointer(PQbinaryTuples) := GetProcedureAddress(Postgres3LibraryHandle,'PQbinaryTuples');
-    pointer(PQfname) := GetProcedureAddress(Postgres3LibraryHandle,'PQfname');
-    pointer(PQfnumber) := GetProcedureAddress(Postgres3LibraryHandle,'PQfnumber');
-    pointer(PQftable) := GetProcedureAddress(Postgres3LibraryHandle,'PQftable');
-    pointer(PQftablecol) := GetProcedureAddress(Postgres3LibraryHandle,'PQftablecol');
-    pointer(PQfformat) := GetProcedureAddress(Postgres3LibraryHandle,'PQfformat');
-    pointer(PQftype) := GetProcedureAddress(Postgres3LibraryHandle,'PQftype');
-    pointer(PQfsize) := GetProcedureAddress(Postgres3LibraryHandle,'PQfsize');
-    pointer(PQfmod) := GetProcedureAddress(Postgres3LibraryHandle,'PQfmod');
-    pointer(PQcmdStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQcmdStatus');
-    pointer(PQoidStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQoidStatus');
-    pointer(PQoidValue) := GetProcedureAddress(Postgres3LibraryHandle,'PQoidValue');
-    pointer(PQcmdTuples) := GetProcedureAddress(Postgres3LibraryHandle,'PQcmdTuples');
-    pointer(PQgetvalue) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetvalue');
-    pointer(PQgetlength) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetlength');
-    pointer(PQgetisnull) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetisnull');
-    pointer(PQclear) := GetProcedureAddress(Postgres3LibraryHandle,'PQclear');
-    pointer(PQfreemem) := GetProcedureAddress(Postgres3LibraryHandle,'PQfreemem');
-    pointer(PQmakeEmptyPGresult) := GetProcedureAddress(Postgres3LibraryHandle,'PQmakeEmptyPGresult');
-    pointer(PQescapeString) := GetProcedureAddress(Postgres3LibraryHandle,'PQescapeString');
-    pointer(PQescapeBytea) := GetProcedureAddress(Postgres3LibraryHandle,'PQescapeBytea');
-    pointer(PQunescapeBytea) := GetProcedureAddress(Postgres3LibraryHandle,'PQunescapeBytea');
-    pointer(PQprint) := GetProcedureAddress(Postgres3LibraryHandle,'PQprint');
-    pointer(PQdisplayTuples) := GetProcedureAddress(Postgres3LibraryHandle,'PQdisplayTuples');
-    pointer(PQprintTuples) := GetProcedureAddress(Postgres3LibraryHandle,'PQprintTuples');
-    pointer(lo_open) := GetProcedureAddress(Postgres3LibraryHandle,'lo_open');
-    pointer(lo_close) := GetProcedureAddress(Postgres3LibraryHandle,'lo_close');
-    pointer(lo_read) := GetProcedureAddress(Postgres3LibraryHandle,'lo_read');
-    pointer(lo_write) := GetProcedureAddress(Postgres3LibraryHandle,'lo_write');
-    pointer(lo_lseek) := GetProcedureAddress(Postgres3LibraryHandle,'lo_lseek');
-    pointer(lo_creat) := GetProcedureAddress(Postgres3LibraryHandle,'lo_creat');
-    pointer(lo_tell) := GetProcedureAddress(Postgres3LibraryHandle,'lo_tell');
-    pointer(lo_unlink) := GetProcedureAddress(Postgres3LibraryHandle,'lo_unlink');
-    pointer(lo_import) := GetProcedureAddress(Postgres3LibraryHandle,'lo_import');
-    pointer(lo_export) := GetProcedureAddress(Postgres3LibraryHandle,'lo_export');
-    pointer(PQmblen) := GetProcedureAddress(Postgres3LibraryHandle,'PQmblen');
-    pointer(PQenv2encoding) := GetProcedureAddress(Postgres3LibraryHandle,'PQenv2encoding');
+      Postgres3LoadedLibrary:=libpath;
+      pointer(PQconnectStart) := GetProcedureAddress(Postgres3LibraryHandle,'PQconnectStart');
+      pointer(PQconnectPoll) := GetProcedureAddress(Postgres3LibraryHandle,'PQconnectPoll');
+      pointer(PQconnectdb) := GetProcedureAddress(Postgres3LibraryHandle,'PQconnectdb');
+      pointer(PQsetdbLogin) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetdbLogin');
+      pointer(PQfinish) := GetProcedureAddress(Postgres3LibraryHandle,'PQfinish');
+      pointer(PQconndefaults) := GetProcedureAddress(Postgres3LibraryHandle,'PQconndefaults');
+      pointer(PQconninfoFree) := GetProcedureAddress(Postgres3LibraryHandle,'PQconninfoFree');
+      pointer(PQresetStart) := GetProcedureAddress(Postgres3LibraryHandle,'PQresetStart');
+      pointer(PQresetPoll) := GetProcedureAddress(Postgres3LibraryHandle,'PQresetPoll');
+      pointer(PQreset) := GetProcedureAddress(Postgres3LibraryHandle,'PQreset');
+      pointer(PQrequestCancel) := GetProcedureAddress(Postgres3LibraryHandle,'PQrequestCancel');
+      pointer(PQdb) := GetProcedureAddress(Postgres3LibraryHandle,'PQdb');
+      pointer(PQuser) := GetProcedureAddress(Postgres3LibraryHandle,'PQuser');
+      pointer(PQpass) := GetProcedureAddress(Postgres3LibraryHandle,'PQpass');
+      pointer(PQhost) := GetProcedureAddress(Postgres3LibraryHandle,'PQhost');
+      pointer(PQport) := GetProcedureAddress(Postgres3LibraryHandle,'PQport');
+      pointer(PQtty) := GetProcedureAddress(Postgres3LibraryHandle,'PQtty');
+      pointer(PQoptions) := GetProcedureAddress(Postgres3LibraryHandle,'PQoptions');
+      pointer(PQstatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQstatus');
+      pointer(PQtransactionStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQtransactionStatus');
+      pointer(PQparameterStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQparameterStatus');
+      pointer(PQprotocolVersion) := GetProcedureAddress(Postgres3LibraryHandle,'PQprotocolVersion');
+      pointer(PQserverVersion) := GetProcedureAddress(Postgres3LibraryHandle,'PQserverVersion');
+      pointer(PQerrorMessage) := GetProcedureAddress(Postgres3LibraryHandle,'PQerrorMessage');
+      pointer(PQsocket) := GetProcedureAddress(Postgres3LibraryHandle,'PQsocket');
+      pointer(PQbackendPID) := GetProcedureAddress(Postgres3LibraryHandle,'PQbackendPID');
+      pointer(PQclientEncoding) := GetProcedureAddress(Postgres3LibraryHandle,'PQclientEncoding');
+      pointer(PQsetClientEncoding) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetClientEncoding');
+  {$ifdef USE_SSL}
+      pointer(PQgetssl) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetssl');
+  {$endif}
+      pointer(PQsetErrorVerbosity) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetErrorVerbosity');
+      pointer(PQtrace) := GetProcedureAddress(Postgres3LibraryHandle,'PQtrace');
+      pointer(PQuntrace) := GetProcedureAddress(Postgres3LibraryHandle,'PQuntrace');
+      pointer(PQsetNoticeReceiver) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetNoticeReceiver');
+      pointer(PQsetNoticeProcessor) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetNoticeProcessor');
+      pointer(PQexec) := GetProcedureAddress(Postgres3LibraryHandle,'PQexec');
+      pointer(PQexecParams) := GetProcedureAddress(Postgres3LibraryHandle,'PQexecParams');
+      pointer(PQexecPrepared) := GetProcedureAddress(Postgres3LibraryHandle,'PQexecPrepared');
+      pointer(PQPrepare) := GetProcedureAddress(Postgres3LibraryHandle,'PQprepare');
+      pointer(PQdescribePrepared) := GetProcedureAddress(Postgres3LibraryHandle,'PQdescribePrepared');
+      pointer(PQsendQuery) := GetProcedureAddress(Postgres3LibraryHandle,'PQsendQuery');
+      pointer(PQsendQueryParams) := GetProcedureAddress(Postgres3LibraryHandle,'PQsendQueryParams');
+      pointer(PQsendQueryPrepared) := GetProcedureAddress(Postgres3LibraryHandle,'PQsendQueryPrepared');
+      pointer(PQgetResult) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetResult');
+      pointer(PQisBusy) := GetProcedureAddress(Postgres3LibraryHandle,'PQisBusy');
+      pointer(PQconsumeInput) := GetProcedureAddress(Postgres3LibraryHandle,'PQconsumeInput');
+      pointer(PQnotifies) := GetProcedureAddress(Postgres3LibraryHandle,'PQnotifies');
+      pointer(PQputCopyData) := GetProcedureAddress(Postgres3LibraryHandle,'PQputCopyData');
+      pointer(PQputCopyEnd) := GetProcedureAddress(Postgres3LibraryHandle,'PQputCopyEnd');
+      pointer(PQgetCopyData) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetCopyData');
+      pointer(PQgetline) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetline');
+      pointer(PQputline) := GetProcedureAddress(Postgres3LibraryHandle,'PQputline');
+      pointer(PQgetlineAsync) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetlineAsync');
+      pointer(PQputnbytes) := GetProcedureAddress(Postgres3LibraryHandle,'PQputnbytes');
+      pointer(PQendcopy) := GetProcedureAddress(Postgres3LibraryHandle,'PQendcopy');
+      pointer(PQsetnonblocking) := GetProcedureAddress(Postgres3LibraryHandle,'PQsetnonblocking');
+      pointer(PQisnonblocking) := GetProcedureAddress(Postgres3LibraryHandle,'PQisnonblocking');
+      pointer(PQflush) := GetProcedureAddress(Postgres3LibraryHandle,'PQflush');
+      pointer(PQfn) := GetProcedureAddress(Postgres3LibraryHandle,'PQfn');
+      pointer(PQresultStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQresultStatus');
+      pointer(PQresStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQresStatus');
+      pointer(PQresultErrorMessage) := GetProcedureAddress(Postgres3LibraryHandle,'PQresultErrorMessage');
+      pointer(PQresultErrorField) := GetProcedureAddress(Postgres3LibraryHandle,'PQresultErrorField');
+      pointer(PQntuples) := GetProcedureAddress(Postgres3LibraryHandle,'PQntuples');
+      pointer(PQnfields) := GetProcedureAddress(Postgres3LibraryHandle,'PQnfields');
+      pointer(PQbinaryTuples) := GetProcedureAddress(Postgres3LibraryHandle,'PQbinaryTuples');
+      pointer(PQfname) := GetProcedureAddress(Postgres3LibraryHandle,'PQfname');
+      pointer(PQfnumber) := GetProcedureAddress(Postgres3LibraryHandle,'PQfnumber');
+      pointer(PQftable) := GetProcedureAddress(Postgres3LibraryHandle,'PQftable');
+      pointer(PQftablecol) := GetProcedureAddress(Postgres3LibraryHandle,'PQftablecol');
+      pointer(PQfformat) := GetProcedureAddress(Postgres3LibraryHandle,'PQfformat');
+      pointer(PQftype) := GetProcedureAddress(Postgres3LibraryHandle,'PQftype');
+      pointer(PQfsize) := GetProcedureAddress(Postgres3LibraryHandle,'PQfsize');
+      pointer(PQfmod) := GetProcedureAddress(Postgres3LibraryHandle,'PQfmod');
+      pointer(PQcmdStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQcmdStatus');
+      pointer(PQoidStatus) := GetProcedureAddress(Postgres3LibraryHandle,'PQoidStatus');
+      pointer(PQoidValue) := GetProcedureAddress(Postgres3LibraryHandle,'PQoidValue');
+      pointer(PQcmdTuples) := GetProcedureAddress(Postgres3LibraryHandle,'PQcmdTuples');
+      pointer(PQgetvalue) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetvalue');
+      pointer(PQgetlength) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetlength');
+      pointer(PQgetisnull) := GetProcedureAddress(Postgres3LibraryHandle,'PQgetisnull');
+      pointer(PQclear) := GetProcedureAddress(Postgres3LibraryHandle,'PQclear');
+      pointer(PQfreemem) := GetProcedureAddress(Postgres3LibraryHandle,'PQfreemem');
+      pointer(PQmakeEmptyPGresult) := GetProcedureAddress(Postgres3LibraryHandle,'PQmakeEmptyPGresult');
+      pointer(PQescapeString) := GetProcedureAddress(Postgres3LibraryHandle,'PQescapeString');
+      pointer(PQescapeBytea) := GetProcedureAddress(Postgres3LibraryHandle,'PQescapeBytea');
+      pointer(PQunescapeBytea) := GetProcedureAddress(Postgres3LibraryHandle,'PQunescapeBytea');
+      pointer(PQprint) := GetProcedureAddress(Postgres3LibraryHandle,'PQprint');
+      pointer(PQdisplayTuples) := GetProcedureAddress(Postgres3LibraryHandle,'PQdisplayTuples');
+      pointer(PQprintTuples) := GetProcedureAddress(Postgres3LibraryHandle,'PQprintTuples');
+      pointer(lo_open) := GetProcedureAddress(Postgres3LibraryHandle,'lo_open');
+      pointer(lo_close) := GetProcedureAddress(Postgres3LibraryHandle,'lo_close');
+      pointer(lo_read) := GetProcedureAddress(Postgres3LibraryHandle,'lo_read');
+      pointer(lo_write) := GetProcedureAddress(Postgres3LibraryHandle,'lo_write');
+      pointer(lo_lseek) := GetProcedureAddress(Postgres3LibraryHandle,'lo_lseek');
+      pointer(lo_creat) := GetProcedureAddress(Postgres3LibraryHandle,'lo_creat');
+      pointer(lo_tell) := GetProcedureAddress(Postgres3LibraryHandle,'lo_tell');
+      pointer(lo_unlink) := GetProcedureAddress(Postgres3LibraryHandle,'lo_unlink');
+      pointer(lo_import) := GetProcedureAddress(Postgres3LibraryHandle,'lo_import');
+      pointer(lo_export) := GetProcedureAddress(Postgres3LibraryHandle,'lo_export');
+      pointer(PQmblen) := GetProcedureAddress(Postgres3LibraryHandle,'PQmblen');
+      pointer(PQenv2encoding) := GetProcedureAddress(Postgres3LibraryHandle,'PQenv2encoding');
 
-    InitialiseDllist(libpath);
-    end
-  else
-    if (libpath<>pqlib) and (Postgres3LoadedLibrary<>libpath) then
-      begin
-      Dec(RefCount);
-      Raise EInOUtError.CreateFmt(SErrAlreadyLoaded,[Postgres3LoadedLibrary]);
-      end;
+      InitialiseDllist(libpath);
+      end
+    else
+      if (libpath<>pqlib) and (Postgres3LoadedLibrary<>libpath) then
+        begin
+        Dec(RefCount);
+        Raise EInOUtError.CreateFmt(SErrAlreadyLoaded,[Postgres3LoadedLibrary]);
+        end;
+  finally
+    LeaveCriticalsection(libpgCriticalSection);
+  end;
 end;
 
 Procedure ReleasePostgres3;
 
 begin
-  if RefCount > 0 then dec(RefCount);
-  if RefCount = 0 then
-    begin
-    if not UnloadLibrary(Postgres3LibraryHandle) then inc(RefCount);
-    ReleaseDllist;
-    end;
+  EnterCriticalsection(libpgCriticalSection);
+  try
+    if RefCount > 0 then dec(RefCount);
+    if RefCount = 0 then
+      begin
+      if not UnloadLibrary(Postgres3LibraryHandle) then inc(RefCount);
+      ReleaseDllist;
+      end;
+  finally
+    LeaveCriticalsection(libpgCriticalSection);
+  end;
 end;
 
 // This function is also defined in postgres3!