|
@@ -31,12 +31,17 @@ type
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TPQCursor }
|
|
{ TPQCursor }
|
|
|
|
+ // TField and TFieldDef only support a limited amount of fields.
|
|
|
|
+ // TFieldBinding and TExtendedFieldType can be used to map PQ types
|
|
|
|
+ // on standard fields and retain mapping info.
|
|
TExtendedFieldType = (eftNone,eftEnum);
|
|
TExtendedFieldType = (eftNone,eftEnum);
|
|
|
|
+
|
|
TFieldBinding = record
|
|
TFieldBinding = record
|
|
- Index : Integer;
|
|
|
|
- TypeOID : oid;
|
|
|
|
- TypeName : String;
|
|
|
|
- ExtendedFieldType: TExtendedFieldType;
|
|
|
|
|
|
+ FieldDef : TSQLDBFieldDef; // FieldDef this is associated with
|
|
|
|
+ Index : Integer; // Tuple index
|
|
|
|
+ TypeOID : oid; // Filled with type OID if it is not standard.
|
|
|
|
+ TypeName : String; // Filled with type name by getextendedfieldInfo
|
|
|
|
+ ExtendedFieldType: TExtendedFieldType; //
|
|
end;
|
|
end;
|
|
PFieldBinding = ^TFieldBinding;
|
|
PFieldBinding = ^TFieldBinding;
|
|
TFieldBindings = Array of TFieldBinding;
|
|
TFieldBindings = Array of TFieldBinding;
|
|
@@ -49,6 +54,7 @@ type
|
|
res : PPGresult;
|
|
res : PPGresult;
|
|
CurTuple : integer;
|
|
CurTuple : integer;
|
|
FieldBinding : TFieldBindings;
|
|
FieldBinding : TFieldBindings;
|
|
|
|
+ Function GetFieldBinding(F : TFieldDef): PFieldBinding;
|
|
Public
|
|
Public
|
|
Destructor Destroy; override;
|
|
Destructor Destroy; override;
|
|
end;
|
|
end;
|
|
@@ -84,6 +90,7 @@ type
|
|
procedure ExecuteDirectPG(const Query : String);
|
|
procedure ExecuteDirectPG(const Query : String);
|
|
Procedure GetExtendedFieldInfo(cursor: TPQCursor; Bindings : TFieldBindings);
|
|
Procedure GetExtendedFieldInfo(cursor: TPQCursor; Bindings : TFieldBindings);
|
|
protected
|
|
protected
|
|
|
|
+ procedure ApplyFieldUpdate(C : TSQLCursor; P: TSQLDBParam; F: TField; UseOldValue: Boolean); override;
|
|
Function ErrorOnUnknownType : Boolean;
|
|
Function ErrorOnUnknownType : Boolean;
|
|
// Add connection to pool.
|
|
// Add connection to pool.
|
|
procedure AddConnection(T: TPQTranConnection);
|
|
procedure AddConnection(T: TPQTranConnection);
|
|
@@ -150,10 +157,7 @@ ResourceString
|
|
SErrCommitFailed = 'Commit transaction failed';
|
|
SErrCommitFailed = 'Commit transaction failed';
|
|
SErrConnectionFailed = 'Connection to database failed';
|
|
SErrConnectionFailed = 'Connection to database failed';
|
|
SErrTransactionFailed = 'Start of transacion failed';
|
|
SErrTransactionFailed = 'Start of transacion failed';
|
|
- SErrClearSelection = 'Clear of selection failed';
|
|
|
|
SErrExecuteFailed = 'Execution of query failed';
|
|
SErrExecuteFailed = 'Execution of query failed';
|
|
- SErrFieldDefsFailed = 'Can not extract field information from query';
|
|
|
|
- SErrFetchFailed = 'Fetch of data failed';
|
|
|
|
SErrPrepareFailed = 'Preparation of query failed.';
|
|
SErrPrepareFailed = 'Preparation of query failed.';
|
|
SErrUnPrepareFailed = 'Unpreparation of query failed.';
|
|
SErrUnPrepareFailed = 'Unpreparation of query failed.';
|
|
|
|
|
|
@@ -223,6 +227,29 @@ end;
|
|
|
|
|
|
{ TPQCursor }
|
|
{ TPQCursor }
|
|
|
|
|
|
|
|
+function TPQCursor.GetFieldBinding(F: TFieldDef): PFieldBinding;
|
|
|
|
+
|
|
|
|
+Var
|
|
|
|
+ I : Integer;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ Result:=Nil;
|
|
|
|
+ if (F=Nil) then exit;
|
|
|
|
+ // This is an optimization: it is so for 99% of cases (FieldNo-1=array index)
|
|
|
|
+ if F is TSQLDBFieldDef then
|
|
|
|
+ Result:=PFieldBinding(TSQLDBFieldDef(F).SQLDBData)
|
|
|
|
+ else If (FieldBinding[F.FieldNo-1].FieldDef=F) then
|
|
|
|
+ Result:=@FieldBinding[F.FieldNo-1]
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ I:=Length(FieldBinding)-1;
|
|
|
|
+ While (I>=0) and (FieldBinding[i].FieldDef<>F) do
|
|
|
|
+ Dec(I);
|
|
|
|
+ if I>=0 then
|
|
|
|
+ Result:=@FieldBinding[i];
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
destructor TPQCursor.Destroy;
|
|
destructor TPQCursor.Destroy;
|
|
begin
|
|
begin
|
|
if Assigned(tr) then
|
|
if Assigned(tr) then
|
|
@@ -342,6 +369,14 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure TPQConnection.ApplyFieldUpdate(C : TSQLCursor; P: TSQLDBParam; F: TField;
|
|
|
|
+ UseOldValue: Boolean);
|
|
|
|
+begin
|
|
|
|
+ inherited ApplyFieldUpdate(C,P, F, UseOldValue);
|
|
|
|
+ if (C is TPQCursor) then
|
|
|
|
+ P.SQLDBData:=TPQCursor(C).GetFieldBinding(F.FieldDef);
|
|
|
|
+end;
|
|
|
|
+
|
|
function TPQConnection.ErrorOnUnknownType: Boolean;
|
|
function TPQConnection.ErrorOnUnknownType: Boolean;
|
|
begin
|
|
begin
|
|
Result:=False;
|
|
Result:=False;
|
|
@@ -802,8 +837,11 @@ const TypeStrings : array[TFieldType] of string =
|
|
);
|
|
);
|
|
|
|
|
|
|
|
|
|
-var s : string;
|
|
|
|
- i : integer;
|
|
|
|
|
|
+var
|
|
|
|
+ s,ts : string;
|
|
|
|
+ i : integer;
|
|
|
|
+ P : TParam;
|
|
|
|
+ PQ : TSQLDBParam;
|
|
|
|
|
|
begin
|
|
begin
|
|
with (cursor as TPQCursor) do
|
|
with (cursor as TPQCursor) do
|
|
@@ -824,8 +862,21 @@ begin
|
|
begin
|
|
begin
|
|
s := s + '(';
|
|
s := s + '(';
|
|
for i := 0 to AParams.Count-1 do
|
|
for i := 0 to AParams.Count-1 do
|
|
- if TypeStrings[AParams[i].DataType] <> 'Unknown' then
|
|
|
|
- s := s + TypeStrings[AParams[i].DataType] + ','
|
|
|
|
|
|
+ begin
|
|
|
|
+ P:=AParams[i];
|
|
|
|
+ If (P is TSQLDBParam) then
|
|
|
|
+ PQ:=TSQLDBParam(P)
|
|
|
|
+ else
|
|
|
|
+ PQ:=Nil;
|
|
|
|
+ TS:=TypeStrings[P.DataType];
|
|
|
|
+ if (TS<>'Unknown') then
|
|
|
|
+ begin
|
|
|
|
+ If Assigned(PQ)
|
|
|
|
+ and Assigned(PQ.SQLDBData)
|
|
|
|
+ and (PFieldBinding(PQ.SQLDBData)^.ExtendedFieldType=eftEnum) then
|
|
|
|
+ ts:='unknown';
|
|
|
|
+ s := s + ts + ','
|
|
|
|
+ end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
if AParams[i].DataType = ftUnknown then
|
|
if AParams[i].DataType = ftUnknown then
|
|
@@ -838,6 +889,7 @@ begin
|
|
else
|
|
else
|
|
DatabaseErrorFmt(SUnsupportedParameter,[Fieldtypenames[AParams[i].DataType]],self);
|
|
DatabaseErrorFmt(SUnsupportedParameter,[Fieldtypenames[AParams[i].DataType]],self);
|
|
end;
|
|
end;
|
|
|
|
+ end;
|
|
s[length(s)] := ')';
|
|
s[length(s)] := ')';
|
|
buf := AParams.ParseSQL(buf,false,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psPostgreSQL);
|
|
buf := AParams.ParseSQL(buf,false,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psPostgreSQL);
|
|
end;
|
|
end;
|
|
@@ -992,8 +1044,9 @@ var
|
|
nFields : integer;
|
|
nFields : integer;
|
|
b : Boolean;
|
|
b : Boolean;
|
|
Q : TPQCursor;
|
|
Q : TPQCursor;
|
|
- FD : TFieldDef;
|
|
|
|
|
|
+ FD : TSQLDBFieldDef;
|
|
FB : PFieldBinding;
|
|
FB : PFieldBinding;
|
|
|
|
+ C : TFieldDefClass;
|
|
|
|
|
|
begin
|
|
begin
|
|
B:=False;
|
|
B:=False;
|
|
@@ -1005,10 +1058,13 @@ begin
|
|
for i := 0 to nFields-1 do
|
|
for i := 0 to nFields-1 do
|
|
begin
|
|
begin
|
|
fieldtype := TranslateFldType(Res, i,size, aoid );
|
|
fieldtype := TranslateFldType(Res, i,size, aoid );
|
|
- with TFieldDef.Create(FieldDefs, FieldDefs.MakeNameUnique(PQfname(Res, i)), fieldtype,size, False, (i + 1)) do
|
|
|
|
|
|
+ FD:=FieldDefs.Add(FieldDefs.MakeNameUnique(PQfname(Res, i)),fieldtype,Size,False,I+1) as TSQLDBFieldDef;
|
|
|
|
+ With FD do
|
|
begin
|
|
begin
|
|
- FieldBinding[FieldNo-1].Index := i;
|
|
|
|
- FieldBinding[FieldNo-1].TypeOID:=aOID;
|
|
|
|
|
|
+ SQLDBData:=@FieldBinding[i];
|
|
|
|
+ FieldBinding[i].Index:=i;
|
|
|
|
+ FieldBinding[i].FieldDef:=FD;
|
|
|
|
+ FieldBinding[i].TypeOID:=aOID;
|
|
B:=B or (aOID>0);
|
|
B:=B or (aOID>0);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
@@ -1023,13 +1079,13 @@ begin
|
|
FB:[email protected][i];
|
|
FB:[email protected][i];
|
|
if (FB^.TypeOID>0) then
|
|
if (FB^.TypeOID>0) then
|
|
begin
|
|
begin
|
|
- FD:=FieldDefs[FB^.Index];
|
|
|
|
|
|
+ FD:=FB^.FieldDef;
|
|
Case FB^.ExtendedFieldType of
|
|
Case FB^.ExtendedFieldType of
|
|
eftEnum :
|
|
eftEnum :
|
|
begin
|
|
begin
|
|
FD.DataType:=ftString;
|
|
FD.DataType:=ftString;
|
|
FD.Size:=64;
|
|
FD.Size:=64;
|
|
- FD.Attributes:=FD.Attributes+[faReadonly];
|
|
|
|
|
|
+ //FD.Attributes:=FD.Attributes+[faReadonly];
|
|
end
|
|
end
|
|
else
|
|
else
|
|
if ErrorOnUnknownType then
|
|
if ErrorOnUnknownType then
|
|
@@ -1133,7 +1189,7 @@ begin
|
|
Createblob := False;
|
|
Createblob := False;
|
|
with cursor as TPQCursor do
|
|
with cursor as TPQCursor do
|
|
begin
|
|
begin
|
|
- x := FieldBinding[FieldDef.FieldNo-1].Index;
|
|
|
|
|
|
+ x := GetFieldBinding(FieldDef)^.Index;
|
|
|
|
|
|
// Joost, 5 jan 2006: I disabled the following, since it's useful for
|
|
// Joost, 5 jan 2006: I disabled the following, since it's useful for
|
|
// debugging, but it also slows things down. In principle things can only go
|
|
// debugging, but it also slows things down. In principle things can only go
|