24 |
|
{ Corporation. All Rights Reserved. } |
25 |
|
{ Contributor(s): Jeff Overcash } |
26 |
|
{ } |
27 |
+ |
{ IBX For Lazarus (Firebird Express) } |
28 |
+ |
{ Contributor: Tony Whyman, MWA Software http://www.mwasoftware.co.uk } |
29 |
+ |
{ Portions created by MWA Software are copyright McCallum Whyman } |
30 |
+ |
{ Associates Ltd 2011 } |
31 |
+ |
{ } |
32 |
|
{************************************************************************} |
33 |
|
|
34 |
|
unit IBSQL; |
38 |
|
interface |
39 |
|
|
40 |
|
uses |
41 |
< |
{$IFDEF LINUX } |
37 |
< |
baseunix,unix, |
38 |
< |
{$ELSE} |
39 |
< |
{$DEFINE HAS_SQLMONITOR} |
41 |
> |
{$IFDEF WINDOWS } |
42 |
|
Windows, |
43 |
+ |
{$ELSE} |
44 |
+ |
baseunix, unix, |
45 |
|
{$ENDIF} |
46 |
|
SysUtils, Classes, Forms, Controls, IBHeader, |
47 |
|
IBErrorCodes, IBExternals, DB, IB, IBDatabase, IBUtils, IBXConst; |
98 |
|
public |
99 |
|
constructor Create(Parent: TIBXSQLDA; Query: TIBSQL); |
100 |
|
procedure Assign(Source: TIBXSQLVAR); |
101 |
+ |
procedure Clear; |
102 |
|
procedure LoadFromFile(const FileName: String); |
103 |
|
procedure LoadFromStream(Stream: TStream); |
104 |
|
procedure SaveToFile(const FileName: String); |
191 |
|
{ TIBOutputDelimitedFile } |
192 |
|
TIBOutputDelimitedFile = class(TIBBatchOutput) |
193 |
|
protected |
194 |
< |
{$IFDEF LINUX} |
194 |
> |
{$IFDEF UNIX} |
195 |
|
FHandle: cint; |
196 |
|
{$ELSE} |
197 |
|
FHandle: THandle; |
234 |
|
{ TIBOutputRawFile } |
235 |
|
TIBOutputRawFile = class(TIBBatchOutput) |
236 |
|
protected |
237 |
< |
{$IFDEF LINUX} |
237 |
> |
{$IFDEF UNIX} |
238 |
|
FHandle: cint; |
239 |
|
{$ELSE} |
240 |
|
FHandle: THandle; |
248 |
|
{ TIBInputRawFile } |
249 |
|
TIBInputRawFile = class(TIBBatchInput) |
250 |
|
protected |
251 |
< |
{$IFDEF LINUX} |
251 |
> |
{$IFDEF UNIX} |
252 |
|
FHandle: cint; |
253 |
|
{$ELSE} |
254 |
|
FHandle: THandle; |
270 |
|
TIBSQL = class(TComponent) |
271 |
|
private |
272 |
|
FIBLoaded: Boolean; |
273 |
+ |
function GetFieldCount: integer; |
274 |
|
protected |
275 |
|
FBase: TIBBase; |
276 |
|
FBOF, { At BOF? } |
330 |
|
property Eof: Boolean read GetEOF; |
331 |
|
property Fields[const Idx: Integer]: TIBXSQLVAR read GetFields; |
332 |
|
property FieldIndex[FieldName: String]: Integer read GetFieldIndex; |
333 |
+ |
property FieldCount: integer read GetFieldCount; |
334 |
|
property Open: Boolean read FOpen; |
335 |
|
property Params: TIBXSQLDA read GetSQLParams; |
336 |
|
property Plan: String read GetPlan; |
356 |
|
implementation |
357 |
|
|
358 |
|
uses |
359 |
< |
IBIntf, IBBlob, Variants {$IFDEF HAS_SQLMONITOR}, IBSQLMonitor {$ENDIF}; |
359 |
> |
IBIntf, IBBlob, Variants , IBSQLMonitor; |
360 |
|
|
361 |
|
{ TIBXSQLVAR } |
362 |
|
constructor TIBXSQLVAR.Create(Parent: TIBXSQLDA; Query: TIBSQL); |
371 |
|
szBuff: PChar; |
372 |
|
s_bhandle, d_bhandle: TISC_BLOB_HANDLE; |
373 |
|
bSourceBlob, bDestBlob: Boolean; |
374 |
< |
iSegs, iMaxSeg, iSize: Long; |
374 |
> |
iSegs: Int64; |
375 |
> |
iMaxSeg: Int64; |
376 |
> |
iSize: Int64; |
377 |
|
iBlobType: Short; |
378 |
|
begin |
379 |
|
szBuff := nil; |
435 |
|
0, nil), True); |
436 |
|
try |
437 |
|
IBBlob.WriteBlob(@d_bhandle, szBuff, iSize); |
438 |
+ |
isNull := false |
439 |
|
finally |
440 |
|
FSQL.Call(isc_close_blob(StatusVector, @d_bhandle), True); |
441 |
|
end; |
594 |
|
function TIBXSQLVAR.GetAsDateTime: TDateTime; |
595 |
|
var |
596 |
|
tm_date: TCTimeStructure; |
597 |
+ |
msecs: word; |
598 |
|
begin |
599 |
|
result := 0; |
600 |
|
if not IsNull then |
620 |
|
SQL_TYPE_TIME: begin |
621 |
|
isc_decode_sql_time(PISC_TIME(FXSQLVAR^.sqldata), @tm_date); |
622 |
|
try |
623 |
+ |
msecs := (PISC_TIME(FXSQLVAR^.sqldata)^ mod 10000) div 10; |
624 |
|
result := EncodeTime(Word(tm_date.tm_hour), Word(tm_date.tm_min), |
625 |
< |
Word(tm_date.tm_sec), 0) |
625 |
> |
Word(tm_date.tm_sec), msecs) |
626 |
|
except |
627 |
|
on E: EConvertError do begin |
628 |
|
IBError(ibxeInvalidDataConversion, [nil]); |
634 |
|
try |
635 |
|
result := EncodeDate(Word(tm_date.tm_year + 1900), Word(tm_date.tm_mon + 1), |
636 |
|
Word(tm_date.tm_mday)); |
637 |
+ |
msecs := (PISC_TIMESTAMP(FXSQLVAR^.sqldata)^.timestamp_time mod 10000) div 10; |
638 |
|
if result >= 0 then |
639 |
|
result := result + EncodeTime(Word(tm_date.tm_hour), Word(tm_date.tm_min), |
640 |
< |
Word(tm_date.tm_sec), 0) |
640 |
> |
Word(tm_date.tm_sec), msecs) |
641 |
|
else |
642 |
|
result := result - EncodeTime(Word(tm_date.tm_hour), Word(tm_date.tm_min), |
643 |
< |
Word(tm_date.tm_sec), 0) |
643 |
> |
Word(tm_date.tm_sec), msecs) |
644 |
|
except |
645 |
|
on E: EConvertError do begin |
646 |
|
IBError(ibxeInvalidDataConversion, [nil]); |
770 |
|
result := '(Array)'; {do not localize} |
771 |
|
SQL_BLOB: begin |
772 |
|
ss := TStringStream.Create(''); |
773 |
< |
SaveToStream(ss); |
774 |
< |
result := ss.DataString; |
775 |
< |
ss.Free; |
773 |
> |
try |
774 |
> |
SaveToStream(ss); |
775 |
> |
result := ss.DataString; |
776 |
> |
finally |
777 |
> |
ss.Free; |
778 |
> |
end; |
779 |
|
end; |
780 |
|
SQL_TEXT, SQL_VARYING: begin |
781 |
|
sz := FXSQLVAR^.sqldata; |
1048 |
|
xvar.FXSQLVAR^.sqllen := SizeOf(ISC_TIME); |
1049 |
|
IBAlloc(xvar.FXSQLVAR^.sqldata, 0, xvar.FXSQLVAR^.sqllen); |
1050 |
|
isc_encode_sql_time(@tm_date, PISC_TIME(xvar.FXSQLVAR^.sqldata)); |
1051 |
+ |
if Ms > 0 then |
1052 |
+ |
Inc(PISC_TIME(xvar.FXSQLVAR^.sqldata)^,Ms*10); |
1053 |
|
xvar.FModified := True; |
1054 |
|
end; |
1055 |
|
end; |
1081 |
|
xvar.FXSQLVAR^.sqllen := SizeOf(TISC_QUAD); |
1082 |
|
IBAlloc(xvar.FXSQLVAR^.sqldata, 0, xvar.FXSQLVAR^.sqllen); |
1083 |
|
isc_encode_date(@tm_date, PISC_QUAD(xvar.FXSQLVAR^.sqldata)); |
1084 |
+ |
if Ms > 0 then |
1085 |
+ |
Inc(PISC_TIMESTAMP(xvar.FXSQLVAR^.sqldata)^.timestamp_time,Ms*10); |
1086 |
|
xvar.FModified := True; |
1087 |
|
end; |
1088 |
|
end; |
1385 |
|
end; |
1386 |
|
end; |
1387 |
|
|
1388 |
+ |
procedure TIBXSQLVAR.Clear; |
1389 |
+ |
begin |
1390 |
+ |
IsNull := true; |
1391 |
+ |
end; |
1392 |
+ |
|
1393 |
+ |
|
1394 |
|
{ TIBXSQLDA } |
1395 |
|
constructor TIBXSQLDA.Create(Query: TIBSQL); |
1396 |
|
begin |
1613 |
|
|
1614 |
|
destructor TIBOutputDelimitedFile.Destroy; |
1615 |
|
begin |
1616 |
< |
{$IFDEF LINUX} |
1616 |
> |
{$IFDEF UNIX} |
1617 |
|
if FHandle <> -1 then |
1618 |
|
fpclose(FHandle); |
1619 |
|
{$ELSE} |
1629 |
|
procedure TIBOutputDelimitedFile.ReadyFile; |
1630 |
|
var |
1631 |
|
i: Integer; |
1632 |
< |
{$IFDEF LINUX} |
1632 |
> |
{$IFDEF UNIX} |
1633 |
|
BytesWritten: cint; |
1634 |
|
{$ELSE} |
1635 |
|
BytesWritten: DWORD; |
1640 |
|
FColDelimiter := TAB; |
1641 |
|
if FRowDelimiter = '' then |
1642 |
|
FRowDelimiter := CRLF; |
1643 |
< |
{$IFDEF LINUX} |
1643 |
> |
{$IFDEF UNIX} |
1644 |
|
FHandle := FpOpen(Filename,O_WrOnly or O_Creat); |
1645 |
|
{$ELSE} |
1646 |
|
FHandle := CreateFile(PChar(Filename), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, |
1656 |
|
else |
1657 |
|
st := st + FColDelimiter + strpas(Columns[i].Data^.aliasname); |
1658 |
|
st := st + FRowDelimiter; |
1659 |
< |
{$IFDEF LINUX} |
1659 |
> |
{$IFDEF UNIX} |
1660 |
|
if FHandle <> -1 then |
1661 |
|
BytesWritten := FpWrite(FHandle,st[1],Length(st)); |
1662 |
|
if BytesWritten = -1 then |
1663 |
|
raise Exception.Create('File Write Error'); |
1664 |
|
{$ELSE} |
1665 |
< |
WriteFile(FHandle, PChar(st[1]), Length(st), BytesWritten, nil); |
1665 |
> |
WriteFile(FHandle, st[1], Length(st), BytesWritten, nil); |
1666 |
|
{$ENDIF} |
1667 |
|
end; |
1668 |
|
end; |
1670 |
|
function TIBOutputDelimitedFile.WriteColumns: Boolean; |
1671 |
|
var |
1672 |
|
i: Integer; |
1673 |
< |
{$IFDEF LINUX} |
1673 |
> |
{$IFDEF UNIX} |
1674 |
|
BytesWritten: cint; |
1675 |
|
{$ELSE} |
1676 |
|
BytesWritten: DWORD; |
1678 |
|
st: string; |
1679 |
|
begin |
1680 |
|
result := False; |
1681 |
< |
{$IFDEF LINUX} |
1681 |
> |
{$IFDEF UNIX} |
1682 |
|
if FHandle <> -1 then |
1683 |
|
{$ELSE} |
1684 |
|
if FHandle <> 0 then |
1692 |
|
st := st + StripString(Columns[i].AsString, FColDelimiter + FRowDelimiter); |
1693 |
|
end; |
1694 |
|
st := st + FRowDelimiter; |
1695 |
< |
{$IFDEF LINUX} |
1695 |
> |
{$IFDEF UNIX} |
1696 |
|
BytesWritten := FpWrite(FHandle,st[1],Length(st)); |
1697 |
|
{$ELSE} |
1698 |
|
WriteFile(FHandle, st[1], Length(st), BytesWritten, nil); |
1809 |
|
{ TIBOutputRawFile } |
1810 |
|
destructor TIBOutputRawFile.Destroy; |
1811 |
|
begin |
1812 |
< |
{$IFDEF LINUX} |
1812 |
> |
{$IFDEF UNIX} |
1813 |
|
if FHandle <> -1 then |
1814 |
|
fpclose(FHandle); |
1815 |
|
{$ELSE} |
1824 |
|
|
1825 |
|
procedure TIBOutputRawFile.ReadyFile; |
1826 |
|
begin |
1827 |
< |
{$IFDEF LINUX} |
1827 |
> |
{$IFDEF UNIX} |
1828 |
|
FHandle := FpOpen(Filename,O_WrOnly or O_Creat); |
1829 |
|
{$ELSE} |
1830 |
|
FHandle := CreateFile(PChar(Filename), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, |
1844 |
|
begin |
1845 |
|
for i := 0 to Columns.Count - 1 do |
1846 |
|
begin |
1847 |
< |
{$IFDEF LINUX} |
1847 |
> |
{$IFDEF UNIX} |
1848 |
|
BytesWritten := FpWrite(FHandle,Columns[i].Data^.sqldata^, Columns[i].Data^.sqllen); |
1849 |
|
{$ELSE} |
1850 |
|
WriteFile(FHandle, Columns[i].Data^.sqldata^, Columns[i].Data^.sqllen, |
1860 |
|
{ TIBInputRawFile } |
1861 |
|
destructor TIBInputRawFile.Destroy; |
1862 |
|
begin |
1863 |
< |
{$IFDEF LINUX} |
1863 |
> |
{$IFDEF UNIX} |
1864 |
|
if FHandle <> -1 then |
1865 |
|
fpclose(FHandle); |
1866 |
|
{$ELSE} |
1876 |
|
BytesRead: DWord; |
1877 |
|
begin |
1878 |
|
result := False; |
1879 |
< |
{$IFDEF LINUX} |
1879 |
> |
{$IFDEF UNIX} |
1880 |
|
if FHandle <> -1 then |
1881 |
|
{$ELSE} |
1882 |
|
if FHandle <> 0 then |
1884 |
|
begin |
1885 |
|
for i := 0 to Params.Count - 1 do |
1886 |
|
begin |
1887 |
< |
{$IFDEF LINUX} |
1887 |
> |
{$IFDEF UNIX} |
1888 |
|
BytesRead := FpRead(FHandle,Params[i].Data^.sqldata^,Params[i].Data^.sqllen); |
1889 |
|
{$ELSE} |
1890 |
< |
ReadFile(FHandle, Params[i].Data^.sqldata^, Params[i].Data^.sqllen); |
1890 |
> |
ReadFile(FHandle, Params[i].Data^.sqldata^, Params[i].Data^.sqllen, |
1891 |
|
BytesRead, nil); |
1892 |
|
{$ENDIF} |
1893 |
|
if BytesRead <> DWORD(Params[i].Data^.sqllen) then |
1899 |
|
|
1900 |
|
procedure TIBInputRawFile.ReadyFile; |
1901 |
|
begin |
1902 |
< |
{$IFDEF LINUX} |
1902 |
> |
{$IFDEF UNIX} |
1903 |
|
if FHandle <> -1 then |
1904 |
|
fpclose(FHandle); |
1905 |
|
FHandle := FpOpen(Filename,O_RdOnly); |
2049 |
|
result := FSQLRecord; |
2050 |
|
end; |
2051 |
|
|
2052 |
+ |
function TIBSQL.GetFieldCount: integer; |
2053 |
+ |
begin |
2054 |
+ |
Result := FSQLRecord.Count |
2055 |
+ |
end; |
2056 |
+ |
|
2057 |
|
procedure TIBSQL.DoBeforeDatabaseDisconnect(Sender: TObject); |
2058 |
|
begin |
2059 |
|
if (FHandle <> nil) then begin |
2118 |
|
Database.SQLDialect, |
2119 |
|
FSQLParams.AsXSQLDA), True) |
2120 |
|
end; |
2090 |
– |
{$IFDEF HAS_SQLMONITOR} |
2121 |
|
if not (csDesigning in ComponentState) then |
2122 |
|
MonitorHook.SQLExecute(Self); |
2093 |
– |
{$ENDIF} |
2123 |
|
end; |
2124 |
|
|
2125 |
|
function TIBSQL.GetEOF: Boolean; |
2181 |
|
FBOF := False; |
2182 |
|
result := FSQLRecord; |
2183 |
|
end; |
2155 |
– |
{$IFDEF HAS_SQLMONITOR} |
2184 |
|
if not (csDesigning in ComponentState) then |
2185 |
|
MonitorHook.SQLFetch(Self); |
2158 |
– |
{$ENDIF} |
2186 |
|
end; |
2187 |
|
end; |
2188 |
|
|
2513 |
|
end; |
2514 |
|
end; |
2515 |
|
FPrepared := True; |
2489 |
– |
{$IFDEF HAS_SQLMONITOR} |
2516 |
|
if not (csDesigning in ComponentState) then |
2517 |
|
MonitorHook.SQLPrepare(Self); |
2492 |
– |
{$ENDIF} |
2518 |
|
except |
2519 |
|
on E: Exception do begin |
2520 |
|
if (FHandle <> nil) then |