1 {*********************************************************}
3 { Zeos Database Objects }
4 { Abstract Database Connectivity 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 {********************************************************@}
52 unit ZDbcResultSetMetadata;
59 Classes, SysUtils, Contnrs, ZDbcIntfs, ZClasses, ZCollections,
66 ZTokenizer, ZSelectSchema, ZCompatibility, ZDbcResultSet;
70 {** Implements a column information structure. }
71 TZColumnInfo = class(TObject)
73 FAutoIncrement: Boolean;
74 FCaseSensitive: Boolean;
77 FNullable: TZColumnNullableType;
79 FColumnDisplaySize: Integer;
80 FMaxLenghtBytes: Integer;
88 FColumnType: TZSQLType;
89 FInternalColumnType: TZSQLType;
92 FDefinitelyWritable: Boolean;
93 FDefaultValue: string;
94 FDefaultExpression : string;
97 function GetColumnTypeName: string;
99 property AutoIncrement: Boolean read FAutoIncrement write FAutoIncrement;
100 property CaseSensitive: Boolean read FCaseSensitive write FCaseSensitive;
101 property Searchable: Boolean read FSearchable write FSearchable;
102 property Currency: Boolean read FCurrency write FCurrency;
103 property Nullable: TZColumnNullableType read FNullable write FNullable;
105 property Signed: Boolean read FSigned write FSigned;
106 property ColumnDisplaySize: Integer read FColumnDisplaySize
107 write FColumnDisplaySize;
108 property MaxLenghtBytes: Integer read FMaxLenghtBytes
109 write FMaxLenghtBytes;
110 property ColumnLabel: string read FColumnLabel write FColumnLabel;
111 property ColumnName: string read FColumnName write FColumnName;
112 property SchemaName: string read FSchemaName write FSchemaName;
113 property Precision: Integer read FPrecision write FPrecision;
114 property Scale: Integer read FScale write FScale;
115 property TableName: string read FTableName write FTableName;
116 property CatalogName: string read FCatalogName write FCatalogName;
117 property ColumnType: TZSQLType read FColumnType write FColumnType;
118 property InternalColumnType: TZSQLType read FInternalColumnType write FInternalColumnType;
119 property ReadOnly: Boolean read FReadOnly write FReadOnly;
120 property Writable: Boolean read FWritable write FWritable;
121 property DefinitelyWritable: Boolean read FDefinitelyWritable
122 write FDefinitelyWritable;
123 property DefaultValue: string read FDefaultValue write FDefaultValue;
124 property DefaultExpression: string read FDefaultExpression write FDefaultExpression;
127 {** Implements Abstract ResultSet Metadata. }
128 TZAbstractResultSetMetadata = class(TContainedObject, IZResultSetMetaData)
131 FMetadata: IZDatabaseMetadata;
132 FColumnsLabels: TStrings;
134 FTableColumns: TZHashMap;
135 FIdentifierConvertor: IZIdentifierConvertor;
136 FResultSet: TZAbstractResultSet;
137 procedure SetMetadata(const Value: IZDatabaseMetadata);
139 procedure LoadColumn(ColumnIndex: Integer; ColumnInfo: TZColumnInfo;
140 SelectSchema: IZSelectSchema); virtual;
142 function GetTableColumns(TableRef: TZTableRef): IZResultSet;
143 function ReadColumnByRef(FieldRef: TZFieldRef;
144 ColumnInfo: TZColumnInfo): Boolean;
145 function ReadColumnByName(FieldName: string; TableRef: TZTableRef;
146 ColumnInfo: TZColumnInfo): Boolean;
147 procedure ClearColumn(ColumnInfo: TZColumnInfo);
148 procedure LoadColumns;
149 procedure ReplaceStarColumns(SelectSchema: IZSelectSchema);
151 property MetaData: IZDatabaseMetadata read FMetadata write SetMetadata;
152 property ColumnsLabels: TStrings read FColumnsLabels write FColumnsLabels;
153 property SQL: string read FSQL write FSQL;
154 property IdentifierConvertor: IZIdentifierConvertor
155 read FIdentifierConvertor write FIdentifierConvertor;
156 property Loaded: Boolean read FLoaded write FLoaded;
157 property ResultSet: TZAbstractResultSet read FResultSet write FResultSet;
159 constructor Create(Metadata: IZDatabaseMetadata; SQL: string;
160 ParentResultSet: TZAbstractResultSet);
161 destructor Destroy; override;
163 function GetColumnCount: Integer; virtual;
164 function IsAutoIncrement(Column: Integer): Boolean; virtual;
165 function IsCaseSensitive(Column: Integer): Boolean; virtual;
166 function IsSearchable(Column: Integer): Boolean; virtual;
167 function IsCurrency(Column: Integer): Boolean; virtual;
168 function IsNullable(Column: Integer): TZColumnNullableType; virtual;
170 function IsSigned(Column: Integer): Boolean; virtual;
171 function GetColumnDisplaySize(Column: Integer): Integer; virtual;
172 function GetColumnLabel(Column: Integer): string; virtual;
173 function GetColumnName(Column: Integer): string; virtual;
174 function GetSchemaName(Column: Integer): string; virtual;
175 function GetPrecision(Column: Integer): Integer; virtual;
176 function GetScale(Column: Integer): Integer; virtual;
177 function GetTableName(Column: Integer): string; virtual;
178 function GetCatalogName(Column: Integer): string; virtual;
179 function GetColumnType(Column: Integer): TZSQLType; virtual;
180 function GetColumnTypeName(Column: Integer): string; virtual;
181 function IsReadOnly(Column: Integer): Boolean; virtual;
182 function IsWritable(Column: Integer): Boolean; virtual;
183 function IsDefinitelyWritable(Column: Integer): Boolean; virtual;
184 function GetDefaultValue(Column: Integer): string; virtual;
185 function HasDefaultValue(Column: Integer): Boolean; virtual;
190 uses ZVariant, ZDbcUtils, ZDbcMetadata;
195 Constructs this object and assigns main properties.
197 constructor TZColumnInfo.Create;
199 FAutoIncrement := False;
200 FCaseSensitive := False;
201 FSearchable := False;
203 FNullable := ntNullableUnknown;
205 FColumnDisplaySize := 0;
214 FColumnType := stUnknown;
215 FInternalColumnType := stUnknown;
218 FDefinitelyWritable := False;
222 Retrieves the designated column's database-specific type name.
223 @return type name used by the database. If the column type is
224 a user-defined type, then a fully-qualified type name is returned.
226 function TZColumnInfo.GetColumnTypeName: string;
228 Result := DefineColumnTypeName(FColumnType);
231 { TZAbstractResultSetMetadata }
234 Constructs this object and assignes the main properties.
235 @param Metadata a database metadata object.
236 @param SQL an SQL query statement.
237 @param ColumnsInfo a collection of columns info.
239 constructor TZAbstractResultSetMetadata.Create(Metadata: IZDatabaseMetadata;
240 SQL: string; ParentResultSet: TZAbstractResultSet);
242 inherited Create(ParentResultSet);
244 SetMetadata(Metadata);
246 FLoaded := not (FMetadata <> nil);
247 FTableColumns := TZHashMap.Create;
248 FResultSet := ParentResultSet;
252 Destroys this object and cleanups the memory.
254 destructor TZAbstractResultSetMetadata.Destroy;
256 FIdentifierConvertor := nil;
258 if Assigned(FTableColumns) then
263 FTableColumns := nil;
264 if FColumnsLabels <> nil then
270 Returns the number of columns in this <code>ResultSet</code> object.
271 @return the number of columns
273 function TZAbstractResultSetMetadata.GetColumnCount: Integer;
275 Result := FResultSet.ColumnsInfo.Count;
279 Indicates whether the designated column is automatically numbered, thus read-only.
280 @param column the first column is 1, the second is 2, ...
281 @return <code>true</code> if so; <code>false</code> otherwise
283 function TZAbstractResultSetMetadata.IsAutoIncrement(Column: Integer): Boolean;
287 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).AutoIncrement;
291 Indicates whether a column's case matters.
292 @param column the first column is 1, the second is 2, ...
293 @return <code>true</code> if so; <code>false</code> otherwise
295 function TZAbstractResultSetMetadata.IsCaseSensitive(Column: Integer): Boolean;
299 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).CaseSensitive;
303 Indicates whether the designated column can be used in a where clause.
304 @param column the first column is 1, the second is 2, ...
305 @return <code>true</code> if so; <code>false</code> otherwise
307 function TZAbstractResultSetMetadata.IsSearchable(Column: Integer): Boolean;
311 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).Searchable;
315 Indicates whether the designated column is a cash value.
316 @param column the first column is 1, the second is 2, ...
317 @return <code>true</code> if so; <code>false</code> otherwise
319 function TZAbstractResultSetMetadata.IsCurrency(Column: Integer): Boolean;
321 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).Currency;
325 Indicates the nullability of values in the designated column.
326 @param column the first column is 1, the second is 2, ...
327 @return the nullability status of the given column; one of <code>columnNoNulls</code>,
328 <code>columnNullable</code> or <code>columnNullableUnknown</code>
330 function TZAbstractResultSetMetadata.IsNullable(
331 Column: Integer): TZColumnNullableType;
335 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).Nullable;
339 Indicates whether values in the designated column are signed numbers.
340 @param column the first column is 1, the second is 2, ...
341 @return <code>true</code> if so; <code>false</code> otherwise
343 function TZAbstractResultSetMetadata.IsSigned(Column: Integer): Boolean;
345 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).Signed;
349 Indicates the designated column's normal maximum width in characters.
350 @param column the first column is 1, the second is 2, ...
351 @return the normal maximum number of characters allowed as the width
352 of the designated column
354 function TZAbstractResultSetMetadata.GetColumnDisplaySize(
355 Column: Integer): Integer;
357 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).ColumnDisplaySize;
361 Gets the designated column's suggested title for use in printouts and
363 @param column the first column is 1, the second is 2, ...
364 @return the suggested column title
366 function TZAbstractResultSetMetadata.GetColumnLabel(Column: Integer): string;
370 ColumnsInfo: TObjectList;
372 { Prepare unique column labels. }
373 if FColumnsLabels = nil then
375 ColumnsInfo := FResultSet.ColumnsInfo;
376 FColumnsLabels := TStringList.Create;
377 for I := 0 to ColumnsInfo.Count - 1 do
380 ColumnName := TZColumnInfo(ColumnsInfo[I]).ColumnLabel;
381 for J := 0 to I - 1 do
383 if TZColumnInfo(ColumnsInfo[J]).ColumnLabel = ColumnName then
386 if ColumnName = '' then
387 ColumnName := 'Column';
389 ColumnName := ColumnName + '_' + IntToStr(N);
390 FColumnsLabels.Add(ColumnName);
394 Result := ColumnsLabels[Column - 1];
398 Get the designated column's name.
399 @param column the first column is 1, the second is 2, ...
402 function TZAbstractResultSetMetadata.GetColumnName(
403 Column: Integer): string;
407 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).ColumnName;
411 Get the designated column's table's schema.
412 @param column the first column is 1, the second is 2, ...
413 @return schema name or "" if not applicable
415 function TZAbstractResultSetMetadata.GetSchemaName(
416 Column: Integer): string;
420 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).SchemaName;
424 Get the designated column's number of decimal digits.
425 @param column the first column is 1, the second is 2, ...
428 function TZAbstractResultSetMetadata.GetPrecision(Column: Integer): Integer;
430 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).Precision;
434 Gets the designated column's number of digits to right of the decimal point.
435 @param column the first column is 1, the second is 2, ...
438 function TZAbstractResultSetMetadata.GetScale(Column: Integer): Integer;
440 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).Scale;
444 Gets the designated column's table name.
445 @param column the first column is 1, the second is 2, ...
446 @return table name or "" if not applicable
448 function TZAbstractResultSetMetadata.GetTableName(Column: Integer): string;
452 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).TableName;
456 Gets the designated column's table's catalog name.
457 @param column the first column is 1, the second is 2, ...
458 @return column name or "" if not applicable
460 function TZAbstractResultSetMetadata.GetCatalogName(Column: Integer): string;
464 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).CatalogName;
468 Retrieves the designated column's SQL type.
469 @param column the first column is 1, the second is 2, ...
470 @return SQL type from java.sql.Types
472 function TZAbstractResultSetMetadata.GetColumnType(Column: Integer): TZSQLType;
474 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).ColumnType;
478 Retrieves the designated column's database-specific type name.
480 @param column the first column is 1, the second is 2, ...
481 @return type name used by the database. If the column type is
482 a user-defined type, then a fully-qualified type name is returned.
484 function TZAbstractResultSetMetadata.GetColumnTypeName(Column: Integer): string;
486 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).GetColumnTypeName;
490 Indicates whether the designated column is definitely not writable.
491 @param column the first column is 1, the second is 2, ...
492 @return <code>true</code> if so; <code>false</code> otherwise
494 function TZAbstractResultSetMetadata.IsReadOnly(Column: Integer): Boolean;
498 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).ReadOnly;
502 Indicates whether it is possible for a write on the designated column to succeed.
503 @param column the first column is 1, the second is 2, ...
504 @return <code>true</code> if so; <code>false</code> otherwise
506 function TZAbstractResultSetMetadata.IsWritable(Column: Integer): Boolean;
510 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).Writable;
514 Indicates whether a write on the designated column will definitely succeed.
515 @param column the first column is 1, the second is 2, ...
516 @return <code>true</code> if so; <code>false</code> otherwise
518 function TZAbstractResultSetMetadata.IsDefinitelyWritable(
519 Column: Integer): Boolean;
523 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).DefinitelyWritable;
527 Gets a default value for this field.
528 @param column the first column is 1, the second is 2, ...
529 @return a default value for this field.
531 function TZAbstractResultSetMetadata.GetDefaultValue(
532 Column: Integer): string;
536 Result := TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).DefaultValue;
540 Finds whether this field has a default value.
541 @param column the first column is 1, the second is 2, ...
542 @return true if this field has a default value.
544 function TZAbstractResultSetMetadata.HasDefaultValue(
545 Column: Integer): Boolean;
549 // '' = NULL / no default value, '''''' = empty string (''), etc.
550 Result := not(TZColumnInfo(FResultSet.ColumnsInfo[Column - 1]).DefaultValue = '');
554 Gets a table description result set.
555 @param TableRef a table reference object.
556 @return a result set with table columns from database metadata.
558 function TZAbstractResultSetMetadata.GetTableColumns(
559 TableRef: TZTableRef): IZResultSet;
561 TableKey: IZAnyValue;
563 TableKey := TZAnyValue.CreateWithString(TableRef.FullName);
564 if FTableColumns.Get(TableKey) = nil then
566 Result := Metadata.GetColumns(TableRef.Catalog,
567 TableRef.Schema, TableRef.Table, '');
568 FTableColumns.Put(TableKey, Result);
571 Result := FTableColumns.Get(TableKey) as IZResultSet;
575 Clears specified column information.
576 @param ColumnInfo a column information object.
578 procedure TZAbstractResultSetMetadata.ClearColumn(ColumnInfo: TZColumnInfo);
580 ColumnInfo.ReadOnly := True;
581 ColumnInfo.Writable := False;
582 ColumnInfo.DefinitelyWritable := False;
583 ColumnInfo.CatalogName := '';
584 ColumnInfo.SchemaName := '';
585 ColumnInfo.TableName := '';
586 ColumnInfo.ColumnName := '';
590 Reads a column information from table metadata.
591 @param FieldName a name of the field.
592 @param TableRef a table reference object.
593 @param ColumnInfo a column information object.
594 @return <code>True</code> is column was found and read.
596 function TZAbstractResultSetMetadata.ReadColumnByName(FieldName: string;
597 TableRef: TZTableRef; ColumnInfo: TZColumnInfo): Boolean;
599 TableColumns: IZResultSet;
600 tempColType: TZSQLType;
603 TableColumns := GetTableColumns(TableRef);
604 { Checks for unexisted table. }
605 if not Assigned(TableColumns) then
608 { Locates a column row. }
609 TableColumns.BeforeFirst;
610 while TableColumns.Next do
611 if TableColumns.GetString(4) = FieldName then
613 if TableColumns.IsAfterLast then
615 { Locates a column row with case insensitivity. }
616 TableColumns.BeforeFirst;
617 while TableColumns.Next do
618 if AnsiUpperCase(TableColumns.GetString(4)) = AnsiUpperCase(FieldName) then
620 if TableColumns.IsAfterLast then
624 { Reads a column information. }
626 ColumnInfo.CatalogName := TableColumns.GetString(1);
627 ColumnInfo.SchemaName := TableColumns.GetString(2);
628 ColumnInfo.TableName := TableColumns.GetString(3);
629 ColumnInfo.ColumnName := FieldName;
631 //If the returned column information is null then the value assigned during
632 //the resultset.open will be kept
633 if not TableColumns.IsNull(5) then
635 //since Pointer referencing by RowAccessor we've a pointer and GetBlob
636 //raises an exception if the pointer is a reference to PPAnsiChar or
637 //ZPPWideChar. if we execute a cast of a lob field the database meta-informtions
638 //assume a IZLob-Pointer. So let's prevent this case and check for
639 //stByte, stString, stUnicoeString first. If this type is returned from the
640 //ResultSet-Metadata we do NOT overwrite the column-type
641 //f.e. select cast( name as varchar(100)), cast(setting as varchar(100)) from pg_settings
643 //or the same vice versa:
644 //(CASE WHEN (Ticket51_B."Name" IS NOT NULL) THEN Ticket51_B."Name" ELSE 'Empty' END) As "Name"
645 //we've NO fixed length for a case(postgres and FB2.5up f.e.) select
646 tempColType := TZSQLType(TableColumns.GetShort(5));
647 if not (TZSQLType(TableColumns.GetShort(5)) in [stBinaryStream, stAsciiStream,
648 stUnicodeStream, stBytes, stString, stUnicodeString]) then
649 ColumnInfo.ColumnType := tempColType;
651 if not TableColumns.IsNull(11) then
652 ColumnInfo.Nullable := TZColumnNullableType(TableColumns.GetInt(11));
653 if not TableColumns.IsNull(19) then
654 ColumnInfo.AutoIncrement := TableColumns.GetBoolean(19);
655 if not TableColumns.IsNull(20) then
656 ColumnInfo.CaseSensitive := TableColumns.GetBoolean(20);
657 if not TableColumns.IsNull(21) then
658 ColumnInfo.Searchable := TableColumns.GetBoolean(21);
659 if not TableColumns.IsNull(22) then
660 if ColumnInfo.AutoIncrement and Assigned(FMetadata) then {improve ADO where the metainformations do not bring autoincremental fields through}
661 if FMetadata.GetDatabaseInfo.SupportsUpdateAutoIncrementFields then
662 ColumnInfo.Writable := TableColumns.GetBoolean(22)
664 ColumnInfo.Writable := False
666 ColumnInfo.Writable := TableColumns.GetBoolean(22);
667 if not TableColumns.IsNull(23) then
668 if ColumnInfo.AutoIncrement and Assigned(FMetadata) then {improve ADO where the metainformations do not bring autoincremental fields through}
669 if FMetadata.GetDatabaseInfo.SupportsUpdateAutoIncrementFields then
670 ColumnInfo.DefinitelyWritable := TableColumns.GetBoolean(23)
672 ColumnInfo.DefinitelyWritable := False
674 ColumnInfo.DefinitelyWritable := TableColumns.GetBoolean(23);
675 if not TableColumns.IsNull(24) then
676 if ColumnInfo.AutoIncrement and Assigned(FMetadata) then {improve ADO where the metainformations do not bring autoincremental fields through}
677 if FMetadata.GetDatabaseInfo.SupportsUpdateAutoIncrementFields then
678 ColumnInfo.ReadOnly := TableColumns.GetBoolean(24)
680 ColumnInfo.ReadOnly := True
682 ColumnInfo.ReadOnly := TableColumns.GetBoolean(24);
683 if not TableColumns.IsNull(13) then
684 ColumnInfo.DefaultValue := TableColumns.GetString(13);
688 Reads a column information from table metadata.
689 @param FieldRef a field reference object.
690 @param ColumnInfo a column information object.
691 @return <code>True</code> if column was found and read.
693 function TZAbstractResultSetMetadata.ReadColumnByRef(
694 FieldRef: TZFieldRef; ColumnInfo: TZColumnInfo): Boolean;
697 ClearColumn(ColumnInfo);
698 { Checks for uncompleted field reference. }
699 if not Assigned(FieldRef) or not Assigned(FieldRef.TableRef) then
701 if not FieldRef.IsField then
704 Result := ReadColumnByName(FieldRef.Field, FieldRef.TableRef, ColumnInfo);
708 Initializes on single column of the result set.
709 @param ColumnIndex a column index in the query.
710 @param ColumnInfo a column information object to be initialized.
711 @param SelectSchema a schema of the select statement.
713 procedure TZAbstractResultSetMetadata.LoadColumn(ColumnIndex: Integer;
714 ColumnInfo: TZColumnInfo; SelectSchema: IZSelectSchema);
717 FieldRef: TZFieldRef;
718 TableRef: TZTableRef;
721 { Initializes single columns with specified table. }
722 FieldRef := SelectSchema.LinkFieldByIndexAndShortName(ColumnIndex,
723 ColumnInfo.ColumnLabel, IdentifierConvertor);
724 ReadColumnByRef(FieldRef, ColumnInfo);
725 if ColumnInfo.ColumnName <> '' then
728 { Initializes single columns without specified table. }
731 while (ColumnInfo.ColumnName = '') and (I < SelectSchema.TableCount)
734 TableRef := SelectSchema.Tables[I];
735 if Assigned(FieldRef) then
736 Found := ReadColumnByName(IdentifierConvertor.ExtractQuote(FieldRef.Field), TableRef, ColumnInfo)
738 Found := ReadColumnByName(IdentifierConvertor.ExtractQuote(ColumnInfo.ColumnLabel), TableRef, ColumnInfo);
744 Replaces '*' columns in the select schema.
745 @param SelectSchema a query select schema.
747 procedure TZAbstractResultSetMetadata.ReplaceStarColumns(
748 SelectSchema: IZSelectSchema);
752 FieldRef: TZFieldRef;
753 TableRef: TZTableRef;
754 ResultSet: IZResultSet;
757 while I < SelectSchema.FieldCount do
759 Current := SelectSchema.Fields[I];
760 if (Current.Field = '*') and (Current.TableRef <> nil) then
762 TableRef := Current.TableRef;
763 ResultSet := Self.GetTableColumns(TableRef);
764 if ResultSet <> nil then
766 ResultSet.BeforeFirst;
767 while ResultSet.Next do
769 FieldRef := TZFieldRef.Create(True, TableRef.Catalog, TableRef.Schema,
770 TableRef.Table, ResultSet.GetString(4), '', TableRef);
771 SelectSchema.InsertField(I, FieldRef);
775 SelectSchema.DeleteField(Current);
782 procedure TZAbstractResultSetMetadata.SetMetadata(
783 const Value: IZDatabaseMetadata);
787 FIdentifierConvertor := Value.GetIdentifierConvertor
789 FIdentifierConvertor := TZDefaultIdentifierConvertor.Create(FMetadata);
793 Initializes columns with additional data.
795 procedure TZAbstractResultSetMetadata.LoadColumns;
799 Tokenizer: IZTokenizer;
800 StatementAnalyser: IZStatementAnalyser;
801 SelectSchema: IZSelectSchema;
802 FillByIndices: Boolean;
804 { Parses the Select statement and retrieves a schema object. }
805 Driver := Metadata.GetConnection.GetDriver;
806 Tokenizer := Driver.GetTokenizer;
807 StatementAnalyser := Driver.GetStatementAnalyser;
808 SelectSchema := StatementAnalyser.DefineSelectSchemaFromQuery(Tokenizer, SQL);
809 if Assigned(SelectSchema) then
811 SelectSchema.LinkReferences(IdentifierConvertor);
812 ReplaceStarColumns(SelectSchema);
813 FillByIndices := SelectSchema.FieldCount = FResultSet.ColumnsInfo.Count;
814 for I := 0 to FResultSet.ColumnsInfo.Count - 1 do
816 if FillByIndices then
817 LoadColumn(I + 1, TZColumnInfo(FResultSet.ColumnsInfo[I]), SelectSchema)
819 LoadColumn(-1, TZColumnInfo(FResultSet.ColumnsInfo[I]), SelectSchema);