mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 15:29:14 +02:00
* Patch from Joost van der Sluis
- Use of the dynamically loaded library (postgres3dyn) - support for the postgreSQL'a internal fieldtype 'name' - implemented UpdateIndexDefs - Support for more then one query for each connection
This commit is contained in:
parent
35a249fc8f
commit
bfcb70b5e4
@ -2,10 +2,17 @@ unit pqconnection;
|
|||||||
|
|
||||||
{$mode objfpc}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
{$Define LinkDynamically}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, sqldb, db,postgres3, dbconst;
|
Classes, SysUtils, sqldb, db, dbconst,
|
||||||
|
{$IfDef LinkDynamically}
|
||||||
|
postgres3dyn;
|
||||||
|
{$Else}
|
||||||
|
postgres3;
|
||||||
|
{$EndIf}
|
||||||
|
|
||||||
type
|
type
|
||||||
TPQTrans = Class(TSQLHandle)
|
TPQTrans = Class(TSQLHandle)
|
||||||
@ -20,10 +27,12 @@ type
|
|||||||
nFields : integer;
|
nFields : integer;
|
||||||
res : PPGresult;
|
res : PPGresult;
|
||||||
BaseRes : PPGresult;
|
BaseRes : PPGresult;
|
||||||
|
Nr : string;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TPQConnection = class (TSQLConnection)
|
TPQConnection = class (TSQLConnection)
|
||||||
private
|
private
|
||||||
|
FCursorCount : word;
|
||||||
FConnectString : string;
|
FConnectString : string;
|
||||||
FSQLDatabaseHandle : pointer;
|
FSQLDatabaseHandle : pointer;
|
||||||
function TranslateFldType(Type_Oid : integer) : TFieldType;
|
function TranslateFldType(Type_Oid : integer) : TFieldType;
|
||||||
@ -48,6 +57,8 @@ type
|
|||||||
procedure CommitRetaining(trans : TSQLHandle); override;
|
procedure CommitRetaining(trans : TSQLHandle); override;
|
||||||
function StartdbTransaction(trans : TSQLHandle) : boolean; override;
|
function StartdbTransaction(trans : TSQLHandle) : boolean; override;
|
||||||
procedure RollBackRetaining(trans : TSQLHandle); override;
|
procedure RollBackRetaining(trans : TSQLHandle); override;
|
||||||
|
procedure UpdateIndexDefs(var IndexDefs : TIndexDefs;TableName : string); override;
|
||||||
|
|
||||||
published
|
published
|
||||||
property DatabaseName;
|
property DatabaseName;
|
||||||
property KeepConnection;
|
property KeepConnection;
|
||||||
@ -71,6 +82,7 @@ ResourceString
|
|||||||
|
|
||||||
const Oid_Bool = 16;
|
const Oid_Bool = 16;
|
||||||
Oid_Text = 25;
|
Oid_Text = 25;
|
||||||
|
Oid_Name = 19;
|
||||||
Oid_Int8 = 20;
|
Oid_Int8 = 20;
|
||||||
Oid_int2 = 21;
|
Oid_int2 = 21;
|
||||||
Oid_Int4 = 23;
|
Oid_Int4 = 23;
|
||||||
@ -238,6 +250,10 @@ procedure TPQConnection.DoInternalConnect;
|
|||||||
var msg : string;
|
var msg : string;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{$IfDef LinkDynamically}
|
||||||
|
InitialisePostgres3;
|
||||||
|
{$EndIf}
|
||||||
|
|
||||||
inherited dointernalconnect;
|
inherited dointernalconnect;
|
||||||
|
|
||||||
if (DatabaseName = '') then
|
if (DatabaseName = '') then
|
||||||
@ -261,13 +277,18 @@ end;
|
|||||||
procedure TPQConnection.DoInternalDisconnect;
|
procedure TPQConnection.DoInternalDisconnect;
|
||||||
begin
|
begin
|
||||||
PQfinish(FSQLDatabaseHandle);
|
PQfinish(FSQLDatabaseHandle);
|
||||||
|
{$IfDef LinkDynamically}
|
||||||
|
ReleasePostgres3;
|
||||||
|
{$EndIf}
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPQConnection.TranslateFldType(Type_Oid : integer) : TFieldType;
|
function TPQConnection.TranslateFldType(Type_Oid : integer) : TFieldType;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
case Type_Oid of
|
case Type_Oid of
|
||||||
Oid_varchar,Oid_bpchar : Result := ftstring;
|
Oid_varchar,Oid_bpchar,
|
||||||
|
Oid_name : Result := ftstring;
|
||||||
Oid_text : REsult := ftmemo;
|
Oid_text : REsult := ftmemo;
|
||||||
Oid_int8 : Result := ftLargeInt;
|
Oid_int8 : Result := ftLargeInt;
|
||||||
Oid_int4 : Result := ftInteger;
|
Oid_int4 : Result := ftInteger;
|
||||||
@ -301,7 +322,11 @@ begin
|
|||||||
begin
|
begin
|
||||||
(cursor as TPQCursor).statement := buf;
|
(cursor as TPQCursor).statement := buf;
|
||||||
if StatementType = stselect then
|
if StatementType = stselect then
|
||||||
statement := 'DECLARE selectst' + name + ' BINARY CURSOR FOR ' + statement;
|
begin
|
||||||
|
nr := inttostr(FCursorcount);
|
||||||
|
statement := 'DECLARE slctst' + name + nr +' BINARY CURSOR FOR ' + statement;
|
||||||
|
inc(FCursorcount);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -313,7 +338,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if StatementType = stselect then
|
if StatementType = stselect then
|
||||||
begin
|
begin
|
||||||
Res := pqexec(tr,pchar('CLOSE selectst' + name));
|
Res := pqexec(tr,pchar('CLOSE slctst' + name + nr));
|
||||||
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
|
if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
|
||||||
begin
|
begin
|
||||||
pqclear(res);
|
pqclear(res);
|
||||||
@ -361,7 +386,7 @@ begin
|
|||||||
with cursor as TPQCursor do
|
with cursor as TPQCursor do
|
||||||
begin
|
begin
|
||||||
// BaseRes := pqexecParams(tr,'FETCH 0 IN selectst' + pchar(name) ,0,nil,nil,nil,nil,1);
|
// BaseRes := pqexecParams(tr,'FETCH 0 IN selectst' + pchar(name) ,0,nil,nil,nil,nil,1);
|
||||||
st := 'FETCH 0 IN selectst' + pchar(name);
|
st := pchar('FETCH 0 IN slctst' + name+nr);
|
||||||
BaseRes := pqexec(tr,pchar(st));
|
BaseRes := pqexec(tr,pchar(st));
|
||||||
if (PQresultStatus(BaseRes) <> PGRES_TUPLES_OK) then
|
if (PQresultStatus(BaseRes) <> PGRES_TUPLES_OK) then
|
||||||
begin
|
begin
|
||||||
@ -374,7 +399,7 @@ begin
|
|||||||
size := PQfsize(BaseRes, i);
|
size := PQfsize(BaseRes, i);
|
||||||
fieldtype := TranslateFldType(PQftype(BaseRes, i));
|
fieldtype := TranslateFldType(PQftype(BaseRes, i));
|
||||||
|
|
||||||
if fieldtype = ftstring then
|
if (fieldtype = ftstring) and (size = -1) then
|
||||||
size := pqfmod(baseres,i)-3;
|
size := pqfmod(baseres,i)-3;
|
||||||
if fieldtype = ftdate then
|
if fieldtype = ftdate then
|
||||||
size := sizeof(double);
|
size := sizeof(double);
|
||||||
@ -396,7 +421,7 @@ var st : string;
|
|||||||
begin
|
begin
|
||||||
with cursor as TPQCursor do
|
with cursor as TPQCursor do
|
||||||
begin
|
begin
|
||||||
st := 'FETCH NEXT IN selectst' + pchar(name);
|
st := pchar('FETCH NEXT IN slctst' + name+nr);
|
||||||
Res := pqexec(tr,pchar(st));
|
Res := pqexec(tr,pchar(st));
|
||||||
if (PQresultStatus(res) <> PGRES_TUPLES_OK) then
|
if (PQresultStatus(res) <> PGRES_TUPLES_OK) then
|
||||||
begin
|
begin
|
||||||
@ -477,6 +502,63 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPQConnection.UpdateIndexDefs(var IndexDefs : TIndexDefs;TableName : string);
|
||||||
|
|
||||||
|
var qry : TSQLQuery;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if not assigned(Transaction) then
|
||||||
|
DatabaseError(SErrConnTransactionnSet);
|
||||||
|
|
||||||
|
qry := tsqlquery.Create(nil);
|
||||||
|
qry.transaction := Transaction;
|
||||||
|
qry.database := Self;
|
||||||
|
with qry do
|
||||||
|
begin
|
||||||
|
ReadOnly := True;
|
||||||
|
sql.clear;
|
||||||
|
|
||||||
|
sql.add('select '+
|
||||||
|
'ic.relname as indexname, '+
|
||||||
|
'tc.relname as tablename, '+
|
||||||
|
'ia.attname, '+
|
||||||
|
'i.indisprimary, '+
|
||||||
|
'i.indisunique '+
|
||||||
|
'from '+
|
||||||
|
'pg_attribute ta, '+
|
||||||
|
'pg_attribute ia, '+
|
||||||
|
'pg_class tc, '+
|
||||||
|
'pg_class ic, '+
|
||||||
|
'pg_index i '+
|
||||||
|
'where '+
|
||||||
|
'(i.indrelid = tc.oid) and '+
|
||||||
|
'(ta.attrelid = tc.oid) and '+
|
||||||
|
'(ia.attrelid = i.indexrelid) and '+
|
||||||
|
'(ic.oid = i.indexrelid) and '+
|
||||||
|
'(ta.attnum = i.indkey[ia.attnum-1]) and '+
|
||||||
|
'(upper(tc.relname)=''' + UpperCase(TableName) +''') '+
|
||||||
|
'order by '+
|
||||||
|
'ic.relname;');
|
||||||
|
open;
|
||||||
|
end;
|
||||||
|
|
||||||
|
while not qry.eof do with IndexDefs.AddIndexDef do
|
||||||
|
begin
|
||||||
|
Name := trim(qry.fields[0].asstring);
|
||||||
|
Fields := trim(qry.Fields[2].asstring);
|
||||||
|
If qry.fields[3].asboolean then options := options + [ixPrimary];
|
||||||
|
If qry.fields[4].asboolean then options := options + [ixUnique];
|
||||||
|
qry.next;
|
||||||
|
while (name = qry.fields[0].asstring) and (not qry.eof) do
|
||||||
|
begin
|
||||||
|
Fields := Fields + ';' + trim(qry.Fields[2].asstring);
|
||||||
|
qry.next;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
qry.close;
|
||||||
|
qry.free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user