1 {*********************************************************}
3 { Zeos Database Objects }
4 { Dataset utility functions and classes }
6 { Originally written by Sergey Seroukhov }
8 {*********************************************************}
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
13 { License Agreement: }
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. }
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. }
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) }
46 { http://www.sourceforge.net/projects/zeoslib. }
49 { Zeos Development Group. }
50 {********************************************************@}
59 Types, Classes, SysUtils, {$IFDEF MSEgui}mclasses, mdb{$ELSE}Db{$ENDIF},
60 Contnrs, {$IFDEF WITH_UNITANSISTRINGS}AnsiStrings, {$ENDIF}
61 ZDbcIntfs, ZDbcCache, ZCompatibility, ZExpression, ZVariant, ZTokenizer;
64 Converts DBC Field Type to TDataset Field Type.
65 @param Value an initial DBC field type.
66 @return a converted TDataset field type.
68 function ConvertDbcToDatasetType(Value: TZSQLType): TFieldType;
71 Converts TDataset Field Type to DBC Field Type.
72 @param Value an initial TDataset field type.
73 @return a converted DBC field type.
75 function ConvertDatasetToDbcType(Value: TFieldType): TZSQLType;
78 Converts field definitions into column information objects.
79 @param Fields a collection of field definitions.
80 @return a collection of column information objects.
82 function ConvertFieldsToColumnInfo(Fields: TFields): TObjectList;
85 Fetches columns from specified resultset.
86 @param ResultSet a source resultset.
87 @param FieldsLookupTable a lookup table to define original index.
88 @param Fields a collection of field definitions.
89 @param RowAccessor a destination row accessor.
91 procedure FetchFromResultSet(ResultSet: IZResultSet;
92 const FieldsLookupTable: TIntegerDynArray; Fields: TFields;
93 RowAccessor: TZRowAccessor);
96 Posts columns from specified resultset.
97 @param ResultSet a source resultset.
98 @param FieldsLookupTable a lookup table to define original index.
99 @param Fields a collection of field definitions.
100 @param RowAccessor a destination row accessor.
102 procedure PostToResultSet(ResultSet: IZResultSet;
103 const FieldsLookupTable: TIntegerDynArray; Fields: TFields;
104 RowAccessor: TZRowAccessor);
107 Defines fields indices for the specified dataset.
108 @param DataSet a dataset object.
109 @param FieldNames a list of field names.
110 @param OnlyDataFields <code>True</code> if only data fields selected.
112 function DefineFields(DataSet: TDataset; const FieldNames: string;
113 var OnlyDataFields: Boolean): TObjectDynArray;
116 Defins a indices of filter fields.
117 @param Dataset a dataset object.
118 @param Expression a expression calculator.
119 @returns an array with field object references.
121 function DefineFilterFields(DataSet: TDataset;
122 Expression: IZExpression): TObjectDynArray;
125 Retrieves a set of specified field values.
126 @param FieldRefs an array with interested field object references.
127 @param ResultSet an initial result set object.
128 @param ResultValues a container for result values.
129 @return an array with field values.
131 procedure RetrieveDataFieldsFromResultSet(const FieldRefs: TObjectDynArray;
132 ResultSet: IZResultSet; var ResultValues: TZVariantDynArray);
135 Retrieves a set of specified field values.
136 @param FieldRefs an array with interested field object references.
137 @param FieldIndices an array with interested field indices.
138 @param RowAccessor a row accessor object.
139 @param ResultValues a container for result values.
140 @return an array with field values.
142 procedure RetrieveDataFieldsFromRowAccessor(const FieldRefs: TObjectDynArray;
143 const FieldIndices: TIntegerDynArray; RowAccessor: TZRowAccessor;
144 var ResultValues: TZVariantDynArray);
147 Copy a set of specified field values to variables.
148 @param Fields an array with interested field object references.
149 @param ResultSet an initial result set object.
150 @param Variables a list of variables.
152 procedure CopyDataFieldsToVars(const Fields: TObjectDynArray;
153 ResultSet: IZResultSet; Variables: IZVariablesList);
156 Prepares values for comparison by CompareFieldsFromResultSet.
157 @param FieldRefs an array with interested field object references.
158 @param DecodedKeyValues given values.
159 @param ResultSet a resultset to get field values.
160 @param PartialKey <code>True</code> if values should be started with the keys.
161 @param CaseInsensitive <code>True</code> if keys are case insensitive.
163 procedure PrepareValuesForComparison(const FieldRefs: TObjectDynArray;
164 var DecodedKeyValues: TZVariantDynArray; ResultSet: IZResultSet;
165 PartialKey: Boolean; CaseInsensitive: Boolean);
168 Compares row field values with the given ones.
169 @param KeyValues given values.
170 @param RowValues row field values.
171 @param PartialKey <code>True</code> if values should be started with the keys.
172 @param CaseInsensitive <code>True</code> if keys are case insensitive.
173 @return <code> if values are equal.
175 function CompareDataFields(const KeyValues, RowValues: TZVariantDynArray;
176 PartialKey: Boolean; CaseInsensitive: Boolean): Boolean;
179 Compares row field values with the given ones.
180 @param FieldRefs an array with interested field object references.
181 @param KeyValues given values.
182 @param RowValues row field values.
183 @param PartialKey <code>True</code> if values should be started with the keys.
184 @param CaseInsensitive <code>True</code> if keys are case insensitive.
185 @return <code> if values are equal.
187 function CompareFieldsFromResultSet(const FieldRefs: TObjectDynArray;
188 const KeyValues: TZVariantDynArray; ResultSet: IZResultSet; PartialKey: Boolean;
189 CaseInsensitive: Boolean): Boolean;
192 Defines a list of key field names.
193 @param Fields a collection of dataset fields.
194 @return a list of key field names.
196 function DefineKeyFields(Fields: TFields): string;
199 Converts datetime value into TDataset internal presentation.
200 @param DataType a type of date-time field.
201 @param Data a data which contains a value.
202 @param Buffer a field buffer pointer
204 procedure DateTimeToNative(DataType: TFieldType; Data: TDateTime; Buffer: Pointer);
207 Converts date times from TDataset internal presentation into datetime value.
208 @param DataType a type of date-time field.
209 @param Buffer a field buffer pointer
210 @return a data which contains a value.
212 function NativeToDateTime(DataType: TFieldType; Buffer: Pointer): TDateTime;
215 Compare values from two key fields.
216 @param Field1 the first field object.
217 @param ResultSet the resultset to read the first field value.
218 @param Field2 the second field object.
220 function CompareKeyFields(Field1: TField; ResultSet: IZResultSet;
221 Field2: TField): Boolean;
224 Defins a indices and directions for sorted fields.
225 @param Dataset a dataset object.
226 @param SortedFields an encoded fields for sorting in the format
227 <Field Name> [ASC | DESC] [, ...]
228 @param FieldRefs a decoded field object references.
229 @param FieldDirs a decoded field directions.
230 @param OnlyDataFields <code>True</code> if only data fields selected.
232 procedure DefineSortedFields(DataSet: TDataset;
233 const SortedFields: string; var FieldRefs: TObjectDynArray;
234 var FieldDirs: TBooleanDynArray; var OnlyDataFields: Boolean);
237 Creates a fields lookup table to define fixed position
238 of the field in dataset.
239 @param Fields a collection of TDataset fields in initial order.
240 @returns a fields lookup table.
242 function CreateFieldsLookupTable(Fields: TFields): TIntegerDynArray;
245 Defines an original field index in the dataset.
246 @param FieldsLookupTable a lookup table to define original index.
247 @param Field a TDataset field object.
248 @returns an original fields index or -1 otherwise.
250 function DefineFieldIndex(const FieldsLookupTable: TIntegerDynArray;
251 Field: TField): Integer;
254 Defines an original field indices in the dataset.
255 @param FieldsLookupTable a lookup table to define original index.
256 @param FieldRefs a TDataset field object references.
257 @returns an array with original fields indices.
259 function DefineFieldIndices(const FieldsLookupTable: TIntegerDynArray;
260 const FieldRefs: TObjectDynArray): TIntegerDynArray;
263 Splits up a qualified object name into pieces. Catalog, schema
266 procedure SplitQualifiedObjectName(QualifiedName: string;
267 var Catalog, Schema, ObjectName: string); overload;
270 Splits up a qualified object name into pieces. Catalog, schema
273 procedure SplitQualifiedObjectName(QualifiedName: string;
274 const SupportsCatalogs, SupportsSchemas: Boolean;
275 var Catalog, Schema, ObjectName: string); overload;
278 Assigns a Statement value from a TParam
279 @param Index the index of Statement.SetParam(Idex..);
280 @param Statement the PrepredStatement where the values have been assigned
281 @param Param the TParam where the value is assigned from
283 procedure SetStatementParam(Index: Integer;
284 Statement: IZPreparedStatement; Param: TParam);
286 {** Common variables. }
288 CommonTokenizer: IZTokenizer;
293 ZMessages, ZGenericSqlToken, ZDbcResultSetMetadata, ZAbstractRODataset,
295 {$IFNDEF WITHOUT_VARBYTESASSTRING}, ZSysUtils{$ENDIF}
296 {$IFDEF WITH_INLINE_ANSISTRLCOMP}, Windows{$ENDIF};
299 Converts DBC Field Type to TDataset Field Type.
300 @param Value an initial DBC field type.
301 @return a converted TDataset field type.
303 function ConvertDbcToDatasetType(Value: TZSQLType): TFieldType;
309 Result := ftSmallInt;
313 Result := ftLargeInt;
314 stFloat, stDouble, stBigDecimal:
318 stBytes{$IFNDEF WITH_FTGUID}, stGUID{$ENDIF}:
329 Result := ftDateTime;
335 Result := ftWideString;
337 Result := {$IFNDEF WITH_WIDEMEMO}ftWideString{$ELSE}ftWideMemo{$ENDIF};
338 {$IFDEF WITH_FTDATASETSUPPORT}
348 Converts TDataset Field Type to DBC Field Type.
349 @param Value an initial TDataset field type.
350 @return a converted DBC field type.
352 function ConvertDatasetToDbcType(Value: TFieldType): TZSQLType;
359 ftInteger, ftAutoInc:
366 Result := stBigDecimal;
376 Result := stTimestamp;
378 Result := stAsciiStream;
380 Result := stBinaryStream;
382 Result := stUnicodeString;
387 {$IFDEF WITH_WIDEMEMO}
389 Result := stUnicodeStream;
391 {$IFDEF WITH_FTDATASETSUPPORT}
401 Converts field definitions into column information objects.
402 @param Fields a collection of field definitions.
403 @return a collection of column information objects.
405 function ConvertFieldsToColumnInfo(Fields: TFields): TObjectList;
409 ColumnInfo: TZColumnInfo;
411 Result := TObjectList.Create(True);
412 for I := 0 to Fields.Count - 1 do
414 Current := Fields[I];
415 ColumnInfo := TZColumnInfo.Create;
417 ColumnInfo.ColumnType := ConvertDatasetToDbcType(Current.DataType);
418 ColumnInfo.ColumnName := Current.FieldName;
419 ColumnInfo.Precision := Current.Size;
420 //This is a hack for stUnicodeStream because there is only ftWideString for both type
421 if ColumnInfo.ColumnType = stUnicodeString then
422 if Current.Size > 10240 then
423 ColumnInfo.ColumnType := stUnicodeStream;
424 ColumnInfo.Scale := 0;
425 ColumnInfo.ColumnLabel := Current.DisplayName;
426 ColumnInfo.ColumnDisplaySize := Current.DisplayWidth;
427 ColumnInfo.DefaultExpression := Current.DefaultExpression;
429 Result.Add(ColumnInfo);
434 Fetches columns from specified resultset.
435 @param ResultSet a source resultset.
436 @param FieldsLookupTable a lookup table to define original index.
437 @param Fields a collection of field definitions.
438 @param RowAccessor a destination row accessor.
440 procedure FetchFromResultSet(ResultSet: IZResultSet;
441 const FieldsLookupTable: TIntegerDynArray; Fields: TFields;
442 RowAccessor: TZRowAccessor);
444 I, FieldIndex: Integer;
446 ColumnIndex, ColumnCount: Integer;
448 RowAccessor.RowBuffer.Index := ResultSet.GetRow;
449 ColumnCount := ResultSet.GetMetadata.GetColumnCount;
451 for I := 0 to Fields.Count - 1 do
453 Current := Fields[I];
454 if not (Current.FieldKind in [fkData, fkInternalCalc]) then
457 ColumnIndex := Current.FieldNo;
458 FieldIndex := DefineFieldIndex(FieldsLookupTable, Current);
459 if (ColumnIndex < 1) or (ColumnIndex > ColumnCount) then
462 case Current.DataType of
464 RowAccessor.SetBoolean(FieldIndex, ResultSet.GetBoolean(ColumnIndex));
466 RowAccessor.SetShort(FieldIndex, ResultSet.GetShort(ColumnIndex));
467 ftInteger, ftAutoInc:
468 RowAccessor.SetInt(FieldIndex, ResultSet.GetInt(ColumnIndex));
470 RowAccessor.SetDouble(FieldIndex, ResultSet.GetDouble(ColumnIndex));
472 RowAccessor.SetLong(FieldIndex, ResultSet.GetLong(ColumnIndex));
474 RowAccessor.SetBigDecimal(FieldIndex, ResultSet.GetBigDecimal(ColumnIndex));
476 // gto: do we need PChar here?
477 //RowAccessor.SetPChar(FieldIndex, ResultSet.GetPChar(ColumnIndex));
478 RowAccessor.SetString(FieldIndex, ResultSet.GetString(ColumnIndex));
480 RowAccessor.SetUnicodeString(FieldIndex, ResultSet.GetUnicodeString(ColumnIndex));
481 ftBytes{$IFDEF WITH_FTGUID}, ftGuid{$ENDIF}:
482 RowAccessor.SetBytes(FieldIndex, ResultSet.GetBytes(ColumnIndex));
484 RowAccessor.SetDate(FieldIndex, ResultSet.GetDate(ColumnIndex));
486 RowAccessor.SetTime(FieldIndex, ResultSet.GetTime(ColumnIndex));
488 RowAccessor.SetTimestamp(FieldIndex, ResultSet.GetTimestamp(ColumnIndex));
489 ftMemo, ftBlob {$IFDEF WITH_WIDEMEMO}, ftWideMemo{$ENDIF}:
490 RowAccessor.SetBlob(FieldIndex, ResultSet.GetBlob(ColumnIndex));
491 {$IFDEF WITH_FTDATASETSUPPORT}
493 RowAccessor.SetDataSet(FieldIndex, ResultSet.GetDataSet(ColumnIndex));
497 if ResultSet.WasNull then
498 RowAccessor.SetNull(FieldIndex);
503 Posts columns from specified resultset.
504 @param ResultSet a source resultset.
505 @param FieldsLookupTable a lookup table to define original index.
506 @param Fields a collection of field definitions.
507 @param RowAccessor a destination row accessor.
509 procedure PostToResultSet(ResultSet: IZResultSet;
510 const FieldsLookupTable: TIntegerDynArray; Fields: TFields;
511 RowAccessor: TZRowAccessor);
513 I, FieldIndex: Integer;
516 ColumnIndex, ColumnCount: Integer;
520 RowAccessor.RowBuffer.Index := ResultSet.GetRow;
521 ColumnCount := ResultSet.GetMetadata.GetColumnCount;
523 for I := 0 to Fields.Count - 1 do
525 Current := Fields[I];
526 if Current.FieldKind <> fkData then
529 ColumnIndex := Current.FieldNo;
530 FieldIndex := DefineFieldIndex(FieldsLookupTable, Current);
531 if (ColumnIndex < 1) or (ColumnIndex > ColumnCount) then
534 // if (Current.Required = True) and (WasNull = True) then
535 // raise EZDatabaseError.Create(Format(SFieldCanNotBeNull, [Current.FieldName]));
536 case Current.DataType of
538 ResultSet.UpdateBoolean(ColumnIndex, RowAccessor.GetBoolean(FieldIndex, WasNull));
540 ResultSet.UpdateShort(ColumnIndex, RowAccessor.GetShort(FieldIndex, WasNull));
541 ftInteger, ftAutoInc:
542 ResultSet.UpdateInt(ColumnIndex, RowAccessor.GetInt(FieldIndex, WasNull));
544 ResultSet.UpdateDouble(ColumnIndex, RowAccessor.GetDouble(FieldIndex, WasNull));
546 ResultSet.UpdateLong(ColumnIndex, RowAccessor.GetLong(FieldIndex, WasNull));
548 ResultSet.UpdateBigDecimal(ColumnIndex,
549 RowAccessor.GetBigDecimal(FieldIndex, WasNull));
551 ResultSet.UpdateString(ColumnIndex, RowAccessor.GetString(FieldIndex, WasNull));
553 ResultSet.UpdateUnicodeString(ColumnIndex,
554 RowAccessor.GetUnicodeString(FieldIndex, WasNull));
555 ftBytes{$IFDEF WITH_FTGUID}, ftGuid{$ENDIF}:
556 ResultSet.UpdateBytes(ColumnIndex, RowAccessor.GetBytes(FieldIndex, WasNull));
558 ResultSet.UpdateDate(ColumnIndex, RowAccessor.GetDate(FieldIndex, WasNull));
560 ResultSet.UpdateTime(ColumnIndex, RowAccessor.GetTime(FieldIndex, WasNull));
562 ResultSet.UpdateTimestamp(ColumnIndex,
563 RowAccessor.GetTimestamp(FieldIndex, WasNull));
566 Stream := RowAccessor.GetAsciiStream(FieldIndex, WasNull);
568 ResultSet.UpdateAsciiStream(ColumnIndex, Stream);
573 {$IFDEF WITH_WIDEMEMO}
576 Stream := RowAccessor.GetUnicodeStream(FieldIndex, WasNull);
578 ResultSet.UpdateUnicodeStream(ColumnIndex, Stream);
586 Stream := RowAccessor.GetBinaryStream(FieldIndex, WasNull);
588 ResultSet.UpdateBinaryStream(ColumnIndex, Stream);
593 {$IFDEF WITH_FTDATASETSUPPORT}
595 ResultSet.UpdateDataSet(ColumnIndex, RowAccessor.GetDataSet(FieldIndex, WasNull));
601 // Performance thing :
602 // The default expression will only be set when necessary : if the value really IS null
603 Resultset.UpdateDefaultExpression(ColumnIndex, RowAccessor.GetColumnDefaultExpression(FieldIndex));
604 ResultSet.UpdateNull(ColumnIndex);
610 Defines fields indices for the specified dataset.
611 @param DataSet a dataset object.
612 @param FieldNames a list of field names.
613 @param OnlyDataFields <code>True</code> if only data fields selected.
615 function DefineFields(DataSet: TDataset; const FieldNames: string;
616 var OnlyDataFields: Boolean): TObjectDynArray;
620 TokenType: TZTokenType;
625 OnlyDataFields := True;
627 SetLength(Result, FieldCount);
628 Tokens := CommonTokenizer.TokenizeBufferToList(FieldNames,
629 [toSkipEOF, toSkipWhitespaces, toUnifyNumbers, toDecodeStrings]);
632 for I := 0 to Tokens.Count - 1 do
634 TokenType := TZTokenType({$IFDEF oldFPC}Pointer({$ENDIF}
635 Tokens.Objects[I]{$IFDEF oldFPC}){$ENDIF});
636 TokenValue := Tokens[I];
639 if TokenType in [ttWord, ttQuoted] then
641 Field := DataSet.FieldByName(TokenValue);
643 else if (TokenType = ttNumber)
644 and (StrToIntDef(TokenValue, 0) < Dataset.Fields.Count) then
646 Field := Dataset.Fields[StrToIntDef(TokenValue, 0)];
648 else if (TokenValue <> ',') and (TokenValue <> ';') then
650 raise EZDatabaseError.Create(Format(SIncorrectSymbol, [TokenValue]));
655 OnlyDataFields := OnlyDataFields and (Field.FieldKind = fkData);
657 SetLength(Result, FieldCount);
658 Result[FieldCount - 1] := Field;
665 if Length(Result) = 0 then
670 Defins a indices of filter fields.
671 @param Dataset a dataset object.
672 @param Expression a expression calculator.
673 @returns an array with field object references.
675 function DefineFilterFields(DataSet: TDataset;
676 Expression: IZExpression): TObjectDynArray;
681 if Expression.Expression <> '' then
683 SetLength(Result, Expression.DefaultVariables.Count);
684 for I := 0 to Expression.DefaultVariables.Count - 1 do
686 Current := DataSet.FindField(Expression.DefaultVariables.Names[I]);
687 if Current <> nil then
694 SetLength(Result, 0);
698 Retrieves a set of specified field values.
699 @param FieldRefs an array with interested field object references.
700 @param ResultSet an initial result set object.
701 @param ResultValues a container for result values.
702 @return an array with field values.
704 procedure RetrieveDataFieldsFromResultSet(const FieldRefs: TObjectDynArray;
705 ResultSet: IZResultSet; var ResultValues: TZVariantDynArray);
707 I, ColumnIndex: Integer;
709 for I := 0 to High(FieldRefs) do
711 ColumnIndex := TField(FieldRefs[I]).FieldNo;
712 if ColumnIndex >= 0 then
714 case TField(FieldRefs[I]).DataType of
716 DefVarManager.SetAsString(ResultValues[I],
717 ResultSet.GetString(ColumnIndex));
719 DefVarManager.SetAsBoolean(ResultValues[I],
720 ResultSet.GetBoolean(ColumnIndex));
721 ftSmallInt, ftInteger, ftAutoInc:
722 DefVarManager.SetAsInteger(ResultValues[I],
723 ResultSet.GetInt(ColumnIndex));
725 DefVarManager.SetAsFloat(ResultValues[I],
726 ResultSet.GetDouble(ColumnIndex));
728 DefVarManager.SetAsInteger(ResultValues[I],
729 ResultSet.GetLong(ColumnIndex));
731 DefVarManager.SetAsFloat(ResultValues[I],
732 ResultSet.GetBigDecimal(ColumnIndex));
733 ftDate, ftTime, ftDateTime:
734 DefVarManager.SetAsDateTime(ResultValues[I],
735 ResultSet.GetTimestamp(ColumnIndex));
737 DefVarManager.SetAsUnicodeString(ResultValues[I],
738 ResultSet.GetUnicodeString(ColumnIndex));
740 DefVarManager.SetAsString(ResultValues[I],
741 ResultSet.GetString(ColumnIndex));
743 if ResultSet.WasNull then
744 ResultValues[I] := NullVariant;
747 ResultValues[I] := NullVariant;
752 Retrieves a set of specified field values.
753 @param FieldRefs an array with interested field object references.
754 @param FieldIndices an array with interested field indices.
755 @param RowAccessor a row accessor object.
756 @param ResultValues a container for result values.
757 @return an array with field values.
759 procedure RetrieveDataFieldsFromRowAccessor(const FieldRefs: TObjectDynArray;
760 const FieldIndices: TIntegerDynArray; RowAccessor: TZRowAccessor;
761 var ResultValues: TZVariantDynArray);
764 ColumnIndex: Integer;
768 for I := 0 to High(FieldRefs) do
770 ColumnIndex := FieldIndices[I];
771 case TField(FieldRefs[I]).DataType of
773 DefVarManager.SetAsString(ResultValues[I],
774 RowAccessor.GetString(ColumnIndex, WasNull));
776 DefVarManager.SetAsBoolean(ResultValues[I],
777 RowAccessor.GetBoolean(ColumnIndex, WasNull));
778 ftSmallInt, ftInteger, ftAutoInc:
779 DefVarManager.SetAsInteger(ResultValues[I],
780 RowAccessor.GetInt(ColumnIndex, WasNull));
782 DefVarManager.SetAsFloat(ResultValues[I],
783 RowAccessor.GetDouble(ColumnIndex, WasNull));
785 DefVarManager.SetAsInteger(ResultValues[I],
786 RowAccessor.GetLong(ColumnIndex, WasNull));
788 DefVarManager.SetAsFloat(ResultValues[I],
789 RowAccessor.GetBigDecimal(ColumnIndex, WasNull));
790 ftDate, ftTime, ftDateTime:
791 DefVarManager.SetAsDateTime(ResultValues[I],
792 RowAccessor.GetTimestamp(ColumnIndex, WasNull));
794 DefVarManager.SetAsUnicodeString(ResultValues[I],
795 RowAccessor.GetUnicodeString(ColumnIndex, WasNull));
797 DefVarManager.SetAsString(ResultValues[I],
798 RowAccessor.GetString(ColumnIndex, WasNull));
801 ResultValues[I] := NullVariant;
806 Copy a set of specified field values to variables.
807 @param Fields an array with interested field object references.
808 @param ResultSet an initial result set object.
809 @param Variables a list of variables.
812 {$HINTS OFF} //Temp seems not to be init...
814 procedure CopyDataFieldsToVars(const Fields: TObjectDynArray;
815 ResultSet: IZResultSet; Variables: IZVariablesList);
817 I, ColumnIndex: Integer;
820 for I := 0 to Length(Fields) - 1 do
822 if Fields[I] = nil then
825 ColumnIndex := TField(Fields[I]).FieldNo;
826 if not ResultSet.IsNull(ColumnIndex) then
828 case TField(Fields[I]).DataType of
830 DefVarManager.SetAsBoolean(Temp, ResultSet.GetBoolean(ColumnIndex));
831 ftSmallInt, ftInteger, ftAutoInc:
832 DefVarManager.SetAsInteger(Temp, ResultSet.GetInt(ColumnIndex));
834 DefVarManager.SetAsFloat(Temp, ResultSet.GetDouble(ColumnIndex));
836 DefVarManager.SetAsInteger(Temp, ResultSet.GetLong(ColumnIndex));
838 DefVarManager.SetAsFloat(Temp, ResultSet.GetBigDecimal(ColumnIndex));
840 DefVarManager.SetAsDateTime(Temp, ResultSet.GetDate(ColumnIndex));
842 DefVarManager.SetAsDateTime(Temp, ResultSet.GetTime(ColumnIndex));
844 DefVarManager.SetAsDateTime(Temp, ResultSet.GetTimestamp(ColumnIndex));
846 DefVarManager.SetAsUnicodeString(Temp,
847 ResultSet.GetUnicodeString(ColumnIndex));
849 DefVarManager.SetAsString(Temp, ResultSet.GetString(ColumnIndex));
851 Variables.Values[I] := Temp;
855 DefVarManager.SetNull(Temp);
856 Variables.Values[I] := Temp;
865 Compares row field values with the given ones.
866 @param KeyValues given values.
867 @param RowValues row field values.
868 @param PartialKey <code>True</code> if values should be started with the keys.
869 @param CaseInsensitive <code>True</code> if keys are case insensitive.
870 @return <code> if values are equal.
872 function CompareDataFields(const KeyValues, RowValues: TZVariantDynArray;
873 PartialKey: Boolean; CaseInsensitive: Boolean): Boolean;
876 Value1, Value2: AnsiString;
877 WValue1, WValue2: WideString;
880 for I := 0 to High(KeyValues) do
882 case KeyValues[I].VType of
885 if CaseInsensitive then
887 WValue1 := WideUpperCase(SoftVarManager.GetAsUnicodeString(KeyValues[I]));
888 WValue2 := WideUpperCase(SoftVarManager.GetAsUnicodeString(RowValues[I]));
892 Result := SysUtils.AnsiStrLComp(PWideChar(WValue2), PWideChar(WValue1), Length(WValue1)) = 0;
894 Value1 := AnsiString(WValue1);
895 Value2 := AnsiString(WValue2);
896 Result := AnsiStrLComp(PAnsiChar(Value2), PAnsiChar(Value1), Length(Value1)) = 0;
900 Result := WValue1 = WValue2
904 WValue1 := SoftVarManager.GetAsUnicodeString(KeyValues[I]);
905 WValue1 := SoftVarManager.GetAsUnicodeString(RowValues[I]);
909 Result := SysUtils.AnsiStrLComp(PWideChar(WValue2), PWideChar(WValue1), Length(WValue1)) = 0;
911 Value1 := AnsiString(WValue1);
912 Value2 := AnsiString(WValue2);
913 Result := AnsiStrLComp(PAnsiChar(Value2), PAnsiChar(Value1), Length(Value1)) = 0;
917 Result := SoftVarManager.Compare(KeyValues[I], RowValues[I]) = 0;
922 if CaseInsensitive then
924 Value1 := AnsiString(AnsiUpperCase(SoftVarManager.GetAsString(KeyValues[I])));
925 Value2 := AnsiString(AnsiUpperCase(SoftVarManager.GetAsString(RowValues[I])));
928 Result := {$IFDEF WITH_ANSISTRLCOMP_DEPRECATED}AnsiStrings.{$ENDIF}AnsiStrLComp(PAnsiChar(Value2), PAnsiChar(Value1), Length(Value1)) = 0
930 Result := Value1 = Value2
934 Value1 := AnsiString(SoftVarManager.GetAsString(KeyValues[I]));
935 Value2 := AnsiString(SoftVarManager.GetAsString(RowValues[I]));
937 Result := {$IFDEF WITH_ANSISTRLCOMP_DEPRECATED}AnsiStrings.{$ENDIF}AnsiStrLComp(PAnsiChar(Value2), PAnsiChar(Value1), Length(Value1)) = 0
939 Result := SoftVarManager.Compare(KeyValues[I], RowValues[I]) = 0;
950 Prepares values for comparison by CompareFieldsFromResultSet.
951 @param FieldRefs an array with interested field object references.
952 @param DecodedKeyValues given values.
953 @param ResultSet a resultset to get field values.
954 @param PartialKey <code>True</code> if values should be started with the keys.
955 @param CaseInsensitive <code>True</code> if keys are case insensitive.
957 procedure PrepareValuesForComparison(const FieldRefs: TObjectDynArray;
958 var DecodedKeyValues: TZVariantDynArray; ResultSet: IZResultSet;
959 PartialKey: Boolean; CaseInsensitive: Boolean);
963 CurrentType : TZSQLType;
965 { Preprocesses cycle variables. }
966 for I := 0 to High(FieldRefs) do
968 Current := TField(FieldRefs[I]);
970 if DecodedKeyValues[I].VType = vtNull then
973 CurrentType := ResultSet.GetMetadata.GetColumnType(Current.FieldNo);
977 if CurrentType = stUnicodeString then
979 DecodedKeyValues[I] := SoftVarManager.Convert(
980 DecodedKeyValues[I], vtUnicodeString);
981 if CaseInsensitive then
983 if DecodedKeyValues[I].VType = vtString then
985 DecodedKeyValues[I].VString := Uppercase(DecodedKeyValues[I].VString);
986 DecodedKeyValues[I].VUnicodeString := DecodedKeyValues[I].VString;
990 DecodedKeyValues[I].VUnicodeString :=
991 WideUpperCase(DecodedKeyValues[I].VUnicodeString);
997 DecodedKeyValues[I] := SoftVarManager.Convert(
998 DecodedKeyValues[I], vtString);
999 if CaseInsensitive then
1001 {$IFDEF LAZARUSUTF8HACK} // Is this correct? Assumes the Lazarus convention all strings are UTF8. But is that
1002 // true in this point, or should that be converted higher up?
1003 DecodedKeyValues[I].VString :=
1004 WideUpperCase(UTF8Decode (DecodedKeyValues[I].VString));
1006 DecodedKeyValues[I].VString :=
1007 AnsiUpperCase(DecodedKeyValues[I].VString);
1016 DecodedKeyValues[I] := SoftVarManager.Convert(
1017 DecodedKeyValues[I], vtBoolean);
1018 stByte, stShort, stInteger, stLong:
1019 DecodedKeyValues[I] := SoftVarManager.Convert(
1020 DecodedKeyValues[I], vtInteger);
1021 stFloat, stDouble, stBigDecimal:
1022 DecodedKeyValues[I] := SoftVarManager.Convert(
1023 DecodedKeyValues[I], vtFloat);
1026 if CaseInsensitive then
1028 if DecodedKeyValues[I].VType = vtString then
1030 DecodedKeyValues[I].VString := Uppercase(DecodedKeyValues[I].VString);
1031 DecodedKeyValues[I].VUnicodeString := DecodedKeyValues[I].VString;
1035 DecodedKeyValues[I].VUnicodeString :=
1036 WideUpperCase(DecodedKeyValues[I].VUnicodeString);
1041 DecodedKeyValues[I] := SoftVarManager.Convert(
1042 DecodedKeyValues[I], vtUnicodeString);
1045 stDate, stTime, stTimestamp:
1046 DecodedKeyValues[I] := SoftVarManager.Convert(
1047 DecodedKeyValues[I], vtDateTime);
1049 if CaseInsensitive then
1051 DecodedKeyValues[I] := SoftVarManager.Convert(
1052 DecodedKeyValues[I], vtString);
1053 {$IFDEF LAZARUSUTF8HACK}
1054 // Is this correct? Assumes the Lazarus convention all strings are UTF8. But is that
1055 // true in this point, or should that be converted higher up?
1056 DecodedKeyValues[I].VString :=
1057 WideUpperCase(UTF8Decode (DecodedKeyValues[I].VString));
1059 DecodedKeyValues[I].VString :=
1060 AnsiUpperCase(DecodedKeyValues[I].VString);
1065 DecodedKeyValues[I] := SoftVarManager.Convert(
1066 DecodedKeyValues[I], vtString);
1074 Compares row field values with the given ones.
1075 @param FieldRefs an array with interested field object references.
1076 @param KeyValues given values.
1077 @param ResultSet a resultset to get field values.
1078 @param PartialKey <code>True</code> if values should be started with the keys.
1079 @param CaseInsensitive <code>True</code> if keys are case insensitive.
1080 @return <code> if values are equal.
1082 function CompareFieldsFromResultSet(const FieldRefs: TObjectDynArray;
1083 const KeyValues: TZVariantDynArray; ResultSet: IZResultSet; PartialKey: Boolean;
1084 CaseInsensitive: Boolean): Boolean;
1087 ColumnIndex: Integer;
1088 AValue1, AValue2: AnsiString;
1089 WValue1, WValue2: WideString;
1090 CurrentType : TZSQLType;
1093 for I := 0 to High(KeyValues) do
1095 ColumnIndex := TField(FieldRefs[I]).FieldNo;
1097 if KeyValues[I].VType = vtNull then
1099 Result := ResultSet.IsNull(ColumnIndex);
1105 CurrentType := ResultSet.GetMetadata.GetColumnType(ColumnIndex);
1109 if CurrentType = stUnicodeString then
1111 WValue1 := KeyValues[I].VUnicodeString;
1112 WValue2 := ResultSet.GetUnicodeString(ColumnIndex);
1114 if CaseInsensitive then
1115 WValue2 := WideUpperCase(WValue2);
1117 Result := SysUtils.AnsiStrLComp(PWideChar(WValue2), PWideChar(WValue1), Length(WValue1)) = 0;
1119 AValue1 := UTF8ToAnsi(UTF8Encode(WValue1));
1120 AValue2 := UTF8ToAnsi(UTF8Encode(WValue2));
1121 Result := AnsiStrLComp(PAnsiChar(AValue2), PAnsiChar(AValue1), Length(AValue1)) = 0;
1126 AValue1 := AnsiString(KeyValues[I].VString);
1127 if (ResultSet.GetConSettings.ClientCodePage^.Encoding = ceAnsi)
1128 or (ResultSet.GetConSettings.AutoEncode and ( ResultSet.GetConSettings.CTRL_CP <> 65001 )) then
1129 AValue2 := AnsiString(ResultSet.GetString(ColumnIndex))
1131 AValue2 := AnsiString({$IFNDEF UNICODE}UTF8ToAnsi{$ENDIF}(ResultSet.GetString(ColumnIndex)));
1133 if CaseInsensitive then
1134 AValue2 := {$IFDEF WITH_UNITANSISTRINGS}AnsiStrings.{$ENDIF}AnsiUpperCase(AValue2);
1135 Result := {$IFDEF WITH_ANSISTRLCOMP_DEPRECATED}AnsiStrings.{$ENDIF}AnsiStrLComp(PAnsiChar(AValue2), PAnsiChar(AValue1), Length(AValue1)) = 0;
1144 Result := KeyValues[I].VBoolean =
1145 ResultSet.GetBoolean(ColumnIndex);
1152 Result := KeyValues[I].VInteger =
1153 ResultSet.GetLong(ColumnIndex);
1156 Result := Abs(KeyValues[I].VFloat -
1157 ResultSet.GetBigDecimal(ColumnIndex)) < FLOAT_COMPARE_PRECISION_SINGLE;
1161 Result := Abs(KeyValues[I].VFloat -
1162 ResultSet.GetBigDecimal(ColumnIndex)) < FLOAT_COMPARE_PRECISION;
1168 Result := KeyValues[I].VDateTime =
1169 ResultSet.GetTimestamp(ColumnIndex);
1173 if CaseInsensitive then
1175 Result := KeyValues[I].VUnicodeString =
1176 WideUpperCase(ResultSet.GetUnicodeString(ColumnIndex));
1180 Result := KeyValues[I].VUnicodeString =
1181 ResultSet.GetUnicodeString(ColumnIndex);
1185 if CaseInsensitive then
1187 {$IFDEF LAZARUSUTF8HACK}
1188 Result := KeyValues[I].VString =
1189 AnsiUpperCase (Utf8ToAnsi(ResultSet.GetString(ColumnIndex)));
1191 Result := KeyValues[I].VString =
1192 AnsiUpperCase(ResultSet.GetString(ColumnIndex));
1197 Result := KeyValues[I].VString =
1198 ResultSet.GetString(ColumnIndex);
1203 Result := Result and not ResultSet.WasNull;
1210 Defines a list of key field names.
1211 @param Fields a collection of dataset fields.
1212 @return a list of key field names.
1214 function DefineKeyFields(Fields: TFields): string;
1220 for I := 0 to Fields.Count - 1 do
1222 if (Fields[I].FieldKind = fkData)
1223 and not (Fields[I].DataType in [ftBlob, ftMemo, ftBytes {$IFDEF WITH_WIDEMEMO}, ftWideMemo{$ENDIF}]) then
1225 if Result <> '' then
1226 Result := Result + ',';
1227 Temp := Fields[I].FieldName;
1228 if (Pos(' ', Temp) > 0) or (Pos('-', Temp) > 0) or (Pos('.', Temp) > 0) then
1229 Temp := '"' + Temp + '"';
1230 Result := Result + Temp;
1236 Converts datetime value into TDataset internal presentation.
1237 @param DataType a type of date-time field.
1238 @param Data a data which contains a value.
1239 @param Buffer a field buffer pointer
1241 procedure DateTimeToNative(DataType: TFieldType; Data: TDateTime;
1244 TimeStamp: TTimeStamp;
1246 TimeStamp := DateTimeToTimeStamp(Data);
1248 ftDate: Integer(Buffer^) := TimeStamp.Date;
1249 ftTime: Integer(Buffer^) := TimeStamp.Time;
1251 TDateTime(Buffer^) := TimeStampToMSecs(TimeStamp);
1256 Converts date times from TDataset internal presentation into datetime value.
1257 @param DataType a type of date-time field.
1258 @param Buffer a field buffer pointer
1259 @return a data which contains a value.
1261 function NativeToDateTime(DataType: TFieldType; Buffer: Pointer): TDateTime;
1264 TimeStamp: TTimeStamp;
1269 TimeStamp.Time := 0;
1270 TimeStamp.Date := Integer(Buffer^);
1274 {$IFDEF WITH_FPC_FTTIME_BUG}
1275 TimeStamp := DateTimeToTimeStamp(TDateTime(Buffer^));
1277 TimeStamp.Time := Integer(Buffer^);
1278 TimeStamp.Date := DateDelta;
1283 {$IF not defined(cpui386) and defined(FPC)}
1284 TimeStamp := MSecsToTimeStamp(System.Trunc(Int(TDateTime(Buffer^))));
1286 TimeStamp := MSecsToTimeStamp(TDateTime(Buffer^));
1289 TimeStamp.Time := 0;
1290 TimeStamp.Date := 0;
1293 Result := TimeStampToDateTime(TimeStamp);
1296 Result := TDateTime(Buffer^);
1301 Compare values from two key fields.
1302 @param Field1 the first field object.
1303 @param ResultSet the resultset to read the first field value.
1304 @param Field2 the second field object.
1306 function CompareKeyFields(Field1: TField; ResultSet: IZResultSet;
1307 Field2: TField): Boolean;
1310 if Field1.FieldNo >= 1 then
1312 case Field1.DataType of
1314 Result := ResultSet.GetBoolean(Field1.FieldNo) = Field2.AsBoolean;
1315 ftSmallInt, ftInteger, ftAutoInc:
1316 Result := ResultSet.GetInt(Field1.FieldNo) = Field2.AsInteger;
1319 Result := Abs(ResultSet.GetFloat(Field1.FieldNo)
1320 - Field2.AsFloat) < FLOAT_COMPARE_PRECISION;
1324 if Field2 is TLargeIntField then
1325 Result := ResultSet.GetLong(Field1.FieldNo)
1326 = TLargeIntField(Field2).AsLargeInt
1328 Result := ResultSet.GetInt(Field1.FieldNo) = Field2.AsInteger;
1332 Result := Abs(ResultSet.GetBigDecimal(Field1.FieldNo)
1333 - Field2.{$IFDEF WITH_ASCURRENCY}AsCurrency{$ELSE}AsFloat{$ENDIF})
1334 < FLOAT_COMPARE_PRECISION;
1337 Result := ResultSet.GetDate(Field1.FieldNo) = Field2.AsDateTime;
1339 Result := ResultSet.GetTime(Field1.FieldNo) = Field2.AsDateTime;
1341 Result := ResultSet.GetTimestamp(Field1.FieldNo) = Field2.AsDateTime;
1343 Result := ResultSet.GetUnicodeString(Field1.FieldNo) =
1344 Field2.{$IFDEF WITH_ASVARIANT}AsVariant{$ELSE}AsString{$ENDIF};
1346 Result := ResultSet.GetString(Field1.FieldNo) = Field2.AsString;
1352 Defins a indices and directions for sorted fields.
1353 @param Dataset a dataset object.
1354 @param SortedFields an encoded fields for sorting in the format
1355 <Field Name> [ASC | DESC] [, ...]
1356 @param FieldRefs a decoded field object references.
1357 @param FieldDirs a decoded field directions.
1358 @param OnlyDataFields <code>True</code> if only data fields selected.
1360 procedure DefineSortedFields(DataSet: TDataset;
1361 const SortedFields: string; var FieldRefs: TObjectDynArray;
1362 var FieldDirs: TBooleanDynArray; var OnlyDataFields: Boolean);
1366 TokenType: TZTokenType;
1369 FieldCount: Integer;
1371 OnlyDataFields := True;
1373 SetLength(FieldRefs, FieldCount);
1374 SetLength(FieldDirs, FieldCount);
1375 Tokens := CommonTokenizer.TokenizeBufferToList(SortedFields,
1376 [toSkipEOF, toSkipWhitespaces, toUnifyNumbers, toDecodeStrings]);
1379 for I := 0 to Tokens.Count - 1 do
1381 TokenType := TZTokenType({$IFDEF OLDFPC}Pointer({$ENDIF}
1382 Tokens.Objects[I]{$IFDEF OLDFPC}){$ENDIF});
1383 TokenValue := Tokens[I];
1386 if ((UpperCase(TokenValue) = 'DESC')
1387 or (UpperCase(TokenValue) = 'ASC')) and (FieldCount > 0) then
1389 FieldDirs[FieldCount - 1] := (UpperCase(TokenValue) <> 'DESC');
1391 else if TokenType in [ttWord, ttQuoted] then
1393 Field := DataSet.FieldByName(TokenValue)
1395 else if (TokenType = ttNumber)
1396 and (StrToIntDef(TokenValue, 0) < Dataset.Fields.Count) then
1398 Field := Dataset.Fields[StrToIntDef(TokenValue, 0)];
1400 else if (TokenValue <> ',') and (TokenValue <> ';') then
1402 raise EZDatabaseError.Create(Format(SIncorrectSymbol, [TokenValue]));
1405 if Field <> nil then
1407 OnlyDataFields := OnlyDataFields and (Field.FieldKind = fkData);
1409 SetLength(FieldRefs, FieldCount);
1410 SetLength(FieldDirs, FieldCount);
1411 FieldRefs[FieldCount - 1] := Field;
1412 FieldDirs[FieldCount - 1] := True;
1421 Creates a fields lookup table to define fixed position
1422 of the field in dataset.
1423 @param Fields a collection of TDataset fields in initial order.
1424 @returns a fields lookup table.
1426 function CreateFieldsLookupTable(Fields: TFields): TIntegerDynArray;
1430 SetLength(Result, Fields.Count);
1431 for I := 0 to Fields.Count - 1 do
1432 Result[I] := Integer(Fields[I]);
1436 Defines an original field index in the dataset.
1437 @param FieldsLookupTable a lookup table to define original index.
1438 @param Field a TDataset field object.
1439 @returns an original fields index or -1 otherwise.
1441 function DefineFieldIndex(const FieldsLookupTable: TIntegerDynArray;
1442 Field: TField): Integer;
1447 for I := 0 to High(FieldsLookupTable) do
1449 if FieldsLookupTable[I] = Integer(Field) then
1458 Defines an original field indices in the dataset.
1459 @param FieldsLookupTable a lookup table to define original index.
1460 @param FieldRefs a TDataset field object references.
1461 @returns an array with original fields indices.
1463 function DefineFieldIndices(const FieldsLookupTable: TIntegerDynArray;
1464 const FieldRefs: TObjectDynArray): TIntegerDynArray;
1468 if FieldRefs = nil then
1474 SetLength(Result, Length(FieldRefs));
1475 for I := 0 to High(Result) do
1476 Result[I] := DefineFieldIndex(FieldsLookupTable, TField(FieldRefs[I]));
1480 Splits up a qualified object name into pieces. Catalog, schema
1483 procedure SplitQualifiedObjectName(QualifiedName: string;
1484 var Catalog, Schema, ObjectName: string);
1487 function ExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar;
1488 Strings: TStrings): Integer;
1491 EOS, InQuote: Boolean;
1496 if (Content = nil) or (Content^ = #0) or (Strings = nil) then
1501 Strings.BeginUpdate;
1504 while CharInSet(Tail^, WhiteSpace + [#13, #10]) do
1509 while (InQuote and not CharInSet(Tail^, [QuoteChar, #0])) or
1510 not CharInSet(Tail^, Separators + [#0, #13, #10, '''', '"']) do
1512 if CharInSet(Tail^, ['''', '"']) then
1514 if (QuoteChar <> #0) and (QuoteChar = Tail^) then
1518 InQuote := QuoteChar <> #0;
1525 if (Head <> Tail) and (Head^ <> #0) then
1527 if Strings <> nil then
1529 SetString(Item, Head, Tail - Head);
1546 SL := TStringList.Create;
1550 ObjectName := QualifiedName;
1551 ExtractStrings(['.'], [' '], PChar(QualifiedName), SL);
1555 Schema := SL.Strings[0];
1556 ObjectName := SL.Strings[1];
1559 Catalog := SL.Strings[0];
1560 Schema := SL.Strings[1];
1561 ObjectName := SL.Strings[2];
1565 ObjectName := SL.Strings[SL.Count - 1];
1566 Schema := SL.Strings[SL.Count - 2];
1567 for I := 0 to SL.Count - 3 do
1569 Catalog := Catalog + SL.Strings[I];
1570 if I < SL.Count - 3 then
1571 Catalog := Catalog + '.';
1581 Splits up a qualified object name into pieces. Catalog, schema
1584 procedure SplitQualifiedObjectName(QualifiedName: string;
1585 const SupportsCatalogs, SupportsSchemas: Boolean;
1586 var Catalog, Schema, ObjectName: string);
1591 if SupportsCatalogs and SupportsSchemas then
1592 SplitQualifiedObjectName(QualifiedName, Catalog, Schema, ObjectName)
1595 SL := TStringList.Create;
1599 ObjectName := QualifiedName;
1600 ExtractStrings(['.'], [' '], PChar(QualifiedName), SL);
1605 if SupportsCatalogs then
1607 Catalog := SL.Strings[0];
1608 if SupportsSchemas then
1609 Schema := SL.Strings[1]
1611 ObjectName := SL.Strings[1];
1614 if SupportsSchemas then
1616 Schema := SL.Strings[0];
1617 ObjectName := SL.Strings[1];
1620 ObjectName := SL.Strings[0]+'.'+SL.Strings[1];
1623 if SupportsCatalogs then
1625 Catalog := SL.Strings[0];
1626 if SupportsSchemas then
1628 Schema := SL.Strings[1];
1629 ObjectName := SL.Strings[2]
1632 ObjectName := SL.Strings[1]+'.'+SL.Strings[2];
1635 if SupportsSchemas then
1637 Schema := SL.Strings[0];
1638 ObjectName := SL.Strings[1]+'.'+SL.Strings[2];
1641 ObjectName := SL.Strings[0]+'.'+SL.Strings[1]+'.'+SL.Strings[2];
1643 if SupportsCatalogs then
1645 Catalog := SL.Strings[0];
1646 if SupportsSchemas then
1648 Schema := SL.Strings[1];
1649 for i := 2 to SL.Count-1 do
1651 ObjectName := SL.Strings[i]
1653 ObjectName := ObjectName+'.'+SL.Strings[i];
1658 for i := 2 to SL.Count-1 do
1660 ObjectName := SL.Strings[i]
1662 ObjectName := ObjectName+'.'+SL.Strings[i];
1666 if SupportsSchemas then
1668 Schema := SL.Strings[0];
1669 for i := 1 to SL.Count-1 do
1671 ObjectName := SL.Strings[i]
1673 ObjectName := ObjectName+'.'+SL.Strings[i];
1676 for i := 0 to SL.Count-1 do
1678 ObjectName := SL.Strings[i]
1680 ObjectName := ObjectName+'.'+SL.Strings[i];
1689 Assigns a Statement value from a TParam
1690 @param Index the index of Statement.SetXxxx(ColumnIndex, xxx);
1691 @param Statement the PrepredStatement where the values have been assigned
1692 @param Param the TParam where the value is assigned from
1694 procedure SetStatementParam(Index: Integer;
1695 Statement: IZPreparedStatement; Param: TParam);
1698 TempBytes: TByteDynArray;
1699 {$IFDEF WITH_ASBYTES}Bts: TBytes;{$ENDIF}
1700 {$IFDEF WITHOUT_VARBYTESASSTRING}V: Variant;{$ENDIF}
1702 if Param.IsNull then
1703 Statement.SetNull(Index, ConvertDatasetToDbcType(Param.DataType))
1706 case Param.DataType of
1708 Statement.SetBoolean(Index, Param.AsBoolean);
1709 ftSmallInt{$IFDEF WITH_FTSHORTINT}, ftShortInt{$ENDIF}:
1710 Statement.SetShort(Index, Param.AsSmallInt);
1711 ftInteger, ftAutoInc{$IFDEF WITH_FTBYTE}, ftByte{$ENDIF}:
1712 Statement.SetInt(Index, Param.AsInteger);
1713 ftFloat{$IFDEF WITH_FTEXTENDED}, ftExtended{$ENDIF}:
1714 Statement.SetDouble(Index, Param.AsFloat);
1715 {$IFDEF WITH_FTLONGWORD}
1717 Statement.SetInt(Index, Integer(Param.AsLongWord));
1720 Statement.SetLong(Index, StrToInt64(Param.AsString));
1722 Statement.SetBigDecimal(Index, Param.AsCurrency);
1723 ftString, ftFixedChar:
1724 Statement.SetString(Index, Param.AsString);
1725 {$IFDEF WITH_FTWIDESTRING}
1727 Statement.SetUnicodeString(Index, Param.AsWideString);
1729 ftBytes, ftVarBytes{$IFDEF WITH_FTGUID}, ftGuid{$ENDIF}:
1731 {$IFDEF WITH_ASBYTES}
1732 Bts := Param.AsBytes;
1733 SetLength(TempBytes, High(Bts)+1);
1734 System.Move(PAnsichar(Bts)^, PAnsichar(TempBytes)^, High(Bts)+1);
1736 {$IFDEF WITHOUT_VARBYTESASSTRING}
1740 TempBytes := StrToBytes(Param.AsString);
1743 Statement.SetBytes(Index, TempBytes);
1746 Statement.SetDate(Index, Param.AsDate);
1748 Statement.SetTime(Index, Param.AsTime);
1750 Statement.SetTimestamp(Index, Param.AsDateTime);
1753 {EgonHugeist: On reading a Param as Memo the Stream reads Byte-wise
1754 on Changing to stUnicodeString/Delphi12Up a String is from
1755 Type wide/unicode so we have to give him back as
1758 Stream := Param.AsStream;
1760 Stream := TStringStream.Create(Param.AsMemo);
1763 Statement.SetAsciiStream(Index, Stream);
1768 {$IFDEF WITH_WIDEMEMO}
1771 Stream := WideStringStream(Param.AsWideString);
1773 Statement.SetUnicodeStream(Index, Stream);
1781 Stream := TStringStream.Create(Param.AsBlob);
1783 Statement.SetBinaryStream(Index, Stream);
1789 raise EZDatabaseError.Create(SUnKnownParamDataType + IntToStr(Ord(Param.DataType)));
1795 CommonTokenizer := TZGenericSQLTokenizer.Create;
1797 CommonTokenizer := nil;