mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-27 14:52:31 +01:00
fcl-db: oracle:
- bind date and datetime params using Oracle external data type SQLT_TIMESTAMP instead of SQLT_ODT to support fraction seconds - introduce support for ftBlob and ftMemo params, but only with max.length up to 64K git-svn-id: trunk@28041 -
This commit is contained in:
parent
57b233e724
commit
742faaed92
@ -58,8 +58,8 @@ type
|
|||||||
FOciUserSession : POCISession;
|
FOciUserSession : POCISession;
|
||||||
FUserMem : pointer;
|
FUserMem : pointer;
|
||||||
procedure HandleError;
|
procedure HandleError;
|
||||||
procedure GetParameters(cursor : TSQLCursor;AParams : TParams);
|
procedure GetParameters(cursor : TSQLCursor; AParams : TParams);
|
||||||
procedure SetParameters(cursor : TSQLCursor;AParams : TParams);
|
procedure SetParameters(cursor : TSQLCursor; AParams : TParams);
|
||||||
protected
|
protected
|
||||||
// - Connect/disconnect
|
// - Connect/disconnect
|
||||||
procedure DoInternalConnect; override;
|
procedure DoInternalConnect; override;
|
||||||
@ -117,6 +117,17 @@ ResourceString
|
|||||||
SErrHandleAllocFailed = 'The allocation of the error handle failed.';
|
SErrHandleAllocFailed = 'The allocation of the error handle failed.';
|
||||||
SErrOracle = 'Oracle returned error %s:';
|
SErrOracle = 'Oracle returned error %s:';
|
||||||
|
|
||||||
|
type
|
||||||
|
TODateTime = record
|
||||||
|
year : sb2;
|
||||||
|
month : ub1;
|
||||||
|
day : ub1;
|
||||||
|
hour : ub1;
|
||||||
|
min : ub1;
|
||||||
|
sec : ub1;
|
||||||
|
fsec : ub4;
|
||||||
|
end;
|
||||||
|
|
||||||
// Callback functions
|
// Callback functions
|
||||||
|
|
||||||
function cbf_no_data(ictxp:Pdvoid; bindp:POCIBind; iter:ub4; index:ub4; bufpp:PPdvoid;
|
function cbf_no_data(ictxp:Pdvoid; bindp:POCIBind; iter:ub4; index:ub4; bufpp:PPdvoid;
|
||||||
@ -324,46 +335,35 @@ begin
|
|||||||
Raise E;
|
Raise E;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TOracleConnection.GetParameters(cursor: TSQLCursor; AParams: TParams
|
procedure TOracleConnection.GetParameters(cursor: TSQLCursor; AParams: TParams);
|
||||||
);
|
var
|
||||||
var SQLVarNr : integer;
|
i : integer;
|
||||||
i : integer;
|
odt : TODateTime;
|
||||||
f : double;
|
s : string;
|
||||||
year,month,day : word;
|
|
||||||
pb : pbyte;
|
|
||||||
s : string;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
with cursor as TOracleCursor do for SQLVarNr := 0 to High(ParamBuffers) do
|
with cursor as TOracleCursor do for i := 0 to High(ParamBuffers) do
|
||||||
with AParams[SQLVarNr] do
|
with AParams[i] do
|
||||||
if ParamType=ptOutput then
|
if ParamType=ptOutput then
|
||||||
begin
|
begin
|
||||||
if parambuffers[SQLVarNr].ind = -1 then
|
if ParamBuffers[i].ind = -1 then
|
||||||
Value:=null;
|
Value:=null;
|
||||||
|
|
||||||
case DataType of
|
case DataType of
|
||||||
ftInteger : begin
|
ftInteger : AsInteger := PInteger(ParamBuffers[i].buffer)^;
|
||||||
move(parambuffers[SQLVarNr].buffer^,i,sizeof(integer));
|
ftFloat : AsFloat := PDouble(ParamBuffers[i].buffer)^;
|
||||||
asInteger := i;
|
|
||||||
end;
|
|
||||||
ftFloat : begin
|
|
||||||
move(parambuffers[SQLVarNr].buffer^,f,sizeof(double));
|
|
||||||
asFloat := f;
|
|
||||||
end;
|
|
||||||
ftString : begin
|
ftString : begin
|
||||||
SetLength(s,parambuffers[SQLVarNr].Len);
|
SetLength(s,ParamBuffers[i].Len);
|
||||||
move(parambuffers[SQLVarNr].buffer^,s[1],length(s)+1);
|
move(ParamBuffers[i].buffer^,s[1],length(s)+1);
|
||||||
asString:=s;
|
AsString:=s;
|
||||||
end;
|
end;
|
||||||
ftDate, ftDateTime: begin
|
ftDate, ftDateTime: begin
|
||||||
pb := parambuffers[SQLVarNr].buffer;
|
OCIDateTimeGetDate(FOciUserSession, FOciError, ParamBuffers[i].buffer, @odt.year, @odt.month, @odt.day);
|
||||||
year:=(pb[0]-100)*100+pb[1]-100;
|
OCIDateTimeGetTime(FOciUserSession, FOciError, ParamBuffers[i].buffer, @odt.hour, @odt.min, @odt.sec, @odt.fsec);
|
||||||
month:=pb[2];
|
AsDateTime := ComposeDateTime(EncodeDate(odt.year,odt.month,odt.day), EncodeTime(odt.hour,odt.min,odt.sec,odt.fsec div 1000000));
|
||||||
day:=pb[3];
|
|
||||||
asDateTime:=EncodeDate(year,month,day);
|
|
||||||
end;
|
end;
|
||||||
ftFMTBcd : begin
|
ftFMTBcd : begin
|
||||||
AsFMTBCD:=Nvu2FmtBCE(parambuffers[SQLVarNr].buffer);
|
AsFMTBCD:=Nvu2FmtBCE(ParamBuffers[i].buffer);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -524,11 +524,13 @@ end;
|
|||||||
procedure TOracleConnection.PrepareStatement(cursor: TSQLCursor;
|
procedure TOracleConnection.PrepareStatement(cursor: TSQLCursor;
|
||||||
ATransaction: TSQLTransaction; buf: string; AParams: TParams);
|
ATransaction: TSQLTransaction; buf: string; AParams: TParams);
|
||||||
|
|
||||||
var counter : integer;
|
var i : integer;
|
||||||
FOcibind : POCIDefine;
|
FOcibind : POCIDefine;
|
||||||
|
|
||||||
OFieldType : ub2;
|
OFieldType : ub2;
|
||||||
OFieldSize : sb4;
|
OFieldSize : sb4;
|
||||||
|
ODescType : ub4;
|
||||||
|
OBuffer : pointer;
|
||||||
|
|
||||||
stmttype : ub2;
|
stmttype : ub2;
|
||||||
|
|
||||||
@ -541,14 +543,14 @@ begin
|
|||||||
if OCIAttrGet(FOciStmt,OCI_HTYPE_STMT,@stmttype,nil,OCI_ATTR_STMT_TYPE,FOciError) = OCI_ERROR then
|
if OCIAttrGet(FOciStmt,OCI_HTYPE_STMT,@stmttype,nil,OCI_ATTR_STMT_TYPE,FOciError) = OCI_ERROR then
|
||||||
HandleError;
|
HandleError;
|
||||||
case stmttype of
|
case stmttype of
|
||||||
OCI_STMT_SELECT:FStatementType := stSelect;
|
OCI_STMT_SELECT: FStatementType := stSelect;
|
||||||
OCI_STMT_UPDATE:FStatementType := stUpdate;
|
OCI_STMT_UPDATE: FStatementType := stUpdate;
|
||||||
OCI_STMT_DELETE:FStatementType := stDelete;
|
OCI_STMT_DELETE: FStatementType := stDelete;
|
||||||
OCI_STMT_INSERT:FStatementType := stInsert;
|
OCI_STMT_INSERT: FStatementType := stInsert;
|
||||||
OCI_STMT_CREATE,
|
OCI_STMT_CREATE,
|
||||||
OCI_STMT_DROP,
|
OCI_STMT_DROP,
|
||||||
OCI_STMT_DECLARE,
|
OCI_STMT_DECLARE,
|
||||||
OCI_STMT_ALTER:FStatementType := stDDL;
|
OCI_STMT_ALTER: FStatementType := stDDL;
|
||||||
else
|
else
|
||||||
FStatementType := stUnknown;
|
FStatementType := stUnknown;
|
||||||
end;
|
end;
|
||||||
@ -557,10 +559,10 @@ begin
|
|||||||
if assigned(AParams) then
|
if assigned(AParams) then
|
||||||
begin
|
begin
|
||||||
setlength(ParamBuffers,AParams.Count);
|
setlength(ParamBuffers,AParams.Count);
|
||||||
for counter := 0 to AParams.Count-1 do
|
for i := 0 to AParams.Count-1 do
|
||||||
begin
|
begin
|
||||||
|
ODescType := 0;
|
||||||
case AParams[counter].DataType of
|
case AParams[i].DataType of
|
||||||
ftSmallInt, ftInteger :
|
ftSmallInt, ftInteger :
|
||||||
begin OFieldType := SQLT_INT; OFieldSize := sizeof(integer); end;
|
begin OFieldType := SQLT_INT; OFieldSize := sizeof(integer); end;
|
||||||
ftLargeInt :
|
ftLargeInt :
|
||||||
@ -568,31 +570,45 @@ begin
|
|||||||
ftFloat :
|
ftFloat :
|
||||||
begin OFieldType := SQLT_FLT; OFieldSize := sizeof(double); end;
|
begin OFieldType := SQLT_FLT; OFieldSize := sizeof(double); end;
|
||||||
ftDate, ftDateTime :
|
ftDate, ftDateTime :
|
||||||
begin OFieldType := SQLT_DAT; OFieldSize := 7; end;
|
begin OFieldType := SQLT_TIMESTAMP; OFieldSize := sizeof(pointer); ODescType := OCI_DTYPE_TIMESTAMP; end;
|
||||||
ftFixedChar, ftString :
|
ftFixedChar, ftString :
|
||||||
begin OFieldType := SQLT_STR; OFieldSize := 4000; end;
|
begin OFieldType := SQLT_STR; OFieldSize := 4000; end;
|
||||||
ftFMTBcd, ftBCD :
|
ftFMTBcd, ftBCD :
|
||||||
begin OFieldType := SQLT_VNU; OFieldSize := 22; end;
|
begin OFieldType := SQLT_VNU; OFieldSize := 22; end;
|
||||||
|
ftBlob :
|
||||||
|
begin OFieldType := SQLT_LVB; OFieldSize := 65535; end;
|
||||||
|
ftMemo :
|
||||||
|
begin OFieldType := SQLT_LVC; OFieldSize := 65535; end;
|
||||||
else
|
else
|
||||||
DatabaseErrorFmt(SUnsupportedParameter,[Fieldtypenames[AParams[counter].DataType]],self);
|
DatabaseErrorFmt(SUnsupportedParameter,[Fieldtypenames[AParams[i].DataType]],self);
|
||||||
end;
|
end;
|
||||||
parambuffers[counter].buffer := getmem(OFieldSize);
|
|
||||||
parambuffers[counter].Len := OFieldSize;
|
|
||||||
parambuffers[counter].Size := OFieldSize;
|
|
||||||
|
|
||||||
|
ParamBuffers[i].DescType := ODescType;
|
||||||
|
ParamBuffers[i].Len := OFieldSize;
|
||||||
|
ParamBuffers[i].Size := OFieldSize;
|
||||||
|
if ODescType <> 0 then
|
||||||
|
begin
|
||||||
|
OBuffer := @ParamBuffers[i].buffer;
|
||||||
|
OCIDescriptorAlloc(FOciEnvironment, OBuffer, ODescType, 0, nil);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
OBuffer := getmem(OFieldSize);
|
||||||
|
ParamBuffers[i].buffer := OBuffer;
|
||||||
|
end;
|
||||||
|
|
||||||
FOciBind := nil;
|
FOciBind := nil;
|
||||||
|
|
||||||
if AParams[counter].ParamType=ptInput then
|
if AParams[i].ParamType=ptInput then
|
||||||
begin
|
begin
|
||||||
if OCIBindByName(FOciStmt,FOcibind,FOciError,pchar(AParams[counter].Name),length(AParams[counter].Name),ParamBuffers[counter].buffer,OFieldSize,OFieldType,@ParamBuffers[counter].ind,nil,nil,0,nil,OCI_DEFAULT )= OCI_ERROR then
|
if OCIBindByName(FOciStmt,FOcibind,FOciError,pchar(AParams[i].Name),length(AParams[i].Name),OBuffer,OFieldSize,OFieldType,@ParamBuffers[i].ind,nil,nil,0,nil,OCI_DEFAULT )= OCI_ERROR then
|
||||||
HandleError;
|
HandleError;
|
||||||
end
|
end
|
||||||
else if AParams[counter].ParamType=ptOutput then
|
else if AParams[i].ParamType=ptOutput then
|
||||||
begin
|
begin
|
||||||
if OCIBindByName(FOciStmt,FOcibind,FOciError,pchar(AParams[counter].Name),length(AParams[counter].Name),nil,OFieldSize,OFieldType,nil,nil,nil,0,nil,OCI_DATA_AT_EXEC )= OCI_ERROR then
|
if OCIBindByName(FOciStmt,FOcibind,FOciError,pchar(AParams[i].Name),length(AParams[i].Name),nil,OFieldSize,OFieldType,nil,nil,nil,0,nil,OCI_DATA_AT_EXEC )= OCI_ERROR then
|
||||||
HandleError;
|
HandleError;
|
||||||
if OCIBindDynamic(FOcibind, FOciError, nil, @cbf_no_data, @parambuffers[counter], @cbf_get_data) <> OCI_SUCCESS then
|
if OCIBindDynamic(FOcibind, FOciError, nil, @cbf_no_data, @parambuffers[i], @cbf_get_data) <> OCI_SUCCESS then
|
||||||
HandleError;
|
HandleError;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -601,42 +617,36 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TOracleConnection.SetParameters(cursor : TSQLCursor;AParams : TParams);
|
procedure TOracleConnection.SetParameters(cursor : TSQLCursor; AParams : TParams);
|
||||||
|
|
||||||
var SQLVarNr : integer;
|
var i : integer;
|
||||||
i : integer;
|
year, month, day, hour, min, sec, msec : word;
|
||||||
f : double;
|
|
||||||
year, month, day, hour, minute, second, millisecond : word;
|
|
||||||
pb : pbyte;
|
|
||||||
s : string;
|
s : string;
|
||||||
|
blobbuf : string;
|
||||||
|
bloblen : ub4;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
with cursor as TOracleCursor do for SQLVarNr := 0 to High(ParamBuffers) do with AParams[SQLVarNr] do
|
with cursor as TOracleCursor do for i := 0 to High(ParamBuffers) do with AParams[i] do
|
||||||
if ParamType=ptInput then
|
if ParamType=ptInput then
|
||||||
begin
|
begin
|
||||||
if IsNull then parambuffers[SQLVarNr].ind := -1 else
|
if IsNull then ParamBuffers[i].ind := -1 else ParamBuffers[i].ind := 0;
|
||||||
parambuffers[SQLVarNr].ind := 0;
|
|
||||||
|
|
||||||
case DataType of
|
case DataType of
|
||||||
ftSmallInt,
|
ftSmallInt,
|
||||||
ftInteger : begin
|
ftInteger : PInteger(ParamBuffers[i].buffer)^ := AsInteger;
|
||||||
i := asInteger;
|
ftLargeInt : PInt64(ParamBuffers[i].buffer)^ := AsLargeInt;
|
||||||
move(i,parambuffers[SQLVarNr].buffer^,sizeof(integer));
|
ftFloat : PDouble(ParamBuffers[i].buffer)^ := AsFloat;
|
||||||
end;
|
|
||||||
ftLargeInt : PInt64(parambuffers[SQLVarNr].buffer)^ := AsLargeInt;
|
|
||||||
ftFloat : begin
|
|
||||||
f := asFloat;
|
|
||||||
move(f,parambuffers[SQLVarNr].buffer^,sizeof(double));
|
|
||||||
end;
|
|
||||||
ftString,
|
ftString,
|
||||||
ftFixedChar : begin
|
ftFixedChar : begin
|
||||||
s := asString+#0;
|
s := asString+#0;
|
||||||
move(s[1],parambuffers[SQLVarNr].buffer^,length(s)+1);
|
move(s[1],parambuffers[i].buffer^,length(s)+1);
|
||||||
end;
|
end;
|
||||||
ftDate, ftDateTime: begin
|
ftDate, ftDateTime: begin
|
||||||
DecodeDate(asDateTime,year,month,day);
|
DecodeDate(asDateTime,year,month,day);
|
||||||
DecodeTime(asDateTime,hour,minute,second,millisecond);
|
DecodeTime(asDateTime,hour,min,sec,msec);
|
||||||
pb := parambuffers[SQLVarNr].buffer;
|
if OCIDateTimeConstruct(FOciUserSession, FOciError, ParamBuffers[i].buffer, year, month, day, hour, min, sec, msec*1000000, nil, 0) = OCI_ERROR then
|
||||||
|
HandleError;
|
||||||
|
{ pb := ParamBuffers[i].buffer;
|
||||||
pb[0] := (year div 100)+100;
|
pb[0] := (year div 100)+100;
|
||||||
pb[1] := (year mod 100)+100;
|
pb[1] := (year mod 100)+100;
|
||||||
pb[2] := month;
|
pb[2] := month;
|
||||||
@ -644,9 +654,19 @@ begin
|
|||||||
pb[4] := hour+1;
|
pb[4] := hour+1;
|
||||||
pb[5] := minute+1;
|
pb[5] := minute+1;
|
||||||
pb[6] := second+1;
|
pb[6] := second+1;
|
||||||
|
}
|
||||||
end;
|
end;
|
||||||
ftFmtBCD,ftBCD : begin
|
ftFmtBCD, ftBCD : begin
|
||||||
FmtBCD2Nvu(asFmtBCD,parambuffers[SQLVarNr].buffer);
|
FmtBCD2Nvu(asFmtBCD,parambuffers[i].buffer);
|
||||||
|
end;
|
||||||
|
ftBlob, ftMemo : begin
|
||||||
|
blobbuf := AsBlob; // todo: use AsBytes
|
||||||
|
bloblen := length(blobbuf);
|
||||||
|
if bloblen > 65531 then bloblen := 65531;
|
||||||
|
PInteger(ParamBuffers[i].Buffer)^ := bloblen;
|
||||||
|
Move(blobbuf[1], (ParamBuffers[i].Buffer+sizeof(integer))^, bloblen);
|
||||||
|
//if OciLobWrite(TOracleTrans(ATransaction.Handle).FOciSvcCtx, FOciError, ParamBuffers[i].buffer, @bloblen, 1, @blobbuf[1], bloblen, OCI_ONE_PIECE, nil, nil, 0, SQLCS_IMPLICIT) = OCI_ERROR then
|
||||||
|
// HandleError;
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
DatabaseErrorFmt(SUnsupportedParameter,[DataType],self);
|
DatabaseErrorFmt(SUnsupportedParameter,[DataType],self);
|
||||||
@ -945,17 +965,6 @@ end;
|
|||||||
|
|
||||||
function TOracleConnection.LoadField(cursor: TSQLCursor; FieldDef: TFieldDef; buffer: pointer; out CreateBlob : boolean): boolean;
|
function TOracleConnection.LoadField(cursor: TSQLCursor; FieldDef: TFieldDef; buffer: pointer; out CreateBlob : boolean): boolean;
|
||||||
|
|
||||||
type
|
|
||||||
TODateTime = record
|
|
||||||
year : sb2;
|
|
||||||
month : ub1;
|
|
||||||
day : ub1;
|
|
||||||
hour : ub1;
|
|
||||||
min : ub1;
|
|
||||||
sec : ub1;
|
|
||||||
fsec : ub4;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
var
|
||||||
b : pbyte;
|
b : pbyte;
|
||||||
size,i : byte;
|
size,i : byte;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user