zeoslib  UNKNOWN
 All Files
ZDbcCache.pas
Go to the documentation of this file.
1 {*********************************************************}
2 { }
3 { Zeos Database Objects }
4 { Caching Classes and Interfaces }
5 { }
6 { Originally written by Sergey Seroukhov }
7 { }
8 {*********************************************************}
9 
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
12 { }
13 { License Agreement: }
14 { }
15 { This library is distributed in the hope that it will be }
16 { useful, but WITHOUT ANY WARRANTY; without even the }
17 { implied warranty of MERCHANTABILITY or FITNESS FOR }
18 { A PARTICULAR PURPOSE. See the GNU Lesser General }
19 { Public License for more details. }
20 { }
21 { The source code of the ZEOS Libraries and packages are }
22 { distributed under the Library GNU General Public }
23 { License (see the file COPYING / COPYING.ZEOS) }
24 { with the following modification: }
25 { As a special exception, the copyright holders of this }
26 { library give you permission to link this library with }
27 { independent modules to produce an executable, }
28 { regardless of the license terms of these independent }
29 { modules, and to copy and distribute the resulting }
30 { executable under terms of your choice, provided that }
31 { you also meet, for each linked independent module, }
32 { the terms and conditions of the license of that module. }
33 { An independent module is a module which is not derived }
34 { from or based on this library. If you modify this }
35 { library, you may extend this exception to your version }
36 { of the library, but you are not obligated to do so. }
37 { If you do not wish to do so, delete this exception }
38 { statement from your version. }
39 { }
40 { }
41 { The project web site is located on: }
42 { http://zeos.firmos.at (FORUM) }
43 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
44 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
45 { }
46 { http://www.sourceforge.net/projects/zeoslib. }
47 { }
48 { }
49 { Zeos Development Group. }
50 {********************************************************@}
51 
52 unit ZDbcCache;
53 
54 interface
55 
56 {$I ZDbc.inc}
57 
58 
59 uses
60 {$IFDEF MSWINDOWS}
61  Windows,
62 {$ENDIF}
63  Types, Classes, {$IFDEF MSEgui}mclasses,{$ENDIF} SysUtils, Contnrs,
64  ZClasses, ZDbcIntfs, ZDbcResultSet, ZDbcResultSetMetadata, ZVariant,
65  ZCompatibility;
66 
67 type
68 
69  {** Defines a row status type. }
70  TZRowUpdateType = (utUnmodified, utModified, utInserted, utDeleted);
71  TZRowUpdateTypes = set of TZRowUpdateType;
72 
73  TZByteArray = array[0..4096 * SizeOf(Pointer)] of Byte;
74  {** Defines a header for row buffer. }
75  {ludob. Notes on alignment:
76  Columns contains a record per field with the structure
77  null:byte;
78  fielddata:anything;
79  field records are addressed through offsets in Columns stored in FColumnOffsets.
80  Since anything can be stored as fielddata including pointers, fielddata needs
81  to be aligned to pointer. To do this Columns is aligned to pointer and
82  FColumnOffsets is aligned to pointer - 1 (the null:byte). The latter is
83  done in TZRowAccessor.Create where FColumnOffsets is filled in.
84  FPC_REQUIRES_PROPER_ALIGNMENT is a fpc build in define}
85  TZRowBuffer = {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif} record
86  Index: Integer;
87  UpdateType: TZRowUpdateType;
88  BookmarkFlag: Byte;
89  {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
90  dummyalign:pointer;
91  {$endif}
92  Columns: TZByteArray;
93  end;
94  PZRowBuffer = ^TZRowBuffer;
95 
96  {** Implements a column buffer accessor. }
97  TZRowAccessor = class(TZCodePagedObject)
98  private
99  FRowSize: Integer;
100  FColumnsSize: Integer;
101  FColumnCount: Integer;
102  FColumnNames: array of string;
103  FColumnCases: array of Boolean;
104  FColumnTypes: array of TZSQLType;
105  FColumnLengths: array of Integer;
106  FColumnOffsets: array of Integer;
107  FColumnDefaultExpressions: array of string;
108  FBuffer: PZRowBuffer;
109  FHasBlobs: Boolean;
110  FTemp: String;
111 
112  function GetColumnSize(ColumnInfo: TZColumnInfo): Integer;
113  function GetBlobObject(Buffer: PZRowBuffer; ColumnIndex: Integer): IZBlob;
114  procedure SetBlobObject(Buffer: PZRowBuffer; ColumnIndex: Integer;
115  Value: IZBlob);
116  function InternalGetBytes(Buffer: PZRowBuffer; ColumnIndex: Integer): TByteDynArray;
117  procedure InternalSetBytes(Buffer: PZRowBuffer; ColumnIndex: Integer;
118  Value: TByteDynArray; NewPointer: Boolean = False);
119  procedure InternalSetString(Buffer: PZRowBuffer; ColumnIndex: Integer;
120  Value: String; NewPointer: Boolean = False);
121  procedure InternalSetUnicodeString(Buffer: PZRowBuffer; ColumnIndex: Integer;
122  Value: ZWideString; NewPointer: Boolean = False);
123  protected
124  procedure CheckColumnIndex(ColumnIndex: Integer);
125  procedure CheckColumnConvertion(ColumnIndex: Integer; ResultType: TZSQLType);
126 
127  public
128  constructor Create(ColumnsInfo: TObjectList; ConSettings: PZConSettings);
129  destructor Destroy; override;
130 
131  function AllocBuffer(var Buffer: PZRowBuffer): PZRowBuffer;
132  procedure InitBuffer(Buffer: PZRowBuffer);
133  procedure CopyBuffer(SrcBuffer: PZRowBuffer; DestBuffer: PZRowBuffer);
134  procedure MoveBuffer(SrcBuffer: PZRowBuffer; DestBuffer: PZRowBuffer);
135  procedure CloneBuffer(SrcBuffer: PZRowBuffer; DestBuffer: PZRowBuffer);
136  procedure ClearBuffer(Buffer: PZRowBuffer);
137  procedure DisposeBuffer(Buffer: PZRowBuffer);
138 
139  function CompareBuffers(Buffer1, Buffer2: PZRowBuffer;
140  ColumnIndices: TIntegerDynArray; ColumnDirs: TBooleanDynArray): Integer;
141 
142  function Alloc: PZRowBuffer;
143  procedure Init;
144  procedure CopyTo(DestBuffer: PZRowBuffer);
145  procedure CopyFrom(SrcBuffer: PZRowBuffer);
146  procedure MoveTo(DestBuffer: PZRowBuffer);
147  procedure MoveFrom(SrcBuffer: PZRowBuffer);
148  procedure CloneTo(DestBuffer: PZRowBuffer);
149  procedure CloneFrom(SrcBuffer: PZRowBuffer);
150  procedure Clear;
151  procedure Dispose;
152 
153  function GetColumnData(ColumnIndex: Integer; var IsNull: Boolean): Pointer;
154  function GetColumnDataSize(ColumnIndex: Integer): Integer;
155 
156  function GetColumnName(ColumnIndex: Integer): string;
157  function GetColumnCase(ColumnIndex: Integer): Boolean;
158  function GetColumnType(ColumnIndex: Integer): TZSQLType;
159  function GetColumnLength(ColumnIndex: Integer): Integer;
160  function GetColumnOffSet(ColumnIndex: Integer): Integer;
161  function GetColumnDefaultExpression(ColumnIndex: Integer): string;
162  procedure SetColumnDefaultExpression(ColumnIndex: Integer; Value: string);
163 
164  //======================================================================
165  // Methods for accessing results by column index
166  //======================================================================
167 
168  function IsNull(ColumnIndex: Integer): Boolean;
169  function GetPChar(ColumnIndex: Integer; var IsNull: Boolean): PChar;
170  function GetString(ColumnIndex: Integer; var IsNull: Boolean): String;
171  function GetUnicodeString(ColumnIndex: Integer; var IsNull: Boolean): WideString;
172  function GetBoolean(ColumnIndex: Integer; var IsNull: Boolean): Boolean;
173  function GetByte(ColumnIndex: Integer; var IsNull: Boolean): ShortInt;
174  function GetShort(ColumnIndex: Integer; var IsNull: Boolean): SmallInt;
175  function GetInt(ColumnIndex: Integer; var IsNull: Boolean): Integer;
176  function GetLong(ColumnIndex: Integer; var IsNull: Boolean): Int64;
177  function GetFloat(ColumnIndex: Integer; var IsNull: Boolean): Single;
178  function GetDouble(ColumnIndex: Integer; var IsNull: Boolean): Double;
179  function GetBigDecimal(ColumnIndex: Integer; var IsNull: Boolean): Extended;
180  function GetBytes(ColumnIndex: Integer; var IsNull: Boolean): TByteDynArray;
181  function GetDate(ColumnIndex: Integer; var IsNull: Boolean): TDateTime;
182  function GetTime(ColumnIndex: Integer; var IsNull: Boolean): TDateTime;
183  function GetTimestamp(ColumnIndex: Integer; var IsNull: Boolean): TDateTime;
184  function GetAsciiStream(ColumnIndex: Integer; var IsNull: Boolean): TStream;
185  function GetUnicodeStream(ColumnIndex: Integer; var IsNull: Boolean): TStream;
186  function GetBinaryStream(ColumnIndex: Integer; var IsNull: Boolean): TStream;
187  function GetBlob(ColumnIndex: Integer; var IsNull: Boolean): IZBlob;
188  function GetDataSet(ColumnIndex: Integer; var IsNull: Boolean): IZDataSet;
189  function GetValue(ColumnIndex: Integer): TZVariant;
190 
191  //---------------------------------------------------------------------
192  // Updates
193  //---------------------------------------------------------------------
194 
195  procedure SetNotNull(ColumnIndex: Integer);
196  procedure SetNull(ColumnIndex: Integer);
197  procedure SetBoolean(ColumnIndex: Integer; Value: Boolean);
198  procedure SetByte(ColumnIndex: Integer; Value: ShortInt);
199  procedure SetShort(ColumnIndex: Integer; Value: SmallInt);
200  procedure SetInt(ColumnIndex: Integer; Value: Integer);
201  procedure SetLong(ColumnIndex: Integer; Value: Int64);
202  procedure SetFloat(ColumnIndex: Integer; Value: Single);
203  procedure SetDouble(ColumnIndex: Integer; Value: Double);
204  procedure SetBigDecimal(ColumnIndex: Integer; Value: Extended);
205  procedure SetPChar(ColumnIndex: Integer; Value: PChar);
206  procedure SetString(ColumnIndex: Integer; Value: String);
207  procedure SetUnicodeString(ColumnIndex: Integer; Value: WideString);
208  procedure SetBytes(ColumnIndex: Integer; Value: TByteDynArray);
209  procedure SetDate(ColumnIndex: Integer; Value: TDateTime);
210  procedure SetTime(ColumnIndex: Integer; Value: TDateTime);
211  procedure SetTimestamp(ColumnIndex: Integer; Value: TDateTime);
212  procedure SetAsciiStream(ColumnIndex: Integer; Value: TStream);
213  procedure SetUnicodeStream(ColumnIndex: Integer; Value: TStream);
214  procedure SetBinaryStream(ColumnIndex: Integer; Value: TStream);
215  procedure SetBlob(ColumnIndex: Integer; Value: IZBlob);
216  procedure SetDataSet(ColumnIndex: Integer; Value: IZDataSet);
217  procedure SetValue(ColumnIndex: Integer; Value: TZVariant);
218 
219  property ColumnsSize: Integer read FColumnsSize;
220  property RowSize: Integer read FRowSize;
221  property RowBuffer: PZRowBuffer read FBuffer write FBuffer;
222  end;
223 
224 const
225  RowHeaderSize = SizeOf(TZRowBuffer) - SizeOf(TZByteArray);
226 
227 implementation
228 
229 uses Math, ZMessages, ZSysUtils, ZDbcUtils
230  {$IFDEF WITH_UNITANSISTRINGS}, AnsiStrings{$ENDIF};
231 
232 { TZRowAccessor }
233 
234 {**
235  Creates this object and assignes the main properties.
236  @param ColumnsInfo a collection with column information.
237 }
238 constructor TZRowAccessor.Create(ColumnsInfo: TObjectList; ConSettings: PZConSettings);
239 var
240  I: Integer;
241  Current: TZColumnInfo;
242 begin
243  Self.ConSettings := ConSettings;
244  FBuffer := nil;
245  FColumnCount := ColumnsInfo.Count;
246  FColumnsSize := 0;
247  {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
248  FColumnsSize:=align(FColumnsSize+1,sizeof(pointer))-1;
249  {$endif}
250  SetLength(FColumnNames, FColumnCount);
251  SetLength(FColumnCases, FColumnCount);
252  SetLength(FColumnTypes, FColumnCount);
253  SetLength(FColumnLengths, FColumnCount);
254  SetLength(FColumnOffsets, FColumnCount);
255  SetLength(FColumnDefaultExpressions, FColumnCount);
256  FHasBlobs := False;
257 
258  for I := 0 to FColumnCount - 1 do
259  begin
260  Current := TZColumnInfo(ColumnsInfo[I]);
261  FColumnNames[I] := Current.ColumnName;
262  FColumnCases[I] := Current.CaseSensitive;
263  FColumnTypes[I] := Current.ColumnType;
264  FColumnLengths[I] := GetColumnSize(Current);
265  FColumnOffsets[I] := FColumnsSize;
266  FColumnDefaultExpressions[I] := Current.DefaultExpression;
267  Inc(FColumnsSize, FColumnLengths[I] + 1);
268  {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
269  FColumnsSize:=align(FColumnsSize+1,sizeof(pointer))-1;
270  {$endif}
271  if Current.ColumnType in [stBytes, stString, stUnicodeString] then
272  FColumnLengths[I] := Current.Precision;
273  if Current.ColumnType = stGUID then
274  FColumnLengths[I] := 16;
275  if FColumnsSize > SizeOf(TZByteArray)-1 then
276  raise EZSQLException.Create(SRowBufferWidthExceeded);
277  FHasBlobs := FHasBlobs
278  or (FColumnTypes[I] in [stAsciiStream, stUnicodeStream, stBinaryStream]);
279  end;
280  FRowSize := FColumnsSize + RowHeaderSize;
281 end;
282 
283 {**
284  Destroys this object and cleanups the memory.
285 }
286 destructor TZRowAccessor.Destroy;
287 begin
288  inherited Destroy;
289 end;
290 
291 {**
292  Checks is the column index correct and row buffer is available.
293  @param ColumnIndex an index of column.
294 }
295 procedure TZRowAccessor.CheckColumnIndex(ColumnIndex: Integer);
296 begin
297  if not Assigned(FBuffer) then
298  raise EZSQLException.Create(SRowBufferIsNotAssigned);
299 
300  if (ColumnIndex <= 0) or (ColumnIndex > FColumnCount) then
301  begin
302  raise EZSQLException.Create(
303  Format(SColumnIsNotAccessable, [ColumnIndex]));
304  end;
305 end;
306 
307 {**
308  Checks is the column convertion from one type to another type allowed.
309  @param ColumnIndex an index of column.
310  @param ResultType a requested data type.
311  @return <code>true</code> if convertion is allowed or throw exception
312  otherwise.
313 }
314 procedure TZRowAccessor.CheckColumnConvertion(ColumnIndex: Integer;
315  ResultType: TZSQLType);
316 begin
317  if not Assigned(FBuffer) then
318  raise EZSQLException.Create(SRowBufferIsNotAssigned);
319 
320  if (ColumnIndex <= 0) or (ColumnIndex > FColumnCount) then
321  begin
322  raise EZSQLException.Create(
323  Format(SColumnIsNotAccessable, [ColumnIndex]));
324  end;
325 
326  if not CheckConvertion(FColumnTypes[ColumnIndex - 1], ResultType) then
327  begin
328  raise EZSQLException.Create(
329  Format(SConvertionIsNotPossible, [ColumnIndex,
330  DefineColumnTypeName(FColumnTypes[ColumnIndex - 1]),
331  DefineColumnTypeName(ResultType)]));
332  end;
333 end;
334 
335 {**
336  Gets a size of column with the specified type.
337  @param ColumnInfo a column information struct.
338  @return a size for the column with the specified type.
339 }
340 function TZRowAccessor.GetColumnSize(ColumnInfo: TZColumnInfo): Integer;
341 begin
342  case ColumnInfo.ColumnType of
343  stBoolean:
344  Result := SizeOf(WordBool);
345  stByte:
346  Result := SizeOf(Byte);
347  stShort:
348  Result := SizeOf(SmallInt);
349  stInteger:
350  Result := SizeOf(Integer);
351  stLong:
352  Result := SizeOf(Int64);
353  stFloat:
354  Result := SizeOf(Single);
355  stDouble:
356  Result := SizeOf(Double);
357  stBigDecimal:
358  Result := SizeOf(Extended);
359  stString:
360  Result := SizeOf(Pointer);
361  stUnicodeString:
362  Result := SizeOf(Pointer);
363  stBytes, stGUID:
364  Result := SizeOf(Pointer) + SizeOf(SmallInt);
365  stDate, stTime, stTimestamp:
366  Result := SizeOf(TDateTime);
367  stAsciiStream, stUnicodeStream, stBinaryStream, stDataSet:
368  Result := SizeOf(Pointer);
369  else
370  Result := 0;
371  end;
372 end;
373 
374 {**
375  Gets a stream from the specified columns.
376  @param Buffer a row buffer.
377  @param ColumnIndex an index of the column.
378 }
379 function TZRowAccessor.GetBlobObject(Buffer: PZRowBuffer;
380  ColumnIndex: Integer): IZBlob;
381 var
382  BlobPtr: PPointer;
383  NullPtr: {$IFDEF WIN64}PBoolean{$ELSE}PByte{$ENDIF};
384 begin
385  BlobPtr := PPointer(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1]);
386  NullPtr := {$IFDEF WIN64}PBoolean{$ELSE}PByte{$ENDIF}(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1]]);
387 
388  {$IFNDEF FPC}
389  if NullPtr^ = {$IFDEF WIN64}false{$ELSE}0{$ENDIF} then //M.A. if NullPtr^ = 0 then
390  {$ELSE}
391  if NullPtr^ = 0 then
392  {$ENDIF}
393  Result := IZBlob(BlobPtr^)
394  else
395  Result := nil;
396 end;
397 
398 {**
399  Sets a blob into the specified columns.
400  @param Buffer a row buffer.
401  @param ColumnIndex an index of the column.
402  @param Value a stream object to be set.
403 }
404 procedure TZRowAccessor.SetBlobObject(Buffer: PZRowBuffer; ColumnIndex: Integer;
405  Value: IZBlob);
406 var
407  BlobPtr: PPointer;
408  NullPtr: {$IFDEF WIN64}PBoolean{$ELSE}PByte{$ENDIF};
409 begin
410  BlobPtr := PPointer(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1]);
411  NullPtr := {$IFDEF WIN64}PBoolean{$ELSE}PByte{$ENDIF}(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1]]);
412 
413  {$IFNDEF FPC}
414  if NullPtr^ = {$IFDEF WIN64}false{$ELSE}0{$ENDIF} then //M.A. if NullPtr^ = 0 then
415  {$ELSE}
416  if NullPtr^ = 0 then
417  {$ENDIF}
418  IZBlob(BlobPtr^) := nil
419  else
420  BlobPtr^ := nil;
421 
422  IZBlob(BlobPtr^) := Value;
423 
424  if Value <> nil then
425  {$IFNDEF FPC}
426  NullPtr^ := {$IFDEF WIN64}false{$ELSE}0{$ENDIF} //M.A. NullPtr^ := 0
427  else
428  NullPtr^ := {$IFDEF WIN64}true{$ELSE}1{$ENDIF}; //M.A. NullPtr^ := 1;
429  {$ELSE}
430  NullPtr^ := 0
431  else
432  NullPtr^ := 1;
433  {$ENDIF}
434 end;
435 
436 function TZRowAccessor.InternalGetBytes(Buffer: PZRowBuffer;
437  ColumnIndex: Integer): TByteDynArray;
438 var
439  P: PPointer;
440  L: SmallInt;
441 begin
442  Result := nil;
443  if ( Buffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 )then
444  begin
445  L := PSmallInt(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1 + SizeOf(Pointer)])^;
446  SetLength(Result, L);
447  if L > 0 then
448  begin
449  P := PPointer(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1]);
450  Move(P^^, Pointer(Result)^, L);
451  end;
452  end;
453 end;
454 
455 procedure TZRowAccessor.InternalSetBytes(Buffer: PZRowBuffer; ColumnIndex: Integer;
456  Value: TByteDynArray; NewPointer: Boolean = False);
457 var
458  P: PPointer;
459  L: SmallInt;
460 begin
461  if Assigned(Buffer) then
462  begin
463  if NewPointer then
464  PNativeUInt(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := 0;
465  P := PPointer(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1]);
466  L := Min(Length(Value), FColumnLengths[ColumnIndex - 1]);
467  PSmallInt(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1 + SizeOf(Pointer)])^ := L;
468  if L > 0 then
469  begin
470  ReallocMem(P^, L);
471  System.Move(Pointer(Value)^, P^^, L);
472  end
473  else
474  if PNativeUInt(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ > 0 then
475  begin
476  System.Dispose(P^);
477  PNativeUInt(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := 0;
478  end;
479  end;
480 end;
481 
482 procedure TZRowAccessor.InternalSetString(Buffer: PZRowBuffer;
483  ColumnIndex: Integer; Value: String; NewPointer: Boolean = False);
484 var
485  C: PPChar;
486  L: SmallInt;
487 begin
488  if Assigned(Buffer) then
489  begin
490  if NewPointer then
491  PNativeUInt(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := 0;
492  C := PPChar(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1]);
493  L := Min(FColumnLengths[ColumnIndex - 1], Length(Value));
494  ReallocMem(C^, L * SizeOf(Char) + SizeOf(Char));
495  System.Move(PChar(Value)^, C^^, L * SizeOf(Char));
496  (C^+L)^ := #0; //set #0 terminator if a truncation is required
497  end;
498 end;
499 
500 procedure TZRowAccessor.InternalSetUnicodeString(Buffer: PZRowBuffer;
501  ColumnIndex: Integer; Value: ZWideString; NewPointer: Boolean = False);
502 var
503  W: ZPPWideChar;
504  L: SmallInt;
505 begin
506  if Assigned(Buffer) then
507  begin
508  if NewPointer then
509  PNativeUInt(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := 0;
510  W := ZPPWideChar(@Buffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1]);
511  L := Min(Length(Value), FColumnLengths[ColumnIndex - 1]);
512  Value := System.Copy(Value, 1, L);
513  L := L * 2 + 2;
514  ReallocMem(W^, L);
515  System.Move(PWideChar(Value)^, W^^, L);
516  end;
517 end;
518 
519 {**
520  Allocates a new row buffer and sets it into the variable.
521  @param Buffer a pointer to row buffer.
522  @return a pointer to the allocated buffer.
523 }
524 function TZRowAccessor.AllocBuffer(var Buffer: PZRowBuffer): PZRowBuffer;
525 begin
526  GetMem(Buffer, FRowSize);
527  InitBuffer(Buffer);
528  Result := Buffer;
529 end;
530 
531 {**
532  Disposes the specified row buffer.
533  @param Buffer a pointer to row buffer.
534 }
535 procedure TZRowAccessor.DisposeBuffer(Buffer: PZRowBuffer);
536 begin
537  if Assigned(Buffer) then
538  begin
539  ClearBuffer(Buffer);
540  FreeMem(Buffer);
541  end;
542 end;
543 
544 {**
545  Initializes the row buffer.
546  @param Buffer a pointer to row buffer.
547 }
548 procedure TZRowAccessor.InitBuffer(Buffer: PZRowBuffer);
549 var
550  I : Integer;
551 begin
552  if Assigned(Buffer) then
553  with Buffer^ do
554  begin
555  Index := 0;
556  BookmarkFlag := 0;//bfCurrent;
557  UpdateType := utUnmodified;
558  FillChar(Columns, FColumnsSize, 0);
559  for I := 0 to FColumnCount - 1 do Columns[FColumnOffsets[I]] := 1;
560  end;
561 end;
562 
563 {**
564  Copies the row buffer from source to destination row.
565  @param SrcBuffer a pointer to source row buffer.
566  @param DestBuffer a pointer to destination row buffer.
567 }
568 procedure TZRowAccessor.CopyBuffer(SrcBuffer: PZRowBuffer; DestBuffer: PZRowBuffer);
569 var
570  I: Integer;
571 begin
572  ClearBuffer(DestBuffer);
573  with DestBuffer^ do
574  begin
575  Index := SrcBuffer^.Index;
576  UpdateType := SrcBuffer^.UpdateType;
577  BookmarkFlag := SrcBuffer^.BookmarkFlag;
578  System.Move(SrcBuffer^.Columns, Columns, FColumnsSize);
579  for I := 0 to FColumnCount - 1 do
580  case FColumnTypes[I] of
581  stAsciiStream, stUnicodeStream, stBinaryStream:
582  if (Columns[FColumnOffsets[I]] = 0) then
583  begin
584  Columns[FColumnOffsets[I]] := 1;
585  SetBlobObject(DestBuffer, I + 1, GetBlobObject(SrcBuffer, I + 1));
586  end;
587  stString: InternalSetString(DestBuffer, I +1,
588  PPChar(@SrcBuffer.Columns[FColumnOffsets[I] + 1])^, True);
589  stUnicodeString: InternalSetUnicodeString(DestBuffer, I +1,
590  ZPPWideChar(@SrcBuffer.Columns[FColumnOffsets[I] + 1])^, True);
591  stBytes,stGUID: InternalSetBytes(DestBuffer, I +1, InternalGetBytes(SrcBuffer, I +1), True);
592  end;
593  end;
594 end;
595 
596 {**
597  Moves the row buffer from source to destination row.
598  Source buffer is cleaned up after the operation.
599  @param SrcBuffer a pointer to source row buffer.
600  @param DestBuffer a pointer to destination row buffer.
601 }
602 procedure TZRowAccessor.MoveBuffer(SrcBuffer: PZRowBuffer; DestBuffer: PZRowBuffer);
603 begin
604  CopyBuffer(SrcBuffer, DestBuffer);
605  ClearBuffer(SrcBuffer);
606 end;
607 
608 {**
609  Clones the row buffer from source to destination row.
610  @param SrcBuffer a pointer to source row buffer.
611  @param DestBuffer a pointer to destination row buffer.
612 }
613 procedure TZRowAccessor.CloneBuffer(SrcBuffer: PZRowBuffer; DestBuffer: PZRowBuffer);
614 var
615  I: Integer;
616  Blob: IZBlob;
617 begin
618  ClearBuffer(DestBuffer);
619  with DestBuffer^ do
620  begin
621  Index := SrcBuffer^.Index;
622  UpdateType := SrcBuffer^.UpdateType;
623  BookmarkFlag := SrcBuffer^.BookmarkFlag;
624  System.Move(SrcBuffer^.Columns, Columns, FColumnsSize);
625  for I := 0 to FColumnCount - 1 do
626  case FColumnTypes[I] of
627  stAsciiStream, stUnicodeStream, stBinaryStream:
628  if (Columns[FColumnOffsets[I]] = 0) then
629  begin
630  Columns[FColumnOffsets[I]] := 1;
631  Blob := GetBlobObject(SrcBuffer, I + 1);
632  if Blob <> nil then
633  Blob := Blob.Clone;
634  SetBlobObject(DestBuffer, I + 1, Blob);
635  end;
636  stString: InternalSetString(DestBuffer, I +1,
637  PPChar(@SrcBuffer.Columns[FColumnOffsets[I] + 1])^, True);
638  stUnicodeString: InternalSetUnicodeString(DestBuffer, I +1,
639  ZPPWideChar(@SrcBuffer.Columns[FColumnOffsets[I] + 1])^, True);
640  stBytes,stGUID: InternalSetBytes(DestBuffer, I +1, InternalGetBytes(SrcBuffer, I +1), True);
641  end;
642  end;
643 end;
644 
645 {**
646  Compares fields from two row buffers.
647  @param Buffer1 the first row buffer to compare.
648  @param Buffer2 the second row buffer to compare.
649  @param ColumnIndices column indices to compare.
650  @param ColumnDirs compare direction for each columns.
651 }
652 function TZRowAccessor.CompareBuffers(Buffer1, Buffer2: PZRowBuffer;
653  ColumnIndices: TIntegerDynArray; ColumnDirs: TBooleanDynArray): Integer;
654 var
655  I: Integer;
656  ColumnIndex: Integer;
657  Length1, Length2: SmallInt;
658  ValuePtr1, ValuePtr2: Pointer;
659  Blob1, Blob2: IZBlob;
660  BlobEmpty1, BlobEmpty2: Boolean;
661  Bts1, Bts2: TByteDynArray;
662 begin
663  Result := 0;
664  for I := Low(ColumnIndices) to High(ColumnIndices) do
665  begin
666  ColumnIndex := ColumnIndices[I] - 1;
667  { Checks for both Null columns. }
668  if (Buffer1.Columns[FColumnOffsets[ColumnIndex]] = 1) and
669  (Buffer2.Columns[FColumnOffsets[ColumnIndex]] = 1) then
670  Continue;
671  { Checks for not-Null and Null columns. }
672  if Buffer1.Columns[FColumnOffsets[ColumnIndex]] <>
673  Buffer2.Columns[FColumnOffsets[ColumnIndex]] then
674  begin
675  if not (FColumnTypes[ColumnIndex]
676  in [stAsciiStream, stUnicodeStream, stBinaryStream]) then
677  begin
678  Result := Buffer2.Columns[FColumnOffsets[ColumnIndex]] -
679  Buffer1.Columns[FColumnOffsets[ColumnIndex]];
680  if not ColumnDirs[I] then
681  Result := -Result;
682  Break;
683  end;
684  end;
685  { Compares column values. }
686  ValuePtr1 := @Buffer1.Columns[FColumnOffsets[ColumnIndex] + 1];
687  ValuePtr2 := @Buffer2.Columns[FColumnOffsets[ColumnIndex] + 1];
688  case FColumnTypes[ColumnIndex] of
689  stByte:
690  Result := Ord((PByte(ValuePtr1)^ > PByte(ValuePtr2)^))-Ord((PByte(ValuePtr1)^ < PByte(ValuePtr2)^));
691  stShort:
692  Result := Ord((PShortInt(ValuePtr1)^ > PShortInt(ValuePtr2)^))-Ord((PShortInt(ValuePtr1)^ < PShortInt(ValuePtr2)^));
693  stInteger:
694  Result := Ord((PLongInt(ValuePtr1)^ > PLongInt(ValuePtr2)^))-Ord((PLongInt(ValuePtr1)^ < PLongInt(ValuePtr2)^));
695  stLong:
696  Result := Ord((PInt64(ValuePtr1)^ > PInt64(ValuePtr2)^))-Ord((PInt64(ValuePtr1)^ < PInt64(ValuePtr2)^));
697  stFloat:
698  Result := Ord((PSingle(ValuePtr1)^ > PSingle(ValuePtr2)^))-Ord((PSingle(ValuePtr1)^ < PSingle(ValuePtr2)^));
699  stDouble:
700  Result := Ord((PDouble(ValuePtr1)^ > PDouble(ValuePtr2)^))-Ord((PDouble(ValuePtr1)^ < PDouble(ValuePtr2)^));
701  stBigDecimal:
702  Result := Ord((PExtended(ValuePtr1)^ > PExtended(ValuePtr2)^))-Ord((PExtended(ValuePtr1)^ < PExtended(ValuePtr2)^));
703  stBoolean:
704  Result := Ord((PWordBool(ValuePtr1)^ > PWordBool(ValuePtr2)^))-Ord((PWordBool(ValuePtr1)^ < PWordBool(ValuePtr2)^));
705  stDate, stTime, stTimestamp:
706  Result := Ord((PDateTime(ValuePtr1)^ > PDateTime(ValuePtr2)^))-Ord((PDateTime(ValuePtr1)^ < PDateTime(ValuePtr2)^));
707  {$IFDEF UNICODE}
708  stUnicodeString,stString:
709  Result := WideCompareStr(PWideChar(ValuePtr1^), PWideChar(ValuePtr2^));
710  {$ELSE}
711  stString:
712  {$IFDEF MSWINDOWS} //Windows can handle nil pointers Linux not FPC-Bug?
713  Result := AnsiStrComp(PAnsiChar(ValuePtr1^), PAnsiChar(ValuePtr2^));
714  {$ELSE}
715  if Assigned(PPAnsichar(ValuePtr1)^) and Assigned(PPAnsiChar(ValuePtr2)^) then
716  Result := AnsiStrComp(PAnsiChar(ValuePtr1^), PAnsiChar(ValuePtr2^))
717  else
718  if not Assigned(PPAnsichar(ValuePtr1)^) and not Assigned(PPAnsiChar(ValuePtr2)^) then
719  Result := 0
720  else
721  Result := -1;
722  {$ENDIF}
723  stUnicodeString:
724  Result := WideCompareStr(PWideChar(ValuePtr1^), PWideChar(ValuePtr2^));
725  {$ENDIF}
726  stBytes,stGUID:
727  begin
728  Length1 := PSmallInt(@Buffer1.Columns[FColumnOffsets[ColumnIndex] + 1 + SizeOf(Pointer)])^;
729  Length2 := PSmallInt(@Buffer2.Columns[FColumnOffsets[ColumnIndex] + 1 + SizeOf(Pointer)])^;
730  Result := Length1 - Length2;
731  if Result = 0 then
732  begin
733  Bts1 := InternalGetBytes(Buffer1, ColumnIndex+1);
734  Bts2 := InternalGetBytes(Buffer2, ColumnIndex+1);
735  if (Assigned(Bts1) and Assigned(Bts2)) then
736  if MemLCompAnsi(PAnsiChar(Bts1), PAnsiChar(Bts2), Length1) then
737  Result := 0
738  else
739  Result := 1
740  else if not Assigned(Bts1) and not Assigned(Bts2) then
741  Result := 0
742  else if Assigned(Bts1) then
743  Result := 1
744  else
745  Result := -1;
746  end;
747  end;
748  stAsciiStream, stBinaryStream, stUnicodeStream:
749  begin
750  Blob1 := GetBlobObject(Buffer1, ColumnIndex + 1);
751  BlobEmpty1 := (Blob1 = nil) or (Blob1.IsEmpty);
752  Blob2 := GetBlobObject(Buffer2, ColumnIndex + 1);
753  BlobEmpty2 := (Blob2 = nil) or (Blob2.IsEmpty);
754  if (BlobEmpty1 = True) and (BlobEmpty2 = True) then
755  Continue
756  else if (BlobEmpty1 <> BlobEmpty2) then
757  begin
758  if BlobEmpty1 then
759  Result := -1
760  else
761  Result := 1;
762  end
763  else if FColumnTypes[ColumnIndex] = stAsciiStream then
764  {$IFDEF WITH_UNITANSISTRINGS}
765  Result := AnsiStrings.AnsiCompareStr(Blob1.GetString, Blob2.GetString)
766  {$ELSE}
767  Result := AnsiCompareStr(Blob1.GetString, Blob2.GetString)
768  {$ENDIF}
769  else if FColumnTypes[ColumnIndex] = stBinaryStream then
770  Result := CompareStr(Blob1.GetString, Blob2.GetString)
771  else if FColumnTypes[ColumnIndex] = stUnicodeStream then
772  Result := WideCompareStr(Blob1.GetUnicodeString, Blob2.GetUnicodeString);
773  end;
774  end;
775  if Result <> 0 then
776  begin
777  if not ColumnDirs[I] then
778  Result := -Result;
779  Break;
780  end;
781  end;
782 end;
783 
784 {**
785  Cleans the specified row buffer.
786  @param Buffer a pointer to row buffer.
787 }
788 procedure TZRowAccessor.ClearBuffer(Buffer: PZRowBuffer);
789 var
790  I: Integer;
791  P: PPointer;
792 begin
793  with Buffer^ do
794  begin
795  Index := -1;
796  UpdateType := utUnmodified;
797  BookmarkFlag := 0;
798  for I := 0 to FColumnCount - 1 do
799  case FColumnTypes[I] of
800  stAsciiStream, stUnicodeStream, stBinaryStream:
801  if (Columns[FColumnOffsets[I]] = 0) then
802  SetBlobObject(Buffer, I + 1, nil);
803  stBytes,stGUID,stString, stUnicodeString:
804  if PNativeUInt(@Columns[FColumnOffsets[I] +1])^ > 0 then
805  begin
806  P := PPointer(@Columns[FColumnOffsets[I] +1]);
807  System.Dispose(P^);
808  end;
809  end;
810  FillChar(Columns, FColumnsSize, 0);
811  for I := 0 to FColumnCount - 1 do Columns[FColumnOffsets[I]] := 1;
812  end;
813 end;
814 
815 {**
816  Allocates a new row buffer.
817  @return a pointer to the allocated buffer.
818 }
819 function TZRowAccessor.Alloc: PZRowBuffer;
820 begin
821  Result := AllocBuffer(FBuffer);
822 end;
823 
824 {**
825  Disposes an associated row buffer.
826 }
827 procedure TZRowAccessor.Dispose;
828 begin
829  DisposeBuffer(FBuffer);
830  FBuffer := nil;
831 end;
832 
833 {**
834  Initializes the associated row buffer.
835 }
836 procedure TZRowAccessor.Init;
837 begin
838  InitBuffer(FBuffer);
839 end;
840 
841 {**
842  Copies the associated row buffer into a specified one.
843  @param DestBuffer a destination row buffer.
844 }
845 procedure TZRowAccessor.CopyTo(DestBuffer: PZRowBuffer);
846 begin
847  CopyBuffer(FBuffer, DestBuffer);
848 end;
849 
850 {**
851  Copies the associated row buffer from a specified one.
852  @param SrcBuffer a source row buffer.
853 }
854 procedure TZRowAccessor.CopyFrom(SrcBuffer: PZRowBuffer);
855 begin
856  CopyBuffer(SrcBuffer, FBuffer);
857 end;
858 
859 {**
860  Moves the associated row buffer into a specified one.
861  @param DestBuffer a destination row buffer.
862 }
863 procedure TZRowAccessor.MoveTo(DestBuffer: PZRowBuffer);
864 begin
865  MoveBuffer(FBuffer, DestBuffer);
866 end;
867 
868 {**
869  Moves the associated row buffer from a specified one.
870  @param SrcBuffer a source row buffer.
871 }
872 procedure TZRowAccessor.MoveFrom(SrcBuffer: PZRowBuffer);
873 begin
874  MoveBuffer(SrcBuffer, FBuffer);
875 end;
876 
877 {**
878  Clones the associated row buffer into a specified one.
879  @param DestBuffer a destination row buffer.
880 }
881 procedure TZRowAccessor.CloneTo(DestBuffer: PZRowBuffer);
882 begin
883  CloneBuffer(FBuffer, DestBuffer);
884 end;
885 
886 {**
887  Clones the associated row buffer from a specified one.
888  @param SrcBuffer a source row buffer.
889 }
890 procedure TZRowAccessor.CloneFrom(SrcBuffer: PZRowBuffer);
891 begin
892  CloneBuffer(SrcBuffer, FBuffer);
893 end;
894 
895 {**
896  Cleans the associated row buffer.
897 }
898 procedure TZRowAccessor.Clear;
899 begin
900  ClearBuffer(FBuffer);
901 end;
902 
903 {**
904  Gets the case sensitive flag of a column data buffer.
905 
906  @param ColumnIndex the first column is 1, the second is 2, ...
907  @return the case sensitive flag of the column data buffer.
908 }
909 function TZRowAccessor.GetColumnCase(ColumnIndex: Integer): Boolean;
910 begin
911  CheckColumnIndex(ColumnIndex);
912  Result := FColumnCases[ColumnIndex-1];
913 end;
914 
915 {**
916  Gets a pointer to the column data buffer.
917 
918  @param ColumnIndex the first column is 1, the second is 2, ...
919  @return a pointer to the column data buffer.
920 }
921 function TZRowAccessor.GetColumnData(ColumnIndex: Integer;
922  var IsNull: Boolean): Pointer;
923 begin
924  CheckColumnConvertion(ColumnIndex, stString);
925  Result := @FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1];
926  IsNull := FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 1;
927 end;
928 
929 {**
930  Gets a size of the column data buffer.
931 
932  @param ColumnIndex the first column is 1, the second is 2, ...
933  @return a size of the column data buffer.
934 }
935 function TZRowAccessor.GetColumnDataSize(ColumnIndex: Integer): Integer;
936 begin
937  CheckColumnConvertion(ColumnIndex, stString);
938  Result := FColumnLengths[ColumnIndex - 1];
939 end;
940 
941 {**
942  Gets then length of a column data buffer.
943 
944  @param ColumnIndex the first column is 1, the second is 2, ...
945  @return the length of the column data buffer.
946 }
947 function TZRowAccessor.GetColumnLength(ColumnIndex: Integer): Integer;
948 begin
949  CheckColumnIndex(ColumnIndex);
950  Result := FColumnLengths[ColumnIndex-1];
951 end;
952 
953 {**
954  Gets then name of a column data buffer.
955 
956  @param ColumnIndex the first column is 1, the second is 2, ...
957  @return the name of the column data buffer.
958 }
959 function TZRowAccessor.GetColumnName(ColumnIndex: Integer): string;
960 begin
961  CheckColumnIndex(ColumnIndex);
962  Result := FColumnNames[ColumnIndex-1];
963 end;
964 
965 {**
966  Gets then offset of a column data buffer.
967 
968  @param ColumnIndex the first column is 1, the second is 2, ...
969  @return then offset of the column data buffer.
970 }
971 function TZRowAccessor.GetColumnOffSet(ColumnIndex: Integer): Integer;
972 begin
973  CheckColumnIndex(ColumnIndex);
974  Result := FColumnOffSets[ColumnIndex-1];
975 end;
976 
977 {**
978  Gets then SQLType of a column data buffer.
979 
980  @param ColumnIndex the first column is 1, the second is 2, ...
981  @return the SQLType of the column data buffer.
982 }
983 function TZRowAccessor.GetColumnType(ColumnIndex: Integer): TZSQLType;
984 begin
985  CheckColumnIndex(ColumnIndex);
986  Result := FColumnTypes[ColumnIndex-1];
987 end;
988 
989 function TZRowAccessor.GetColumnDefaultExpression(ColumnIndex: Integer): string;
990 begin
991  CheckColumnIndex(ColumnIndex);
992  Result := FColumnDefaultExpressions[ColumnIndex-1];
993 end;
994 
995 procedure TZRowAccessor.SetColumnDefaultExpression(ColumnIndex: Integer; Value: string);
996 begin
997  FColumnDefaultExpressions[ColumnIndex-1] := Value;
998 end;
999 
1000 //
1001 //======================================================================
1002 // Methods for accessing results by column index
1003 //======================================================================
1004 
1005 {**
1006  Indicates if the value of the designated column in the current row
1007  of this <code>ResultSet</code> object is Null.
1008 
1009  @param ColumnIndex the first column is 1, the second is 2, ...
1010  @return if the value is SQL <code>NULL</code>, the
1011  value returned is <code>true</code>. <code>false</code> otherwise.
1012 }
1013 function TZRowAccessor.IsNull(ColumnIndex: Integer): Boolean;
1014 var
1015  TempBlob: IZBlob;
1016 begin
1017  CheckColumnConvertion(ColumnIndex, stString);
1018  Result := FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 1;
1019  if not Result and (FColumnTypes[ColumnIndex - 1] in [stAsciiStream,
1020  stBinaryStream, stUnicodeStream]) then
1021  begin
1022  TempBlob := GetBlobObject(FBuffer, ColumnIndex);
1023  Result := (TempBlob = nil) or TempBlob.IsEmpty;
1024  end;
1025 end;
1026 
1027 {**
1028  Gets the value of the designated column in the current row
1029  of this <code>ResultSet</code> object as
1030  a <code>PChar</code> in the Delphi programming language.
1031 
1032  @param columnIndex the first column is 1, the second is 2, ...
1033  @return the column value; if the value is SQL <code>NULL</code>, the
1034  value returned is <code>null</code>
1035 }
1036 function TZRowAccessor.GetPChar(ColumnIndex: Integer; var IsNull: Boolean): PChar;
1037 begin
1038 {$IFNDEF DISABLE_CHECKING}
1039  CheckColumnConvertion(ColumnIndex, stString);
1040 {$ENDIF}
1041  Result := nil;
1042  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1043  begin
1044  case FColumnTypes[ColumnIndex - 1] of
1045  stString{$IFDEF UNICODE}, stUnicodeString{$ENDIF}:
1046  Result := PPChar(FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1047  else
1048  begin
1049  FTemp := GetString(ColumnIndex, IsNull);
1050  Result := PChar(FTemp);
1051  end;
1052  end;
1053  IsNull := False;
1054  end
1055  else
1056  IsNull := True;
1057 end;
1058 
1059 {**
1060  Gets the value of the designated column in the current row
1061  of this <code>ResultSet</code> object as
1062  a <code>String</code> in the Java programming language.
1063 
1064  @param columnIndex the first column is 1, the second is 2, ...
1065  @return the column value; if the value is SQL <code>NULL</code>, the
1066  value returned is <code>null</code>
1067 }
1068 function TZRowAccessor.GetString(ColumnIndex: Integer; var IsNull: Boolean): String;
1069 var
1070  TempBlob: IZBlob;
1071  GUID: TGUID;
1072 begin
1073 {$IFNDEF DISABLE_CHECKING}
1074  CheckColumnConvertion(ColumnIndex, stString);
1075 {$ENDIF}
1076  Result := '';
1077  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1078  begin
1079  case FColumnTypes[ColumnIndex - 1] of
1080  stBoolean:
1081  if GetBoolean(ColumnIndex, IsNull) then
1082  Result := 'True'
1083  else
1084  Result := 'False';
1085  stByte: Result := IntToStr(GetByte(ColumnIndex, IsNull));
1086  stShort: Result := IntToStr(GetShort(ColumnIndex, IsNull));
1087  stInteger: Result := IntToStr(GetInt(ColumnIndex, IsNull));
1088  stLong: Result := IntToStr(GetLong(ColumnIndex, IsNull));
1089  stFloat: Result := FloatToSQLStr(GetFloat(ColumnIndex, IsNull));
1090  stDouble: Result := FloatToSQLStr(GetDouble(ColumnIndex, IsNull));
1091  stBigDecimal: Result := FloatToSQLStr(GetBigDecimal(ColumnIndex, IsNull));
1092  stString: Result := PPChar(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1093  stUnicodeString, stUnicodeStream: Result := ZDbcString(GetUnicodeString(ColumnIndex, IsNull)); //wide down to expect codpage Ansi
1094  stBytes: Result := String(BytesToStr(GetBytes(ColumnIndex, IsNull)));
1095  stGUID:
1096  begin
1097  System.Move(Pointer(GetBytes(ColumnIndex, IsNull))^, GUID, 16);
1098  Result := GUIDToString(GUID);
1099  end;
1100  stDate: Result := FormatDateTime('yyyy-mm-dd', GetDate(ColumnIndex, IsNull));
1101  stTime: Result := FormatDateTime('hh:mm:ss', GetTime(ColumnIndex, IsNull));
1102  stTimestamp: Result := FormatDateTime('yyyy-mm-dd hh:mm:ss',
1103  GetTimestamp(ColumnIndex, IsNull));
1104  stAsciiStream, stBinaryStream:
1105  begin
1106  TempBlob := GetBlobObject(FBuffer, ColumnIndex);
1107  if (TempBlob <> nil) and not TempBlob.IsEmpty then
1108  Result := String(TempBlob.GetString);
1109  end;
1110  end;
1111  IsNull := False;
1112  end
1113  else
1114  IsNull := True;
1115 end;
1116 
1117 {**
1118  Gets the value of the designated column in the current row
1119  of this <code>ResultSet</code> object as
1120  a <code>WideString</code> in the ObjectPascal programming language.
1121 
1122  @param columnIndex the first column is 1, the second is 2, ...
1123  @return the column value; if the value is SQL <code>NULL</code>, the
1124  value returned is <code>null</code>
1125 }
1126 function TZRowAccessor.GetUnicodeString(ColumnIndex: Integer; var IsNull: Boolean):
1127  WideString;
1128 var
1129  TempBlob: IZBlob;
1130 begin
1131 {$IFNDEF DISABLE_CHECKING}
1132  CheckColumnConvertion(ColumnIndex, stUnicodeString);
1133 {$ENDIF}
1134  Result := '';
1135  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1136  begin
1137  case FColumnTypes[ColumnIndex - 1] of
1138  stUnicodeString{$IFDEF UNICODE}, stString{$ENDIF}:
1139  Result := ZPPWideChar(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1140  stUnicodeStream:
1141  begin
1142  TempBlob := GetBlobObject(FBuffer, ColumnIndex);
1143  if (TempBlob <> nil) and not TempBlob.IsEmpty then
1144  Result := TempBlob.GetUnicodeString;
1145  end;
1146  {$IFNDEF UNICODE}
1147  stString: Result := ZDbcUnicodeString(GetString(ColumnIndex, IsNull), ConSettings.CTRL_CP);
1148  {$ENDIF}
1149  else
1150  Result := WideString(GetString(ColumnIndex, IsNull));
1151  end;
1152  IsNull := False;
1153  end
1154  else
1155  IsNull := True;
1156 end;
1157 
1158 {**
1159  Gets the value of the designated column in the current row
1160  of this <code>ResultSet</code> object as
1161  a <code>boolean</code> in the Java programming language.
1162 
1163  @param columnIndex the first column is 1, the second is 2, ...
1164  @return the column value; if the value is SQL <code>NULL</code>, the
1165  value returned is <code>false</code>
1166 }
1167 function TZRowAccessor.GetBoolean(ColumnIndex: Integer; var IsNull: Boolean): Boolean;
1168 var
1169  TempStr: string;
1170 begin
1171 {$IFNDEF DISABLE_CHECKING}
1172  CheckColumnConvertion(ColumnIndex, stBoolean);
1173 {$ENDIF}
1174  Result := False;
1175  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1176  begin
1177  case FColumnTypes[ColumnIndex - 1] of
1178  stBoolean:
1179  Result := PWordBool(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1180  stByte: Result := GetByte(ColumnIndex, IsNull) <> 0;
1181  stShort: Result := GetShort(ColumnIndex, IsNull) <> 0;
1182  stInteger: Result := GetInt(ColumnIndex, IsNull) <> 0;
1183  stLong: Result := GetLong(ColumnIndex, IsNull) <> 0;
1184  stFloat: Result := GetFloat(ColumnIndex, IsNull) <> 0;
1185  stDouble: Result := GetDouble(ColumnIndex, IsNull) <> 0;
1186  stBigDecimal: Result := GetBigDecimal(ColumnIndex, IsNull) <> 0;
1187  stString, stUnicodeString:
1188  begin
1189  TempStr := UpperCase(GetString(ColumnIndex, IsNull));
1190  Result := (TempStr = 'T') or (TempStr = 'Y') or (TempStr = 'TRUE')
1191  or (TempStr = 'YES');
1192  end;
1193  end;
1194  IsNull := False;
1195  end
1196  else
1197  IsNull := True;
1198 end;
1199 
1200 {**
1201  Gets the value of the designated column in the current row
1202  of this <code>ResultSet</code> object as
1203  a <code>byte</code> in the Java programming language.
1204 
1205  @param columnIndex the first column is 1, the second is 2, ...
1206  @return the column value; if the value is SQL <code>NULL</code>, the
1207  value returned is <code>0</code>
1208 }
1209 function TZRowAccessor.GetByte(ColumnIndex: Integer; var IsNull: Boolean): ShortInt;
1210 begin
1211 {$IFNDEF DISABLE_CHECKING}
1212  CheckColumnConvertion(ColumnIndex, stByte);
1213 {$ENDIF}
1214  Result := 0;
1215  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1216  begin
1217  case FColumnTypes[ColumnIndex - 1] of
1218  stBoolean:
1219  if GetBoolean(ColumnIndex, IsNull) then
1220  Result := 1
1221  else
1222  Result := 0;
1223  stByte: Result := PShortInt(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1224  stShort: Result := GetShort(ColumnIndex, IsNull);
1225  stInteger: Result := GetInt(ColumnIndex, IsNull);
1226  stLong: Result := GetLong(ColumnIndex, IsNull);
1227  stFloat: Result := Trunc(GetFloat(ColumnIndex, IsNull));
1228  stDouble: Result := Trunc(GetDouble(ColumnIndex, IsNull));
1229  stBigDecimal: Result := Trunc(GetBigDecimal(ColumnIndex, IsNull));
1230  stString, stUnicodeString: Result := StrToIntDef(GetString(ColumnIndex, IsNull), 0);
1231  end;
1232  IsNull := False;
1233  end
1234  else
1235  IsNull := True;
1236 end;
1237 
1238 {**
1239  Gets the value of the designated column in the current row
1240  of this <code>ResultSet</code> object as
1241  a <code>short</code> in the Java programming language.
1242 
1243  @param columnIndex the first column is 1, the second is 2, ...
1244  @return the column value; if the value is SQL <code>NULL</code>, the
1245  value returned is <code>0</code>
1246 }
1247 function TZRowAccessor.GetShort(ColumnIndex: Integer; var IsNull: Boolean): SmallInt;
1248 begin
1249 {$IFNDEF DISABLE_CHECKING}
1250  CheckColumnConvertion(ColumnIndex, stShort);
1251 {$ENDIF}
1252  Result := 0;
1253  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1254  begin
1255  case FColumnTypes[ColumnIndex - 1] of
1256  stBoolean:
1257  if GetBoolean(ColumnIndex, IsNull) then
1258  Result := 1
1259  else
1260  Result := 0;
1261  stByte: Result := GetByte(ColumnIndex, IsNull);
1262  stShort: Result := PSmallInt(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1263  stInteger: Result := GetInt(ColumnIndex, IsNull);
1264  stLong: Result := GetLong(ColumnIndex, IsNull);
1265  stFloat: Result := Trunc(GetFloat(ColumnIndex, IsNull));
1266  stDouble: Result := Trunc(GetDouble(ColumnIndex, IsNull));
1267  stBigDecimal: Result := Trunc(GetBigDecimal(ColumnIndex, IsNull));
1268  stString, stUnicodeString: Result := StrToIntDef(GetString(ColumnIndex, IsNull), 0);
1269  end;
1270  IsNull := False;
1271  end
1272  else
1273  IsNull := True;
1274 end;
1275 
1276 {**
1277  Gets the value of the designated column in the current row
1278  of this <code>ResultSet</code> object as
1279  an <code>int</code> in the Java programming language.
1280 
1281  @param columnIndex the first column is 1, the second is 2, ...
1282  @return the column value; if the value is SQL <code>NULL</code>, the
1283  value returned is <code>0</code>
1284 }
1285 function TZRowAccessor.GetInt(ColumnIndex: Integer; var IsNull: Boolean): Integer;
1286 begin
1287 {$IFNDEF DISABLE_CHECKING}
1288  CheckColumnConvertion(ColumnIndex, stInteger);
1289 {$ENDIF}
1290  Result := 0;
1291  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1292  begin
1293  case FColumnTypes[ColumnIndex - 1] of
1294  stBoolean:
1295  if GetBoolean(ColumnIndex, IsNull) then
1296  Result := 1
1297  else
1298  Result := 0;
1299  stByte: Result := GetByte(ColumnIndex, IsNull);
1300  stShort: Result := GetShort(ColumnIndex, IsNull);
1301  stInteger:
1302  Result := PInteger(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1303  stLong: Result := GetLong(ColumnIndex, IsNull);
1304  stFloat: Result := Trunc(GetFloat(ColumnIndex, IsNull));
1305  stDouble: Result := Trunc(GetDouble(ColumnIndex, IsNull));
1306  stBigDecimal: Result := Trunc(GetBigDecimal(ColumnIndex, IsNull));
1307  stString, stUnicodeString:
1308  Result := StrToIntDef(GetString(ColumnIndex, IsNull), 0);
1309  end;
1310  IsNull := False;
1311  end
1312  else
1313  IsNull := True;
1314 end;
1315 
1316 {**
1317  Gets the value of the designated column in the current row
1318  of this <code>ResultSet</code> object as
1319  a <code>long</code> in the Java programming language.
1320 
1321  @param columnIndex the first column is 1, the second is 2, ...
1322  @return the column value; if the value is SQL <code>NULL</code>, the
1323  value returned is <code>0</code>
1324 }
1325 function TZRowAccessor.GetLong(ColumnIndex: Integer; var IsNull: Boolean): Int64;
1326 begin
1327 {$IFNDEF DISABLE_CHECKING}
1328  CheckColumnConvertion(ColumnIndex, stLong);
1329 {$ENDIF}
1330  Result := 0;
1331  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1332  begin
1333  case FColumnTypes[ColumnIndex - 1] of
1334  stBoolean:
1335  if GetBoolean(ColumnIndex, IsNull) then
1336  Result := 1
1337  else
1338  Result := 0;
1339  stByte: Result := GetByte(ColumnIndex, IsNull);
1340  stShort: Result := GetShort(ColumnIndex, IsNull);
1341  stInteger: Result := GetInt(ColumnIndex, IsNull);
1342  stLong:
1343  Result := PInt64(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1344  stFloat: Result := Trunc(GetFloat(ColumnIndex, IsNull));
1345  stDouble: Result := Trunc(GetDouble(ColumnIndex, IsNull));
1346  stBigDecimal: Result := Trunc(GetBigDecimal(ColumnIndex, IsNull));
1347  stString, stUnicodeString:
1348  Result := StrToIntDef(GetString(ColumnIndex, IsNull), 0);
1349  end;
1350  IsNull := False;
1351  end
1352  else
1353  IsNull := True;
1354 end;
1355 
1356 {**
1357  Gets the value of the designated column in the current row
1358  of this <code>ResultSet</code> object as
1359  a <code>float</code> in the Java programming language.
1360 
1361  @param columnIndex the first column is 1, the second is 2, ...
1362  @return the column value; if the value is SQL <code>NULL</code>, the
1363  value returned is <code>0</code>
1364 }
1365 function TZRowAccessor.GetFloat(ColumnIndex: Integer; var IsNull: Boolean): Single;
1366 begin
1367 {$IFNDEF DISABLE_CHECKING}
1368  CheckColumnConvertion(ColumnIndex, stFloat);
1369 {$ENDIF}
1370  Result := 0;
1371  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1372  begin
1373  case FColumnTypes[ColumnIndex - 1] of
1374  stBoolean:
1375  if GetBoolean(ColumnIndex, IsNull) then
1376  Result := 1
1377  else
1378  Result := 0;
1379  stByte: Result := GetByte(ColumnIndex, IsNull);
1380  stShort: Result := GetShort(ColumnIndex, IsNull);
1381  stInteger: Result := GetInt(ColumnIndex, IsNull);
1382  stLong: Result := GetLong(ColumnIndex, IsNull);
1383  stFloat:
1384  Result := PSingle(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1385  stDouble: Result := GetDouble(ColumnIndex, IsNull);
1386  stBigDecimal: Result := GetBigDecimal(ColumnIndex, IsNull);
1387  stString, stUnicodeString:
1388  Result := SQLStrToFloatDef(AnsiString(GetString(ColumnIndex, IsNull)), 0);
1389  end;
1390  IsNull := False;
1391  end
1392  else
1393  IsNull := True;
1394 end;
1395 
1396 {**
1397  Gets the value of the designated column in the current row
1398  of this <code>ResultSet</code> object as
1399  a <code>double</code> in the Java programming language.
1400 
1401  @param columnIndex the first column is 1, the second is 2, ...
1402  @return the column value; if the value is SQL <code>NULL</code>, the
1403  value returned is <code>0</code>
1404 }
1405 function TZRowAccessor.GetDouble(ColumnIndex: Integer; var IsNull: Boolean): Double;
1406 begin
1407 {$IFNDEF DISABLE_CHECKING}
1408  CheckColumnConvertion(ColumnIndex, stDouble);
1409 {$ENDIF}
1410  Result := 0;
1411  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1412  begin
1413  case FColumnTypes[ColumnIndex - 1] of
1414  stBoolean:
1415  if GetBoolean(ColumnIndex, IsNull) then
1416  Result := 1
1417  else
1418  Result := 0;
1419  stByte: Result := GetByte(ColumnIndex, IsNull);
1420  stShort: Result := GetShort(ColumnIndex, IsNull);
1421  stInteger: Result := GetInt(ColumnIndex, IsNull);
1422  stLong: Result := GetLong(ColumnIndex, IsNull);
1423  stFloat: Result := GetFloat(ColumnIndex, IsNull);
1424  stDouble:
1425  Result := PDouble(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1426  stBigDecimal: Result := GetBigDecimal(ColumnIndex, IsNull);
1427  stString, stUnicodeString:
1428  Result := SQLStrToFloatDef(AnsiString(GetString(ColumnIndex, IsNull)), 0);
1429  end;
1430  IsNull := False;
1431  end
1432  else
1433  IsNull := True;
1434 end;
1435 
1436 {**
1437  Gets the value of the designated column in the current row
1438  of this <code>ResultSet</code> object as
1439  a <code>java.sql.BigDecimal</code> in the Java programming language.
1440 
1441  @param columnIndex the first column is 1, the second is 2, ...
1442  @param scale the number of digits to the right of the decimal point
1443  @return the column value; if the value is SQL <code>NULL</code>, the
1444  value returned is <code>null</code>
1445 }
1446 function TZRowAccessor.GetBigDecimal(ColumnIndex: Integer; var IsNull: Boolean): Extended;
1447 begin
1448 {$IFNDEF DISABLE_CHECKING}
1449  CheckColumnConvertion(ColumnIndex, stBigDecimal);
1450 {$ENDIF}
1451  Result := 0;
1452  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1453  begin
1454  case FColumnTypes[ColumnIndex - 1] of
1455  stBoolean:
1456  if GetBoolean(ColumnIndex, IsNull) then
1457  Result := 1
1458  else
1459  Result := 0;
1460  stByte: Result := GetByte(ColumnIndex, IsNull);
1461  stShort: Result := GetShort(ColumnIndex, IsNull);
1462  stInteger: Result := GetInt(ColumnIndex, IsNull);
1463  stLong: Result := GetLong(ColumnIndex, IsNull);
1464  stFloat: Result := GetFloat(ColumnIndex, IsNull);
1465  stDouble: Result := GetDouble(ColumnIndex, IsNull);
1466  stBigDecimal:
1467  Result := PExtended(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1468  stString, stUnicodeString:
1469  Result := SQLStrToFloatDef(AnsiString(GetString(ColumnIndex, IsNull)), 0);
1470  end;
1471  IsNull := False;
1472  end
1473  else
1474  IsNull := True;
1475 end;
1476 
1477 {**
1478  Gets the value of the designated column in the current row
1479  of this <code>ResultSet</code> object as
1480  a <code>byte</code> array in the Java programming language.
1481  The bytes represent the raw values returned by the driver.
1482 
1483  @param columnIndex the first column is 1, the second is 2, ...
1484  @return the column value; if the value is SQL <code>NULL</code>, the
1485  value returned is <code>null</code>
1486 }
1487 function TZRowAccessor.GetBytes(ColumnIndex: Integer; var IsNull: Boolean): TByteDynArray;
1488 begin
1489 {$IFNDEF DISABLE_CHECKING}
1490  CheckColumnConvertion(ColumnIndex, stBytes);
1491 {$ENDIF}
1492  Result := nil;
1493  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1494  begin
1495  case FColumnTypes[ColumnIndex - 1] of
1496  stBytes,stGUID:
1497  Result := InternalGetBytes(FBuffer, ColumnIndex);
1498  stBinaryStream:
1499  Result := GetBlob(ColumnIndex, IsNull).GetBytes;
1500  else
1501  Result := StrToBytes(AnsiString(GetString(ColumnIndex, IsNull)));
1502  end;
1503  IsNull := False;
1504  end
1505  else
1506  IsNull := True;
1507 end;
1508 
1509 {**
1510  Gets the value of the designated column in the current row
1511  of this <code>ResultSet</code> object as
1512  a <code>java.sql.Date</code> object in the Java programming language.
1513 
1514  @param columnIndex the first column is 1, the second is 2, ...
1515  @return the column value; if the value is SQL <code>NULL</code>, the
1516  value returned is <code>null</code>
1517 }
1518 function TZRowAccessor.GetDate(ColumnIndex: Integer; var IsNull: Boolean): TDateTime;
1519 begin
1520 {$IFNDEF DISABLE_CHECKING}
1521  CheckColumnConvertion(ColumnIndex, stDate);
1522 {$ENDIF}
1523  Result := 0;
1524  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1525  begin
1526  case FColumnTypes[ColumnIndex - 1] of
1527  stDate, stTime, stTimestamp:
1528  Result := Int(PDateTime(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^);
1529  stString, stUnicodeString:
1530  Result := Trunc(AnsiSQLDateToDateTime(GetString(ColumnIndex, IsNull)));
1531  end;
1532  IsNull := False;
1533  end
1534  else
1535  IsNull := True;
1536 end;
1537 
1538 {**
1539  Gets the value of the designated column in the current row
1540  of this <code>ResultSet</code> object as
1541  a <code>java.sql.Time</code> object in the Java programming language.
1542 
1543  @param columnIndex the first column is 1, the second is 2, ...
1544  @return the column value; if the value is SQL <code>NULL</code>, the
1545  value returned is <code>null</code>
1546 }
1547 function TZRowAccessor.GetTime(ColumnIndex: Integer; var IsNull: Boolean): TDateTime;
1548 begin
1549 {$IFNDEF DISABLE_CHECKING}
1550  CheckColumnConvertion(ColumnIndex, stTime);
1551 {$ENDIF}
1552  Result := 0;
1553  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1554  begin
1555  case FColumnTypes[ColumnIndex - 1] of
1556  stDate, stTime, stTimestamp:
1557  Result := Frac(PDateTime(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^);
1558  stString, stUnicodeString:
1559  Result := Frac(AnsiSQLDateToDateTime(GetString(ColumnIndex, IsNull)));
1560  end;
1561  IsNull := False;
1562  end
1563  else
1564  IsNull := True;
1565 end;
1566 
1567 {**
1568  Gets the value of the designated column in the current row
1569  of this <code>ResultSet</code> object as
1570  a <code>java.sql.Timestamp</code> object in the Java programming language.
1571 
1572  @param columnIndex the first column is 1, the second is 2, ...
1573  @return the column value; if the value is SQL <code>NULL</code>, the
1574  value returned is <code>null</code>
1575  @exception SQLException if a database access error occurs
1576 }
1577 function TZRowAccessor.GetTimestamp(ColumnIndex: Integer; var IsNull: Boolean): TDateTime;
1578 begin
1579 {$IFNDEF DISABLE_CHECKING}
1580  CheckColumnConvertion(ColumnIndex, stTimestamp);
1581 {$ENDIF}
1582  Result := 0;
1583  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1584  begin
1585  case FColumnTypes[ColumnIndex - 1] of
1586  stDate, stTime, stTimestamp:
1587  Result := PDateTime(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^;
1588  stString, stUnicodeString:
1589  Result := AnsiSQLDateToDateTime(GetString(ColumnIndex, IsNull));
1590  end;
1591  IsNull := False;
1592  end
1593  else
1594  IsNull := True;
1595 end;
1596 
1597 {**
1598  Gets the value of the designated column in the current row
1599  of this <code>ResultSet</code> object as
1600  a stream of ASCII characters. The value can then be read in chunks from the
1601  stream. This method is particularly
1602  suitable for retrieving large <char>LONGVARCHAR</char> values.
1603  The JDBC driver will
1604  do any necessary conversion from the database format into ASCII.
1605 
1606  <P><B>Note:</B> All the data in the returned stream must be
1607  read prior to getting the value of any other column. The next
1608  call to a <code>getXXX</code> method implicitly closes the stream. Also, a
1609  stream may return <code>0</code> when the method
1610  <code>InputStream.available</code>
1611  is called whether there is data available or not.
1612 
1613  @param columnIndex the first column is 1, the second is 2, ...
1614  @return a Java input stream that delivers the database column value
1615  as a stream of one-byte ASCII characters; if the value is SQL
1616  <code>NULL</code>, the value returned is <code>null</code>
1617 }
1618 function TZRowAccessor.GetAsciiStream(ColumnIndex: Integer; var IsNull: Boolean): TStream;
1619 var
1620  TempBlob: IZBlob;
1621 begin
1622 {$IFNDEF DISABLE_CHECKING}
1623  CheckColumnConvertion(ColumnIndex, stAsciiStream);
1624 {$ENDIF}
1625  TempBlob := GetBlobObject(FBuffer, ColumnIndex);
1626  if (TempBlob <> nil) and not TempBlob.IsEmpty then
1627  Result := TempBlob.GetStream
1628  else
1629  Result := nil;
1630  IsNull := Result = nil;
1631 end;
1632 
1633 {**
1634  Gets the value of a column in the current row as a stream of
1635  Gets the value of the designated column in the current row
1636  of this <code>ResultSet</code> object as
1637  as a stream of Unicode characters.
1638  The value can then be read in chunks from the
1639  stream. This method is particularly
1640  suitable for retrieving large<code>LONGVARCHAR</code>values. The JDBC driver will
1641  do any necessary conversion from the database format into Unicode.
1642  The byte format of the Unicode stream must be Java UTF-8,
1643  as specified in the Java virtual machine specification.
1644 
1645  <P><B>Note:</B> All the data in the returned stream must be
1646  read prior to getting the value of any other column. The next
1647  call to a <code>getXXX</code> method implicitly closes the stream. Also, a
1648  stream may return <code>0</code> when the method
1649  <code>InputStream.available</code>
1650  is called whether there is data available or not.
1651 
1652  @param columnIndex the first column is 1, the second is 2, ...
1653  @return a Java input stream that delivers the database column value
1654  as a stream in Java UTF-8 byte format; if the value is SQL
1655  <code>NULL</code>, the value returned is <code>null</code>
1656 }
1657 function TZRowAccessor.GetUnicodeStream(ColumnIndex: Integer; var IsNull: Boolean): TStream;
1658 var
1659  TempBlob: IZBlob;
1660 begin
1661 {$IFNDEF DISABLE_CHECKING}
1662  CheckColumnConvertion(ColumnIndex, stUnicodeStream);
1663 {$ENDIF}
1664  TempBlob := GetBlobObject(FBuffer, ColumnIndex);
1665  if (TempBlob <> nil) and not TempBlob.IsEmpty then
1666  Result := TempBlob.GetUnicodeStream
1667  else
1668  Result := nil;
1669  IsNull := Result = nil;
1670 end;
1671 
1672 {**
1673  Gets the value of a column in the current row as a stream of
1674  Gets the value of the designated column in the current row
1675  of this <code>ResultSet</code> object as a binary stream of
1676  uninterpreted bytes. The value can then be read in chunks from the
1677  stream. This method is particularly
1678  suitable for retrieving large <code>LONGVARBINARY</code> values.
1679 
1680  <P><B>Note:</B> All the data in the returned stream must be
1681  read prior to getting the value of any other column. The next
1682  call to a <code>getXXX</code> method implicitly closes the stream. Also, a
1683  stream may return <code>0</code> when the method
1684  <code>InputStream.available</code>
1685  is called whether there is data available or not.
1686 
1687  @param columnIndex the first column is 1, the second is 2, ...
1688  @return a Java input stream that delivers the database column value
1689  as a stream of uninterpreted bytes;
1690  if the value is SQL <code>NULL</code>, the value returned is <code>null</code>
1691 }
1692 function TZRowAccessor.GetBinaryStream(ColumnIndex: Integer; var IsNull: Boolean): TStream;
1693 var
1694  TempBlob: IZBlob;
1695 begin
1696 {$IFNDEF DISABLE_CHECKING}
1697  CheckColumnConvertion(ColumnIndex, stBinaryStream);
1698 {$ENDIF}
1699  TempBlob := GetBlobObject(FBuffer, ColumnIndex);
1700  if (TempBlob <> nil) and not TempBlob.IsEmpty then
1701  Result := TempBlob.GetStream
1702  else
1703  Result := nil;
1704  IsNull := Result = nil;
1705 end;
1706 
1707 {**
1708  Returns the value of the designated column in the current row
1709  of this <code>ResultSet</code> object as a <code>Blob</code> object
1710  in the Java programming language.
1711 
1712  @param ColumnIndex the first column is 1, the second is 2, ...
1713  @return a <code>Blob</code> object representing the SQL <code>BLOB</code> value in
1714  the specified column
1715 }
1716 function TZRowAccessor.GetBlob(ColumnIndex: Integer; var IsNull: Boolean): IZBlob;
1717 begin
1718 {$IFNDEF DISABLE_CHECKING}
1719  CheckColumnIndex(ColumnIndex);
1720  if not (FColumnTypes[ColumnIndex - 1] in [stAsciiStream, stBinaryStream,
1721  stUnicodeStream]) then
1722  begin
1723  raise EZSQLException.Create(
1724  Format(SCanNotAccessBlobRecord,
1725  [ColumnIndex, DefineColumnTypeName(FColumnTypes[ColumnIndex - 1])]));
1726  end;
1727 {$ENDIF}
1728 
1729  Result := GetBlobObject(FBuffer, ColumnIndex);
1730  IsNull := Result = nil;
1731  if Result = nil then
1732  begin
1733  Result := TZAbstractBlob.CreateWithStream(nil, nil);
1734  SetBlobObject(FBuffer, ColumnIndex, Result);
1735  end;
1736 end;
1737 
1738 {**
1739  Returns the value of the designated column in the current row
1740  of this <code>ResultSet</code> object as a <code>ResultSet</code> object
1741  in the Java programming language.
1742 
1743  @param ColumnIndex the first column is 1, the second is 2, ...
1744  @return a <code>ResultSet</code> object representing the SQL
1745  <code>ResultSet</code> value in the specified column
1746 }
1747 function TZRowAccessor.GetDataSet(ColumnIndex: Integer; var IsNull: Boolean): IZDataSet;
1748 var
1749  Ptr: PPointer;
1750  NullPtr: {$IFDEF WIN64}PBoolean{$ELSE}PByte{$ENDIF};
1751 begin
1752 {$IFNDEF DISABLE_CHECKING}
1753  CheckColumnIndex(ColumnIndex);
1754  if not (FColumnTypes[ColumnIndex - 1] = stDataSet) then
1755  begin
1756  raise EZSQLException.Create(
1757  Format(SCanNotAccessBlobRecord,
1758  [ColumnIndex, DefineColumnTypeName(FColumnTypes[ColumnIndex - 1])]));
1759  end;
1760 {$ENDIF}
1761 
1762  Ptr := PPointer(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1]);
1763  NullPtr := {$IFDEF WIN64}PBoolean{$ELSE}PByte{$ENDIF}(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]]);
1764 
1765  {$IFNDEF FPC}
1766  if NullPtr^ = {$IFDEF WIN64}false{$ELSE}0{$ENDIF} then
1767  {$ELSE}
1768  if NullPtr^ = 0 then
1769  {$ENDIF}
1770  Result := IZDataSet(Ptr^)
1771  else
1772  Result := nil;
1773 end;
1774 
1775 {**
1776  Gets the value of the designated column in the current row
1777  of this <code>ResultSet</code> object as a <code>Variant</code> value.
1778 
1779  @param columnIndex the first column is 1, the second is 2, ...
1780  @return the column value; if the value is SQL <code>NULL</code>, the
1781  value returned is <code>null</code>
1782 }
1783 function TZRowAccessor.GetValue(ColumnIndex: Integer): TZVariant;
1784 var
1785  ValuePtr: Pointer;
1786  IsNull: Boolean;
1787 begin
1788  IsNull := False;
1789  if FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0 then
1790  begin
1791  ValuePtr := @FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1];
1792  case FColumnTypes[ColumnIndex - 1] of
1793  stByte:
1794  begin
1795  Result.VType := vtInteger;
1796  Result.VInteger := PShortInt(ValuePtr)^;
1797  end;
1798  stShort:
1799  begin
1800  Result.VType := vtInteger;
1801  Result.VInteger := PSmallInt(ValuePtr)^;
1802  end;
1803  stInteger:
1804  begin
1805  Result.VType := vtInteger;
1806  Result.VInteger := PInteger(ValuePtr)^;
1807  end;
1808  stLong:
1809  begin
1810  Result.VType := vtInteger;
1811  Result.VInteger := PInt64(ValuePtr)^;
1812  end;
1813  stFloat:
1814  begin
1815  Result.VType := vtFloat;
1816  Result.VFloat := PSingle(ValuePtr)^;
1817  end;
1818  stDouble:
1819  begin
1820  Result.VType := vtFloat;
1821  Result.VFloat := PDouble(ValuePtr)^;
1822  end;
1823  stBigDecimal:
1824  begin
1825  Result.VType := vtFloat;
1826  Result.VFloat := PExtended(ValuePtr)^;
1827  end;
1828  stBoolean:
1829  begin
1830  Result.VType := vtBoolean;
1831  Result.VBoolean := PWordBool(ValuePtr)^;
1832  end;
1833  stDate, stTime, stTimestamp:
1834  begin
1835  Result.VType := vtDateTime;
1836  Result.VDateTime := PDateTime(ValuePtr)^;
1837  end;
1838  stString:
1839  begin
1840  Result.VType := vtString;
1841  Result.VString := PChar(ValuePtr);
1842  end;
1843  stUnicodeString:
1844  begin
1845  Result.VType := vtUnicodeString;
1846  Result.VUnicodeString := GetUnicodeString(ColumnIndex, IsNull);
1847  end;
1848  stBytes,stGUID,stAsciiStream, stBinaryStream:
1849  begin
1850  Result.VType := vtString;
1851  Result.VString := GetString(ColumnIndex, IsNull);
1852  end;
1853  stUnicodeStream:
1854  begin
1855  Result.VType := vtUnicodeString;
1856  Result.VUnicodeString := GetUnicodeString(ColumnIndex, IsNull);
1857  end;
1858  stDataSet:
1859  begin
1860  Result.VType := vtInterface;
1861  Result.VInterface := GetDataSet(ColumnIndex, IsNull);
1862  end;
1863  else
1864  Result.VType := vtNull;
1865  end;
1866  end
1867  else
1868  Result.VType := vtNull;
1869 end;
1870 
1871 //---------------------------------------------------------------------
1872 // Updates
1873 //---------------------------------------------------------------------
1874 
1875 {**
1876  Gives a not nullable column a null value.
1877 
1878  The <code>SetXXX</code> methods are used to Set column values in the
1879  current row or the insert row. The <code>SetXXX</code> methods do not
1880  Set the underlying database; instead the <code>SetRow</code>
1881  or <code>insertRow</code> methods are called to Set the database.
1882 
1883  @param columnIndex the first column is 1, the second is 2, ...
1884 }
1885 procedure TZRowAccessor.SetNotNull(ColumnIndex: Integer);
1886 begin
1887 {$IFNDEF DISABLE_CHECKING}
1888  CheckColumnConvertion(ColumnIndex, stString);
1889 {$ENDIF}
1890  if (FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 1)
1891  and (FColumnTypes[ColumnIndex - 1] in [stAsciiStream, stBinaryStream,
1892  stUnicodeStream]) then
1893  begin
1894  SetBlobObject(FBuffer, ColumnIndex, nil);
1895  end;
1896  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
1897 end;
1898 
1899 {**
1900  Gives a nullable column a null value.
1901 
1902  The <code>SetXXX</code> methods are used to Set column values in the
1903  current row or the insert row. The <code>SetXXX</code> methods do not
1904  Set the underlying database; instead the <code>SetRow</code>
1905  or <code>insertRow</code> methods are called to Set the database.
1906 
1907  @param columnIndex the first column is 1, the second is 2, ...
1908 }
1909 procedure TZRowAccessor.SetNull(ColumnIndex: Integer);
1910 begin
1911 {$IFNDEF DISABLE_CHECKING}
1912  CheckColumnConvertion(ColumnIndex, stString);
1913 {$ENDIF}
1914  if (FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] = 0) then
1915  case FColumnTypes[ColumnIndex - 1] of
1916  stAsciiStream, stBinaryStream, stUnicodeStream:
1917  SetBlobObject(FBuffer, ColumnIndex, nil);
1918  stBytes,stGUID, stString, stUnicodeString:
1919  if PNativeUInt(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ > 0 then
1920  begin
1921  System.Dispose(PPointer(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^);
1922  PNativeUInt(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := 0;
1923  end;
1924  end;
1925  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 1;
1926 end;
1927 
1928 {**
1929  Sets the designated column with a <code>boolean</code> value.
1930  The <code>SetXXX</code> methods are used to Set column values in the
1931  current row or the insert row. The <code>SetXXX</code> methods do not
1932  Set the underlying database; instead the <code>SetRow</code> or
1933  <code>insertRow</code> methods are called to Set the database.
1934 
1935  @param columnIndex the first column is 1, the second is 2, ...
1936  @param x the new column value
1937 }
1938 procedure TZRowAccessor.SetBoolean(ColumnIndex: Integer; Value: Boolean);
1939 var
1940  TempInt: Integer;
1941 begin
1942 {$IFNDEF DISABLE_CHECKING}
1943  CheckColumnConvertion(ColumnIndex, stBoolean);
1944 {$ENDIF}
1945  if Value then
1946  TempInt := 1
1947  else
1948  TempInt := 0;
1949 
1950  case FColumnTypes[ColumnIndex - 1] of
1951  stBoolean:
1952  begin
1953  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
1954  PWordBool(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := Value;
1955  end;
1956  stByte: SetByte(ColumnIndex, TempInt);
1957  stShort: SetShort(ColumnIndex, TempInt);
1958  stInteger: SetInt(ColumnIndex, TempInt);
1959  stLong: SetLong(ColumnIndex, TempInt);
1960  stFloat: SetFloat(ColumnIndex, TempInt);
1961  stDouble: SetDouble(ColumnIndex, TempInt);
1962  stBigDecimal: SetBigDecimal(ColumnIndex, TempInt);
1963  stString, stUnicodeString:
1964  if Value then
1965  SetString(ColumnIndex, 'True')
1966  else
1967  SetString(ColumnIndex, 'False');
1968  end;
1969 end;
1970 
1971 {**
1972  Sets the designated column with a <code>byte</code> value.
1973  The <code>SetXXX</code> methods are used to Set column values in the
1974  current row or the insert row. The <code>SetXXX</code> methods do not
1975  Set the underlying database; instead the <code>SetRow</code> or
1976  <code>insertRow</code> methods are called to Set the database.
1977 
1978 
1979  @param columnIndex the first column is 1, the second is 2, ...
1980  @param x the new column value
1981 }
1982 procedure TZRowAccessor.SetByte(ColumnIndex: Integer;
1983  Value: ShortInt);
1984 begin
1985 {$IFNDEF DISABLE_CHECKING}
1986  CheckColumnConvertion(ColumnIndex, stByte);
1987 {$ENDIF}
1988  case FColumnTypes[ColumnIndex - 1] of
1989  stBoolean: SetBoolean(ColumnIndex, Value <> 0);
1990  stByte:
1991  begin
1992  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
1993  PShortInt(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := Value;
1994  end;
1995  stShort: SetShort(ColumnIndex, Value);
1996  stInteger: SetInt(ColumnIndex, Value);
1997  stLong: SetLong(ColumnIndex, Value);
1998  stFloat: SetFloat(ColumnIndex, Value);
1999  stDouble: SetDouble(ColumnIndex, Value);
2000  stBigDecimal: SetBigDecimal(ColumnIndex, Value);
2001  stString, stUnicodeString: SetString(ColumnIndex, IntToStr(Value));
2002  end;
2003 end;
2004 
2005 {**
2006  Sets the designated column with a <code>short</code> value.
2007  The <code>SetXXX</code> methods are used to Set column values in the
2008  current row or the insert row. The <code>SetXXX</code> methods do not
2009  Set the underlying database; instead the <code>SetRow</code> or
2010  <code>insertRow</code> methods are called to Set the database.
2011 
2012  @param columnIndex the first column is 1, the second is 2, ...
2013  @param x the new column value
2014 }
2015 procedure TZRowAccessor.SetShort(ColumnIndex: Integer; Value: SmallInt);
2016 begin
2017 {$IFNDEF DISABLE_CHECKING}
2018  CheckColumnConvertion(ColumnIndex, stShort);
2019 {$ENDIF}
2020  case FColumnTypes[ColumnIndex - 1] of
2021  stBoolean: SetBoolean(ColumnIndex, Value <> 0);
2022  stByte: SetByte(ColumnIndex, Value);
2023  stShort:
2024  begin
2025  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2026  PSmallInt(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := Value;
2027  end;
2028  stInteger: SetInt(ColumnIndex, Value);
2029  stLong: SetLong(ColumnIndex, Value);
2030  stFloat: SetFloat(ColumnIndex, Value);
2031  stDouble: SetDouble(ColumnIndex, Value);
2032  stBigDecimal: SetBigDecimal(ColumnIndex, Value);
2033  stString, stUnicodeString: SetString(ColumnIndex, IntToStr(Value));
2034  end;
2035 end;
2036 
2037 {**
2038  Sets the designated column with an <code>int</code> value.
2039  The <code>SetXXX</code> methods are used to Set column values in the
2040  current row or the insert row. The <code>SetXXX</code> methods do not
2041  Set the underlying database; instead the <code>SetRow</code> or
2042  <code>insertRow</code> methods are called to Set the database.
2043 
2044  @param columnIndex the first column is 1, the second is 2, ...
2045  @param x the new column value
2046 }
2047 procedure TZRowAccessor.SetInt(ColumnIndex: Integer; Value: Integer);
2048 begin
2049 {$IFNDEF DISABLE_CHECKING}
2050  CheckColumnConvertion(ColumnIndex, stInteger);
2051 {$ENDIF}
2052  case FColumnTypes[ColumnIndex - 1] of
2053  stBoolean: SetBoolean(ColumnIndex, Value <> 0);
2054  stByte: SetByte(ColumnIndex, Value);
2055  stShort: SetShort(ColumnIndex, Value);
2056  stInteger:
2057  begin
2058  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2059  PInteger(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := Value;
2060  end;
2061  stLong: SetLong(ColumnIndex, Value);
2062  stFloat: SetFloat(ColumnIndex, Value);
2063  stDouble: SetDouble(ColumnIndex, Value);
2064  stBigDecimal: SetBigDecimal(ColumnIndex, Value);
2065  stString, stUnicodeString: SetString(ColumnIndex, IntToStr(Value));
2066  end;
2067 end;
2068 
2069 {**
2070  Sets the designated column with a <code>long</code> value.
2071  The <code>SetXXX</code> methods are used to Set column values in the
2072  current row or the insert row. The <code>SetXXX</code> methods do not
2073  Set the underlying database; instead the <code>SetRow</code> or
2074  <code>insertRow</code> methods are called to Set the database.
2075 
2076  @param columnIndex the first column is 1, the second is 2, ...
2077  @param x the new column value
2078 }
2079 procedure TZRowAccessor.SetLong(ColumnIndex: Integer; Value: Int64);
2080 begin
2081 {$IFNDEF DISABLE_CHECKING}
2082  CheckColumnConvertion(ColumnIndex, stLong);
2083 {$ENDIF}
2084  case FColumnTypes[ColumnIndex - 1] of
2085  stBoolean: SetBoolean(ColumnIndex, Value <> 0);
2086  stByte: SetByte(ColumnIndex, Value);
2087  stShort: SetShort(ColumnIndex, Value);
2088  stInteger: SetInt(ColumnIndex, Value);
2089  stLong:
2090  begin
2091  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2092  PInt64(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := Value;
2093  end;
2094  stFloat: SetFloat(ColumnIndex, Value);
2095  stDouble: SetDouble(ColumnIndex, Value);
2096  stBigDecimal: SetBigDecimal(ColumnIndex, Value);
2097  stString, stUnicodeString: SetString(ColumnIndex, IntToStr(Value));
2098  end;
2099 end;
2100 
2101 {**
2102  Sets the designated column with a <code>float</code> value.
2103  The <code>SetXXX</code> methods are used to Set column values in the
2104  current row or the insert row. The <code>SetXXX</code> methods do not
2105  Set the underlying database; instead the <code>SetRow</code> or
2106  <code>insertRow</code> methods are called to Set the database.
2107 
2108  @param columnIndex the first column is 1, the second is 2, ...
2109  @param x the new column value
2110 }
2111 procedure TZRowAccessor.SetFloat(ColumnIndex: Integer; Value: Single);
2112 begin
2113 {$IFNDEF DISABLE_CHECKING}
2114  CheckColumnConvertion(ColumnIndex, stFloat);
2115 {$ENDIF}
2116  case FColumnTypes[ColumnIndex - 1] of
2117  stBoolean: SetBoolean(ColumnIndex, Value <> 0);
2118  stByte: SetByte(ColumnIndex, Trunc(Value));
2119  stShort: SetShort(ColumnIndex, Trunc(Value));
2120  stInteger: SetInt(ColumnIndex, Trunc(Value));
2121  stLong: SetLong(ColumnIndex, Trunc(Value));
2122  stFloat:
2123  begin
2124  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2125  PSingle(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := Value;
2126  end;
2127  stDouble: SetDouble(ColumnIndex, Value);
2128  stBigDecimal: SetBigDecimal(ColumnIndex, Value);
2129  stString, stUnicodeString: SetString(ColumnIndex, FloatToSQLStr(Value));
2130  end;
2131 end;
2132 
2133 {**
2134  Sets the designated column with a <code>double</code> value.
2135  The <code>SetXXX</code> methods are used to Set column values in the
2136  current row or the insert row. The <code>SetXXX</code> methods do not
2137  Set the underlying database; instead the <code>SetRow</code> or
2138  <code>insertRow</code> methods are called to Set the database.
2139 
2140  @param columnIndex the first column is 1, the second is 2, ...
2141  @param x the new column value
2142 }
2143 procedure TZRowAccessor.SetDouble(ColumnIndex: Integer; Value: Double);
2144 begin
2145 {$IFNDEF DISABLE_CHECKING}
2146  CheckColumnConvertion(ColumnIndex, stDouble);
2147 {$ENDIF}
2148  case FColumnTypes[ColumnIndex - 1] of
2149  stBoolean: SetBoolean(ColumnIndex, Value <> 0);
2150  stByte: SetByte(ColumnIndex, Trunc(Value));
2151  stShort: SetShort(ColumnIndex, Trunc(Value));
2152  stInteger: SetInt(ColumnIndex, Trunc(Value));
2153  stLong: SetLong(ColumnIndex, Trunc(Value));
2154  stFloat: SetFloat(ColumnIndex, Value);
2155  stDouble:
2156  begin
2157  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2158  PDouble(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := Value;
2159  end;
2160  stBigDecimal: SetBigDecimal(ColumnIndex, Value);
2161  stString, stUnicodeString: SetString(ColumnIndex, FloatToSQLStr(Value));
2162  end;
2163 end;
2164 
2165 {**
2166  Sets the designated column with a <code>java.math.BigDecimal</code>
2167  value.
2168  The <code>SetXXX</code> methods are used to Set column values in the
2169  current row or the insert row. The <code>SetXXX</code> methods do not
2170  Set the underlying database; instead the <code>SetRow</code> or
2171  <code>insertRow</code> methods are called to Set the database.
2172 
2173  @param columnIndex the first column is 1, the second is 2, ...
2174  @param x the new column value
2175 }
2176 procedure TZRowAccessor.SetBigDecimal(ColumnIndex: Integer; Value: Extended);
2177 begin
2178 {$IFNDEF DISABLE_CHECKING}
2179  CheckColumnConvertion(ColumnIndex, stBigDecimal);
2180 {$ENDIF}
2181  case FColumnTypes[ColumnIndex - 1] of
2182  stBoolean: SetBoolean(ColumnIndex, Value <> 0);
2183  stByte: SetByte(ColumnIndex, Trunc(Value));
2184  stShort: SetShort(ColumnIndex, Trunc(Value));
2185  stInteger: SetInt(ColumnIndex, Trunc(Value));
2186  stLong: SetLong(ColumnIndex, Trunc(Value));
2187  stFloat: SetFloat(ColumnIndex, Value);
2188  stDouble: SetDouble(ColumnIndex, Value);
2189  stBigDecimal:
2190  begin
2191  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2192  PExtended(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := Value;
2193  end;
2194  stString, stUnicodeString: SetString(ColumnIndex, FloatToSQLStr(Value));
2195  end;
2196 end;
2197 
2198 {**
2199  Sets the designated column with a <code>String</code> value.
2200  The <code>SetXXX</code> methods are used to Set column values in the
2201  current row or the insert row. The <code>SetXXX</code> methods do not
2202  Set the underlying database; instead the <code>SetRow</code> or
2203  <code>insertRow</code> methods are called to Set the database.
2204 
2205  @param columnIndex the first column is 1, the second is 2, ...
2206  @param x the new column value
2207 }
2208 procedure TZRowAccessor.SetPChar(ColumnIndex: Integer; Value: PChar);
2209 begin
2210 {$IFNDEF DISABLE_CHECKING}
2211  CheckColumnConvertion(ColumnIndex, stString);
2212 {$ENDIF}
2213  case FColumnTypes[ColumnIndex - 1] of
2214  stString{$IFDEF UNICODE}, stUnicodeString{$ENDIF}:
2215  begin
2216  if Value <> nil then
2217  begin
2218  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2219  SetString(ColumnIndex, Value);
2220  end
2221  else
2222  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 1;
2223  end;
2224  else
2225  SetString(ColumnIndex, Value);
2226  end;
2227 end;
2228 
2229 {**
2230  Sets the designated column with a <code>String</code> value.
2231  The <code>SetXXX</code> methods are used to Set column values in the
2232  current row or the insert row. The <code>SetXXX</code> methods do not
2233  Set the underlying database; instead the <code>SetRow</code> or
2234  <code>insertRow</code> methods are called to Set the database.
2235 
2236  @param columnIndex the first column is 1, the second is 2, ...
2237  @param x the new column value
2238 }
2239 procedure TZRowAccessor.SetString(ColumnIndex: Integer; Value: String);
2240 var
2241  TempStr: string;
2242  IsNull: Boolean;
2243  GUID: TGUID;
2244  Bts: TByteDynArray;
2245 begin
2246 {$IFNDEF DISABLE_CHECKING}
2247  CheckColumnConvertion(ColumnIndex, stString);
2248 {$ENDIF}
2249  IsNull := False;
2250  case FColumnTypes[ColumnIndex - 1] of
2251  stBoolean:
2252  begin
2253  TempStr := UpperCase(Value);
2254  SetBoolean(ColumnIndex, (TempStr = 'Y') or (TempStr = 'T')
2255  or (TempStr = 'YES') or (TempStr = 'TRUE'));
2256  end;
2257  stByte: SetByte(ColumnIndex, StrToIntDef(Value, 0));
2258  stShort: SetShort(ColumnIndex, StrToIntDef(Value, 0));
2259  stInteger: SetInt(ColumnIndex, StrToIntDef(Value, 0));
2260  stLong: SetLong(ColumnIndex, StrToIntDef(Value, 0));
2261  stFloat: SetFloat(ColumnIndex, SQLStrToFloatDef(AnsiString(Value), 0));
2262  stDouble: SetDouble(ColumnIndex, SQLStrToFloatDef(AnsiString(Value), 0));
2263  stBigDecimal: SetBigDecimal(ColumnIndex, SQLStrToFloatDef(AnsiString(Value), 0));
2264  stString:
2265  begin
2266  InternalSetString(FBuffer, ColumnIndex, Value);
2267  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2268  end;
2269  stUnicodeString:
2270  {$IFDEF UNICODE}
2271  SetUnicodeString(ColumnIndex, Value);
2272  {$ELSE}
2273  SetUnicodeString(ColumnIndex, ZDbcUnicodeString(Value, ConSettings.CTRL_CP));
2274  {$ENDIF}
2275  stBytes: SetBytes(ColumnIndex, StrToBytes(AnsiString(Value)));
2276  stGUID:
2277  begin
2278  GUID := StringToGUID(Value);
2279  SetLength(Bts, 16);
2280  System.Move(Pointer(@GUID)^, Pointer(Bts)^, 16);
2281  SetBytes(ColumnIndex, Bts);
2282  end;
2283  stDate: SetDate(ColumnIndex, AnsiSQLDateToDateTime(Value));
2284  stTime: SetTime(ColumnIndex, AnsiSQLDateToDateTime(Value));
2285  stTimestamp: SetTimestamp(ColumnIndex, AnsiSQLDateToDateTime(Value));
2286  stUnicodeStream:
2287  {$IFDEF UNICODE}
2288  GetBlob(ColumnIndex, IsNull).SetUnicodeString(Value);
2289  {$ELSE}
2290  GetBlob(ColumnIndex, IsNull).SetString(ZDbcUnicodeString(Value, ConSettings.CTRL_CP));
2291  {$ENDIF}
2292  stAsciiStream:
2293  GetBlob(ColumnIndex, IsNull).SetString(ZPlainString(Value, ConSettings, ConSettings.CTRL_CP));
2294  stBinaryStream:
2295  GetBlob(ColumnIndex, IsNull).SetString(RawByteString(Value));
2296  end;
2297 end;
2298 
2299 {**
2300  Sets the designated column with a <code>WideString</code> value.
2301  The <code>SetXXX</code> methods are used to Set column values in the
2302  current row or the insert row. The <code>SetXXX</code> methods do not
2303  Set the underlying database; instead the <code>SetRow</code> or
2304  <code>insertRow</code> methods are called to Set the database.
2305 
2306  @param columnIndex the first column is 1, the second is 2, ...
2307  @param x the new column value
2308 }
2309 procedure TZRowAccessor.SetUnicodeString(ColumnIndex: Integer; Value: WideString);
2310 var IsNull: Boolean;
2311 begin
2312 {$IFNDEF DISABLE_CHECKING}
2313  CheckColumnConvertion(ColumnIndex, stString);
2314 {$ENDIF}
2315  case FColumnTypes[ColumnIndex - 1] of
2316  stUnicodeString{$IFDEF UNICODE},stString{$ENDIF}:
2317  begin
2318  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2319  InternalSetUnicodeString(FBuffer, ColumnIndex, Value);
2320  end;
2321  stUnicodeStream:
2322  GetBlob(ColumnIndex, IsNull).SetUnicodeString(Value);
2323  else
2324  SetString(ColumnIndex, ZDbcString(Value));
2325  end;
2326 end;
2327 
2328 {**
2329  Sets the designated column with a <code>byte</code> array value.
2330  The <code>SetXXX</code> methods are used to Set column values in the
2331  current row or the insert row. The <code>SetXXX</code> methods do not
2332  Set the underlying database; instead the <code>SetRow</code> or
2333  <code>insertRow</code> methods are called to Set the database.
2334 
2335  @param columnIndex the first column is 1, the second is 2, ...
2336  @param x the new column value
2337 }
2338 procedure TZRowAccessor.SetBytes(ColumnIndex: Integer; Value: TByteDynArray);
2339 var
2340  IsNull: Boolean;
2341 begin
2342 {$IFNDEF DISABLE_CHECKING}
2343  CheckColumnConvertion(ColumnIndex, stBytes);
2344 {$ENDIF}
2345  if Value <> nil then
2346  begin
2347  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2348  case FColumnTypes[ColumnIndex - 1] of
2349  stBytes,stGUID: InternalSetBytes(FBuffer, ColumnIndex, Value);
2350  stBinaryStream: GetBlob(ColumnIndex, IsNull).SetBytes(Value);
2351  else
2352  SetString(ColumnIndex, String(BytesToStr(Value)));
2353  end;
2354  end
2355  else
2356  SetNull(ColumnIndex);
2357 end;
2358 
2359 {**
2360  Sets the designated column with a <code>java.sql.Date</code> value.
2361  The <code>SetXXX</code> methods are used to Set column values in the
2362  current row or the insert row. The <code>SetXXX</code> methods do not
2363  Set the underlying database; instead the <code>SetRow</code> or
2364  <code>insertRow</code> methods are called to Set the database.
2365 
2366  @param columnIndex the first column is 1, the second is 2, ...
2367  @param x the new column value
2368 }
2369 procedure TZRowAccessor.SetDate(ColumnIndex: Integer; Value: TDateTime);
2370 begin
2371 {$IFNDEF DISABLE_CHECKING}
2372  CheckColumnConvertion(ColumnIndex, stTimestamp);
2373 {$ENDIF}
2374  case FColumnTypes[ColumnIndex - 1] of
2375  stDate:
2376  begin
2377  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2378  PDateTime(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ :=
2379  Trunc(Value);
2380  end;
2381  stTimestamp: SetTimestamp(ColumnIndex, Trunc(Value));
2382  stString, stUnicodeString: SetString(ColumnIndex, FormatDateTime('yyyy-mm-dd', Value));
2383  end;
2384 end;
2385 
2386 {**
2387  Sets the designated column with a <code>java.sql.Time</code> value.
2388  The <code>SetXXX</code> methods are used to Set column values in the
2389  current row or the insert row. The <code>SetXXX</code> methods do not
2390  Set the underlying database; instead the <code>SetRow</code> or
2391  <code>insertRow</code> methods are called to Set the database.
2392 
2393  @param columnIndex the first column is 1, the second is 2, ...
2394  @param x the new column value
2395 }
2396 procedure TZRowAccessor.SetTime(ColumnIndex: Integer; Value: TDateTime);
2397 begin
2398 {$IFNDEF DISABLE_CHECKING}
2399  CheckColumnConvertion(ColumnIndex, stTime);
2400 {$ENDIF}
2401  case FColumnTypes[ColumnIndex - 1] of
2402  stTime:
2403  begin
2404  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2405  PDateTime(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ :=
2406  Frac(Value);
2407  end;
2408  stTimestamp: SetTimestamp(ColumnIndex, Frac(Value));
2409  stString, stUnicodeString:
2410  SetString(ColumnIndex, FormatDateTime('hh:nn:ss', Value));
2411  end;
2412 end;
2413 
2414 {**
2415  Sets the designated column with a <code>java.sql.Timestamp</code>
2416  value.
2417  The <code>SetXXX</code> methods are used to Set column values in the
2418  current row or the insert row. The <code>SetXXX</code> methods do not
2419  Set the underlying database; instead the <code>SetRow</code> or
2420  <code>insertRow</code> methods are called to Set the database.
2421 
2422  @param columnIndex the first column is 1, the second is 2, ...
2423  @param x the new column value
2424 }
2425 procedure TZRowAccessor.SetTimestamp(ColumnIndex: Integer; Value: TDateTime);
2426 begin
2427 {$IFNDEF DISABLE_CHECKING}
2428  CheckColumnConvertion(ColumnIndex, stTimestamp);
2429 {$ENDIF}
2430  case FColumnTypes[ColumnIndex - 1] of
2431  stDate: SetDate(ColumnIndex, Value);
2432  stTime: SetTime(ColumnIndex, Value);
2433  stTimestamp:
2434  begin
2435  FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]] := 0;
2436  PDateTime(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1])^ := Value;
2437  end;
2438  stString, stUnicodeString:
2439  SetString(ColumnIndex, FormatDateTime('yyyy-mm-dd hh:nn:ss', Value));
2440  end;
2441 end;
2442 
2443 {**
2444  Sets the designated column with an ascii stream value.
2445  The <code>SetXXX</code> methods are used to Set column values in the
2446  current row or the insert row. The <code>SetXXX</code> methods do not
2447  Set the underlying database; instead the <code>SetRow</code> or
2448  <code>insertRow</code> methods are called to Set the database.
2449 
2450  @param columnIndex the first column is 1, the second is 2, ...
2451  @param x the new column value
2452 }
2453 procedure TZRowAccessor.SetAsciiStream(ColumnIndex: Integer; Value: TStream);
2454 var
2455  IsNull: Boolean;
2456 begin
2457 {$IFNDEF DISABLE_CHECKING}
2458  CheckColumnConvertion(ColumnIndex, stAsciiStream);
2459 {$ENDIF}
2460  IsNull := False;
2461  GetBlob(ColumnIndex, IsNull).SetStream(Value);
2462 end;
2463 
2464 {**
2465  Sets the designated column with a binary stream value.
2466  The <code>SetXXX</code> methods are used to Set column values in the
2467  current row or the insert row. The <code>SetXXX</code> methods do not
2468  Set the underlying database; instead the <code>SetRow</code> or
2469  <code>insertRow</code> methods are called to Set the database.
2470 
2471  @param columnIndex the first column is 1, the second is 2, ...
2472  @param x the new column value
2473  @param length the length of the stream
2474 }
2475 procedure TZRowAccessor.SetBinaryStream(ColumnIndex: Integer; Value: TStream);
2476 var
2477  IsNull: Boolean;
2478 begin
2479 {$IFNDEF DISABLE_CHECKING}
2480  CheckColumnConvertion(ColumnIndex, stBinaryStream);
2481 {$ENDIF}
2482  IsNull := False;
2483  GetBlob(ColumnIndex, IsNull).SetStream(Value);
2484 end;
2485 
2486 {**
2487  Sets the designated column with a character stream value.
2488  The <code>SetXXX</code> methods are used to Set column values in the
2489  current row or the insert row. The <code>SetXXX</code> methods do not
2490  Set the underlying database; instead the <code>SetRow</code> or
2491  <code>insertRow</code> methods are called to Set the database.
2492 
2493  @param columnIndex the first column is 1, the second is 2, ...
2494  @param x the new column value
2495 }
2496 procedure TZRowAccessor.SetUnicodeStream(ColumnIndex: Integer;
2497  Value: TStream);
2498 var
2499  IsNull: Boolean;
2500 begin
2501  IsNull := False;
2502 {$IFNDEF DISABLE_CHECKING}
2503  CheckColumnConvertion(ColumnIndex, stUnicodeStream);
2504 {$ENDIF}
2505  GetBlob(ColumnIndex, IsNull).SetStream(Value, True);
2506 end;
2507 
2508 {**
2509  Sets the blob wrapper object to the specified column.
2510  @param ColumnIndex the first column is 1, the second is 2, ...
2511  @param Value a blob wrapper object to be set.
2512 }
2513 procedure TZRowAccessor.SetBlob(ColumnIndex: Integer; Value: IZBlob);
2514 begin
2515 {$IFNDEF DISABLE_CHECKING}
2516  CheckColumnIndex(ColumnIndex);
2517  if not (FColumnTypes[ColumnIndex - 1] in [stAsciiStream, stBinaryStream,
2518  stUnicodeStream]) then
2519  begin
2520  raise EZSQLException.Create(
2521  Format(SCanNotAccessBlobRecord,
2522  [ColumnIndex, DefineColumnTypeName(FColumnTypes[ColumnIndex - 1])]));
2523  end;
2524 {$ENDIF}
2525 
2526  SetBlobObject(FBuffer, ColumnIndex, Value);
2527 end;
2528 
2529 {**
2530  Sets the blob wrapper object to the specified column.
2531  @param ColumnIndex the first column is 1, the second is 2, ...
2532  @param Value a ResultSet wrapper object to be set.
2533 }
2534 procedure TZRowAccessor.SetDataSet(ColumnIndex: Integer; Value: IZDataSet);
2535 var
2536  Ptr: PPointer;
2537  NullPtr: {$IFDEF WIN64}PBoolean{$ELSE}PByte{$ENDIF};
2538 begin
2539 {$IFNDEF DISABLE_CHECKING}
2540  CheckColumnIndex(ColumnIndex);
2541  if not (FColumnTypes[ColumnIndex - 1] = stDataSet) then
2542  begin
2543  raise EZSQLException.Create(
2544  Format(SCanNotAccessBlobRecord,
2545  [ColumnIndex, DefineColumnTypeName(FColumnTypes[ColumnIndex - 1])]));
2546  end;
2547 {$ENDIF}
2548 
2549  Ptr := PPointer(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1] + 1]);
2550  NullPtr := {$IFDEF WIN64}PBoolean{$ELSE}PByte{$ENDIF}(@FBuffer.Columns[FColumnOffsets[ColumnIndex - 1]]);
2551 
2552  {$IFNDEF FPC}
2553  if NullPtr^ = {$IFDEF WIN64}false{$ELSE}0{$ENDIF} then //M.A. if NullPtr^ = 0 then
2554  {$ELSE}
2555  if NullPtr^ = 0 then
2556  {$ENDIF}
2557  IZDataSet(Ptr^) := nil
2558  else
2559  Ptr^ := nil;
2560 
2561  IZDataSet(Ptr^) := Value;
2562 
2563  if Value <> nil then
2564  {$IFNDEF FPC}
2565  NullPtr^ := {$IFDEF WIN64}false{$ELSE}0{$ENDIF} //M.A. NullPtr^ := 0
2566  else
2567  NullPtr^ := {$IFDEF WIN64}true{$ELSE}1{$ENDIF}; //M.A. NullPtr^ := 1;
2568  {$ELSE}
2569  NullPtr^ := 0
2570  else
2571  NullPtr^ := 1;
2572  {$ENDIF}
2573 end;
2574 {**
2575  Sets the designated column with a <code>Variant</code> value.
2576  The <code>SetXXX</code> methods are used to Set column values in the
2577  current row or the insert row. The <code>SetXXX</code> methods do not
2578  Set the underlying database; instead the <code>SetRow</code> or
2579  <code>insertRow</code> methods are called to Set the database.
2580 
2581  @param columnIndex the first column is 1, the second is 2, ...
2582  @param x the new column value
2583 }
2584 procedure TZRowAccessor.SetValue(ColumnIndex: Integer; Value: TZVariant);
2585 begin
2586  case Value.VType of
2587  vtNull: SetNull(ColumnIndex);
2588  vtBoolean: SetBoolean(ColumnIndex, Value.VBoolean);
2589  vtInteger: SetLong(ColumnIndex, Value.VInteger);
2590  vtFloat: SetBigDecimal(ColumnIndex, Value.VFloat);
2591  vtBytes: SetBytes(ColumnIndex, Value.VBytes);
2592  vtString: SetString(ColumnIndex, Value.VString);
2593  vtUnicodeString: SetUnicodeString(ColumnIndex, Value.VUnicodeString);
2594  vtDateTime: SetTimestamp(ColumnIndex, Value.VDateTime);
2595  end;
2596 end;
2597 
2598 end.
2599