zeoslib  UNKNOWN
 All Files
ZDbcMetadata.pas
Go to the documentation of this file.
1 {*********************************************************}
2 { }
3 { Zeos Database Objects }
4 { Abstract Database Connectivity Classes }
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 ZDbcMetadata;
53 
54 interface
55 
56 {$I ZDbc.inc}
57 
58 uses
59 {$IFDEF FPC}
60  {$IFDEF WIN32}
61  Comobj,
62  {$ENDIF}
63 {$ENDIF}
64  Types, Classes, {$IFDEF MSEgui}mclasses,{$ENDIF} SysUtils, Contnrs,
65  ZSysUtils, ZClasses, ZDbcIntfs, ZDbcResultSetMetadata, ZDbcCachedResultSet,
66  ZDbcCache, ZCompatibility, ZSelectSchema, ZURL, ZDbcConnection;
67 
68 const
69  procedureColumnUnknown = 0;
70  procedureColumnIn = 1;
71  procedureColumnInOut = 2;
72  procedureColumnOut = 4;
73  procedureColumnReturn = 5;
74  procedureColumnResult = 3;
75  procedureNoNulls = 0;
76  procedureNullable = 1;
77  procedureNullableUnknown = 2;
78 
79 type
80  TZWildcardsSet= {$IFDEF UNICODE}TSysCharSet{$ELSE}set of Char{$ENDIF};
81 
82  {** Defines a metadata resultset column definition. }
83  TZMetadataColumnDef = {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif} record
84  Name: string;
85  SQLType: TZSQLType;
86  Length: Integer
87  end;
88 
89  {** Defines a dynamic array of metadata column definitions. }
90  TZMetadataColumnDefs = array of TZMetadataColumnDef;
91 
92  {** Represents a Virtual ResultSet interface. }
93  IZVirtualResultSet = interface(IZCachedResultSet)
94  ['{D84055AC-BCD5-40CD-B408-6F11AF000C96}']
95  procedure SetType(Value: TZResultSetType);
96  procedure SetConcurrency(Value: TZResultSetConcurrency);
97  end;
98 
99  {** Implements Virtual ResultSet. }
100  TZVirtualResultSet = class(TZAbstractCachedResultSet, IZVirtualResultSet)
101  protected
102  procedure CalculateRowDefaults(RowAccessor: TZRowAccessor); override;
103  procedure PostRowUpdates(OldRowAccessor, NewRowAccessor: TZRowAccessor);
104  override;
105  public
106  constructor CreateWithStatement(const SQL: string; Statement: IZStatement;
107  ConSettings: PZConSettings);
108  constructor CreateWithColumns(ColumnsInfo: TObjectList; const SQL: string;
109  ConSettings: PZConSettings);
110  destructor Destroy; override;
111  end;
112 
113  {** Implements Abstract Database Metadata. }
114 
115  { TZAbstractDatabaseMetadata }
116 
117  TZAbstractDatabaseMetadata = class(TContainedObject, IZDatabaseMetadata)
118  private
119  FConnection: Pointer;
120  FUrl: TZURL;
121  FCachedResultSets: IZHashMap;
122  FDatabaseInfo: IZDatabaseInfo;
123  FConSettings: PZConSettings;
124  FIC: IZIdentifierConvertor;
125  function GetInfo: TStrings;
126  function GetURLString: String;
127  function StripEscape(const Pattern: string): string;
128  function HasNoWildcards(const Pattern: string): boolean;
129  protected
130  FDatabase: String;
131  WildcardsArray: array of char; //Added by Cipto
132  function EscapeString(const S: string): string; virtual;
133  function DecomposeObjectString(const S: String): String; virtual;
134  function CreateDatabaseInfo: IZDatabaseInfo; virtual; // technobot 2008-06-24
135  function GetStatement: IZSTatement; // technobot 2008-06-28 - moved from descendants
136 
137  { Metadata ResultSets Caching. }
138  procedure AddResultSetToCache(const Key: string; ResultSet: IZResultSet);
139  function GetResultSetFromCache(const Key: string): IZResultSet;
140  function ConstructVirtualResultSet(ColumnsDefs: TZMetadataColumnDefs):
141  IZVirtualResultSet;
142  function CopyToVirtualResultSet(SrcResultSet: IZResultSet;
143  DestResultSet: IZVirtualResultSet): IZVirtualResultSet;
144  function CloneCachedResultSet(ResultSet: IZResultSet): IZResultSet;
145  function ConstructNameCondition(Pattern: string; Column: string): string; virtual;
146  function AddEscapeCharToWildcards(const Pattern:string): string;
147  function GetWildcardsSet:TZWildcardsSet;
148  procedure FillWildcards; virtual;
149  function NormalizePatternCase(Pattern:String): string;
150  property Url: string read GetURLString;
151  property Info: TStrings read GetInfo;
152  property CachedResultSets: IZHashMap read FCachedResultSets
153  write FCachedResultSets;
154  property ConSettings: PZConSettings read FConSettings write FConSettings;
155  property IC: IZIdentifierConvertor read FIC;
156  protected
157  function UncachedGetTables(const Catalog: string; const SchemaPattern: string;
158  const TableNamePattern: string; const Types: TStringDynArray): IZResultSet; virtual;
159  function UncachedGetSchemas: IZResultSet; virtual;
160  function UncachedGetCatalogs: IZResultSet; virtual;
161  function UncachedGetTableTypes: IZResultSet; virtual;
162  function UncachedGetColumns(const Catalog: string; const SchemaPattern: string;
163  const TableNamePattern: string; const ColumnNamePattern: string): IZResultSet; virtual;
164  function UncachedGetTablePrivileges(const Catalog: string; const SchemaPattern: string;
165  const TableNamePattern: string): IZResultSet; virtual;
166  function UncachedGetColumnPrivileges(const Catalog: string; const Schema: string;
167  const Table: string; const ColumnNamePattern: string): IZResultSet; virtual;
168 
169  function UncachedGetPrimaryKeys(const Catalog: string; const Schema: string;
170  const Table: string): IZResultSet; virtual;
171  function UncachedGetImportedKeys(const Catalog: string; const Schema: string;
172  const Table: string): IZResultSet; virtual;
173  function UncachedGetExportedKeys(const Catalog: string; const Schema: string;
174  const Table: string): IZResultSet; virtual;
175  function UncachedGetCrossReference(const PrimaryCatalog: string; const PrimarySchema: string;
176  const PrimaryTable: string; const ForeignCatalog: string; const ForeignSchema: string;
177  const ForeignTable: string): IZResultSet; virtual;
178  function UncachedGetIndexInfo(const Catalog: string; const Schema: string; const Table: string;
179  Unique: Boolean; Approximate: Boolean): IZResultSet; virtual;
180  function UncachedGetSequences(const Catalog: string; const SchemaPattern: string;
181  const SequenceNamePattern: string): IZResultSet; virtual;
182  function UncachedGetTriggers(const Catalog: string; const SchemaPattern: string;
183  const TableNamePattern: string; const TriggerNamePattern: string): IZResultSet; virtual; //EgonHugeist
184  function UncachedGetCollationAndCharSet(const Catalog, SchemaPattern,
185  TableNamePattern, ColumnNamePattern: string): IZResultSet; virtual; //EgonHugeist
186  function UncachedGetCharacterSets: IZResultSet; virtual; //EgonHugeist
187  function UncachedGetProcedures(const Catalog: string; const SchemaPattern: string;
188  const ProcedureNamePattern: string): IZResultSet; virtual;
189  function UncachedGetProcedureColumns(const Catalog: string; const SchemaPattern: string;
190  const ProcedureNamePattern: string; const ColumnNamePattern: string):
191  IZResultSet; virtual;
192  function UncachedGetBestRowIdentifier(const Catalog: string; const Schema: string;
193  const Table: string; Scope: Integer; Nullable: Boolean): IZResultSet; virtual;
194  function UncachedGetVersionColumns(const Catalog: string; const Schema: string;
195  const Table: string): IZResultSet; virtual;
196  function UncachedGetTypeInfo: IZResultSet; virtual;
197  function UncachedGetUDTs(const Catalog: string; const SchemaPattern: string;
198  const TypeNamePattern: string; const Types: TIntegerDynArray): IZResultSet; virtual;
199  public
200  constructor Create(Connection: TZAbstractConnection; const Url: TZURL); virtual;
201  destructor Destroy; override;
202 
203  function GetURL: string; virtual;
204  function GetUserName: string; virtual;
205 
206  function GetDatabaseInfo: IZDatabaseInfo; // technobot 2008-06-24 - see also CreateDatabaseInfo method.
207 
208  function GetTables(const Catalog: string; const SchemaPattern: string;
209  const TableNamePattern: string; const Types: TStringDynArray): IZResultSet;
210  function GetSchemas: IZResultSet;
211  function GetCatalogs: IZResultSet;
212  function GetTableTypes: IZResultSet;
213  function GetColumns(const Catalog: string; const SchemaPattern: string;
214  const TableNamePattern: string; const ColumnNamePattern: string): IZResultSet;
215  function GetTablePrivileges(const Catalog: string; const SchemaPattern: string;
216  const TableNamePattern: string): IZResultSet;
217  function GetColumnPrivileges(const Catalog: string; const Schema: string;
218  const Table: string; const ColumnNamePattern: string): IZResultSet;
219  function GetPrimaryKeys(const Catalog: string; const Schema: string;
220  const Table: string): IZResultSet;
221  function GetImportedKeys(const Catalog: string; const Schema: string;
222  const Table: string): IZResultSet;
223  function GetExportedKeys(const Catalog: string; const Schema: string;
224  const Table: string): IZResultSet;
225  function GetCrossReference(const PrimaryCatalog: string; const PrimarySchema: string;
226  const PrimaryTable: string; const ForeignCatalog: string; const ForeignSchema: string;
227  const ForeignTable: string): IZResultSet;
228  function GetIndexInfo(const Catalog: string; const Schema: string; const Table: string;
229  Unique: Boolean; Approximate: Boolean): IZResultSet;
230  function GetCollationAndCharSet(const Catalog, Schema, TableName, ColumnName: String): IZResultSet; //EgonHugeist
231  function GetCharacterSets: IZResultSet; //EgonHugeist
232  function GetTriggers(const Catalog: string; const SchemaPattern: string;
233  const TableNamePattern: string; const TriggerNamePattern: string): IZResultSet; //EgonHugesit
234  function GetSequences(const Catalog: string; const SchemaPattern: string;
235  const SequenceNamePattern: string): IZResultSet;
236  function GetProcedures(const Catalog: string; const SchemaPattern: string;
237  const ProcedureNamePattern: string): IZResultSet;
238  function GetProcedureColumns(const Catalog: string; const SchemaPattern: string;
239  const ProcedureNamePattern: string; const ColumnNamePattern: string):
240  IZResultSet;
241  function GetBestRowIdentifier(const Catalog: string; const Schema: string;
242  const Table: string; Scope: Integer; Nullable: Boolean): IZResultSet;
243  function GetVersionColumns(const Catalog: string; const Schema: string;
244  const Table: string): IZResultSet;
245  function GetTypeInfo: IZResultSet;
246  function GetUDTs(const Catalog: string; const SchemaPattern: string;
247  const TypeNamePattern: string; const Types: TIntegerDynArray): IZResultSet;
248 
249 
250  function GetConnection: IZConnection; virtual;
251 
252  function GetIdentifierConvertor: IZIdentifierConvertor; virtual;
253  procedure ClearCache; overload;virtual;
254  procedure ClearCache(const Key: string);overload;virtual;
255 
256  // --> technobot 2008-06-14: metadata cache key retrieval API:
257  function GetTablesCacheKey(const Catalog: string; const SchemaPattern: string;
258  const TableNamePattern: string; const Types: TStringDynArray): string;
259  function GetSchemasCacheKey: string;
260  function GetCatalogsCacheKey: string;
261  function GetTableTypesCacheKey: string;
262  function GetColumnsCacheKey(const Catalog: string; const SchemaPattern: string;
263  const TableNamePattern: string; const ColumnNamePattern: string): string;
264  function GetColumnPrivilegesCacheKey(const Catalog: string; const Schema: string;
265  const Table: string; const ColumnNamePattern: string): string;
266  function GetTablePrivilegesCacheKey(const Catalog: string; const SchemaPattern: string;
267  const TableNamePattern: string): string;
268  function GetPrimaryKeysCacheKey(const Catalog: string; const Schema: string;
269  const Table: string): string;
270  function GetImportedKeysCacheKey(const Catalog: string; const Schema: string;
271  const Table: string): string;
272  function GetExportedKeysCacheKey(const Catalog: string; const Schema: string;
273  const Table: string): string;
274  function GetCrossReferenceCacheKey(const PrimaryCatalog: string; const PrimarySchema: string;
275  const PrimaryTable: string; const ForeignCatalog: string; const ForeignSchema: string;
276  const ForeignTable: string): string;
277  function GetIndexInfoCacheKey(const Catalog: string; const Schema: string; const Table: string;
278  const Unique: Boolean; const Approximate: Boolean): string;
279  function GetSequencesCacheKey(const Catalog: string; const SchemaPattern: string;
280  const SequenceNamePattern: string): string;
281  function GetCollationAndCharSetCacheKey(const Catalog, SchemaPattern,
282  TableNamePattern, ColumnPattern: String): string; //EgonHugeist
283  function GetCharacterSetsCacheKey: String; //EgonHugeist
284  function GetTriggersCacheKey(const Catalog: string;
285  const SchemaPattern: string; const TableNamePattern: string;
286  const TriggerNamePattern: string): string; //EgonHugeist
287  function GetProceduresCacheKey(const Catalog: string; const SchemaPattern: string;
288  const ProcedureNamePattern: string): string;
289  function GetProcedureColumnsCacheKey(const Catalog: string; const SchemaPattern: string;
290  const ProcedureNamePattern: string; const ColumnNamePattern: string): string;
291  function GetBestRowIdentifierCacheKey(const Catalog: string; const Schema: string;
292  const Table: string; const Scope: Integer; const Nullable: Boolean): string;
293  function GetVersionColumnsCacheKey(const Catalog: string; const Schema: string;
294  const Table: string): string;
295  function GetTypeInfoCacheKey: string;
296  function GetUDTsCacheKey(const Catalog: string; const SchemaPattern: string;
297  const TypeNamePattern: string; const Types: TIntegerDynArray): string;
298 
299  procedure GetCacheKeys(List: TStrings);
300  // <-- technobot 2008-06-14
301  end;
302 
303  // technobot 2008-06-24 - methods moved as is from TZAbstractDatabaseMetadata:
304  {** Implements Abstract Database Information. }
305  TZAbstractDatabaseInfo = class(TInterfacedObject, IZDatabaseInfo)
306  private
307  FMetadata: TZAbstractDatabaseMetadata;
308  protected
309  FIdentifierQuotes: String;
310  property Metadata: TZAbstractDatabaseMetadata read FMetadata;
311  public
312  constructor Create(const Metadata: TZAbstractDatabaseMetadata); overload;
313  constructor Create(const Metadata: TZAbstractDatabaseMetadata;
314  const IdentifierQuotes: String); overload;
315  destructor Destroy; override;
316 
317  // database/driver/server info:
318  function GetDatabaseProductName: string; virtual;
319  function GetDatabaseProductVersion: string; virtual;
320  function GetDriverName: string; virtual;
321  function GetDriverVersion: string; virtual;
322  function GetDriverMajorVersion: Integer; virtual;
323  function GetDriverMinorVersion: Integer; virtual;
324  function GetServerVersion: string; virtual;
325 
326  // capabilities (what it can/cannot do):
327  function AllProceduresAreCallable: Boolean; virtual;
328  function AllTablesAreSelectable: Boolean; virtual;
329  function SupportsMixedCaseIdentifiers: Boolean; virtual;
330  function SupportsMixedCaseQuotedIdentifiers: Boolean; virtual;
331  function SupportsAlterTableWithAddColumn: Boolean; virtual;
332  function SupportsAlterTableWithDropColumn: Boolean; virtual;
333  function SupportsColumnAliasing: Boolean; virtual;
334  function SupportsConvert: Boolean; virtual;
335  function SupportsConvertForTypes(FromType: TZSQLType; ToType: TZSQLType):
336  Boolean; virtual;
337  function SupportsTableCorrelationNames: Boolean; virtual;
338  function SupportsDifferentTableCorrelationNames: Boolean; virtual;
339  function SupportsExpressionsInOrderBy: Boolean; virtual;
340  function SupportsOrderByUnrelated: Boolean; virtual;
341  function SupportsGroupBy: Boolean; virtual;
342  function SupportsGroupByUnrelated: Boolean; virtual;
343  function SupportsGroupByBeyondSelect: Boolean; virtual;
344  function SupportsLikeEscapeClause: Boolean; virtual;
345  function SupportsMultipleResultSets: Boolean; virtual;
346  function SupportsMultipleTransactions: Boolean; virtual;
347  function SupportsNonNullableColumns: Boolean; virtual;
348  function SupportsMinimumSQLGrammar: Boolean; virtual;
349  function SupportsCoreSQLGrammar: Boolean; virtual;
350  function SupportsExtendedSQLGrammar: Boolean; virtual;
351  function SupportsANSI92EntryLevelSQL: Boolean; virtual;
352  function SupportsANSI92IntermediateSQL: Boolean; virtual;
353  function SupportsANSI92FullSQL: Boolean; virtual;
354  function SupportsIntegrityEnhancementFacility: Boolean; virtual;
355  function SupportsOuterJoins: Boolean; virtual;
356  function SupportsFullOuterJoins: Boolean; virtual;
357  function SupportsLimitedOuterJoins: Boolean; virtual;
358  function SupportsSchemasInDataManipulation: Boolean; virtual;
359  function SupportsSchemasInProcedureCalls: Boolean; virtual;
360  function SupportsSchemasInTableDefinitions: Boolean; virtual;
361  function SupportsSchemasInIndexDefinitions: Boolean; virtual;
362  function SupportsSchemasInPrivilegeDefinitions: Boolean; virtual;
363  function SupportsCatalogsInDataManipulation: Boolean; virtual;
364  function SupportsCatalogsInProcedureCalls: Boolean; virtual;
365  function SupportsCatalogsInTableDefinitions: Boolean; virtual;
366  function SupportsCatalogsInIndexDefinitions: Boolean; virtual;
367  function SupportsCatalogsInPrivilegeDefinitions: Boolean; virtual;
368  function SupportsOverloadPrefixInStoredProcedureName: Boolean; virtual;
369  function SupportsPositionedDelete: Boolean; virtual;
370  function SupportsPositionedUpdate: Boolean; virtual;
371  function SupportsSelectForUpdate: Boolean; virtual;
372  function SupportsStoredProcedures: Boolean; virtual;
373  function SupportsSubqueriesInComparisons: Boolean; virtual;
374  function SupportsSubqueriesInExists: Boolean; virtual;
375  function SupportsSubqueriesInIns: Boolean; virtual;
376  function SupportsSubqueriesInQuantifieds: Boolean; virtual;
377  function SupportsCorrelatedSubqueries: Boolean; virtual;
378  function SupportsUnion: Boolean; virtual;
379  function SupportsUnionAll: Boolean; virtual;
380  function SupportsOpenCursorsAcrossCommit: Boolean; virtual;
381  function SupportsOpenCursorsAcrossRollback: Boolean; virtual;
382  function SupportsOpenStatementsAcrossCommit: Boolean; virtual;
383  function SupportsOpenStatementsAcrossRollback: Boolean; virtual;
384  function SupportsTransactions: Boolean; virtual;
385  function SupportsTransactionIsolationLevel(Level: TZTransactIsolationLevel):
386  Boolean; virtual;
387  function SupportsDataDefinitionAndDataManipulationTransactions: Boolean; virtual;
388  function SupportsDataManipulationTransactionsOnly: Boolean; virtual;
389  function SupportsResultSetType(_Type: TZResultSetType): Boolean; virtual;
390  function SupportsResultSetConcurrency(_Type: TZResultSetType;
391  Concurrency: TZResultSetConcurrency): Boolean; virtual;
392  function SupportsBatchUpdates: Boolean; virtual;
393  function SupportsNonEscapedSearchStrings: Boolean; virtual;
394  function SupportsUpdateAutoIncrementFields: Boolean; virtual;
395 
396  // maxima:
397  function GetMaxBinaryLiteralLength: Integer; virtual;
398  function GetMaxCharLiteralLength: Integer; virtual;
399  function GetMaxColumnNameLength: Integer; virtual;
400  function GetMaxColumnsInGroupBy: Integer; virtual;
401  function GetMaxColumnsInIndex: Integer; virtual;
402  function GetMaxColumnsInOrderBy: Integer; virtual;
403  function GetMaxColumnsInSelect: Integer; virtual;
404  function GetMaxColumnsInTable: Integer; virtual;
405  function GetMaxConnections: Integer; virtual;
406  function GetMaxCursorNameLength: Integer; virtual;
407  function GetMaxIndexLength: Integer; virtual;
408  function GetMaxSchemaNameLength: Integer; virtual;
409  function GetMaxProcedureNameLength: Integer; virtual;
410  function GetMaxCatalogNameLength: Integer; virtual;
411  function GetMaxRowSize: Integer; virtual;
412  function GetMaxStatementLength: Integer; virtual;
413  function GetMaxStatements: Integer; virtual;
414  function GetMaxTableNameLength: Integer; virtual;
415  function GetMaxTablesInSelect: Integer; virtual;
416  function GetMaxUserNameLength: Integer; virtual;
417 
418  // policies (how are various data and operations handled):
419  function IsReadOnly: Boolean; virtual;
420  function IsCatalogAtStart: Boolean; virtual;
421  function DoesMaxRowSizeIncludeBlobs: Boolean; virtual;
422  function NullsAreSortedHigh: Boolean; virtual;
423  function NullsAreSortedLow: Boolean; virtual;
424  function NullsAreSortedAtStart: Boolean; virtual;
425  function NullsAreSortedAtEnd: Boolean; virtual;
426  function NullPlusNonNullIsNull: Boolean; virtual;
427  function UsesLocalFiles: Boolean; virtual;
428  function UsesLocalFilePerTable: Boolean; virtual;
429  function StoresUpperCaseIdentifiers: Boolean; virtual;
430  function StoresLowerCaseIdentifiers: Boolean; virtual;
431  function StoresMixedCaseIdentifiers: Boolean; virtual;
432  function StoresUpperCaseQuotedIdentifiers: Boolean; virtual;
433  function StoresLowerCaseQuotedIdentifiers: Boolean; virtual;
434  function StoresMixedCaseQuotedIdentifiers: Boolean; virtual;
435  function GetDefaultTransactionIsolation: TZTransactIsolationLevel; virtual;
436  function DataDefinitionCausesTransactionCommit: Boolean; virtual;
437  function DataDefinitionIgnoredInTransactions: Boolean; virtual;
438 
439  // interface details (terms, keywords, etc):
440  function GetIdentifierQuoteString: string;
441  function GetSchemaTerm: string; virtual;
442  function GetProcedureTerm: string; virtual;
443  function GetCatalogTerm: string; virtual;
444  function GetCatalogSeparator: string; virtual;
445  function GetSQLKeywords: string; virtual;
446  function GetNumericFunctions: string; virtual;
447  function GetStringFunctions: string; virtual;
448  function GetSystemFunctions: string; virtual;
449  function GetTimeDateFunctions: string; virtual;
450  function GetSearchStringEscape: string; virtual;
451  function GetExtraNameCharacters: string; virtual;
452  end;
453 
454  {** Implements a default Case Sensitive/Unsensitive identifier convertor. }
455  TZDefaultIdentifierConvertor = class (TZAbstractObject,
456  IZIdentifierConvertor)
457  private
458  FMetadata: Pointer;
459  function GetMetaData: IZDatabaseMetadata;
460  protected
461  property Metadata: IZDatabaseMetadata read GetMetaData;
462 
463  function IsLowerCase(const Value: string): Boolean;
464  function IsUpperCase(const Value: string): Boolean;
465  function IsSpecialCase(const Value: string): Boolean; virtual;
466  public
467  constructor Create(Metadata: IZDatabaseMetadata);
468 
469  function IsCaseSensitive(const Value: string): Boolean;
470  function IsQuoted(const Value: string): Boolean; virtual;
471  function Quote(const Value: string): string; virtual;
472  function ExtractQuote(const Value: string): string; virtual;
473  end;
474 
475  function GetTablesMetaDataCacheKey(Const Catalog:String;
476  Const SchemaPattern:String;Const TableNamePattern:String;const Types: TStringDynArray):String;
477  deprecated; // (technobot) use TZAbstractDatabaseMetadata.GetTablesCacheKey instead
478 
479 
480 var
481  CharacterSetsColumnsDynArray: TZMetadataColumnDefs; //EgonHugeist
482  CollationCharSetColumnsDynArray: TZMetadataColumnDefs; //EgonHugeist
483  TriggersColumnsDynArray: TZMetadataColumnDefs; //EgonHugeist
484  TriggersColColumnsDynArray: TZMetadataColumnDefs;
485  ProceduresColumnsDynArray: TZMetadataColumnDefs;
486  ProceduresColColumnsDynArray: TZMetadataColumnDefs;
487  TableColumnsDynArray: TZMetadataColumnDefs;
488  SchemaColumnsDynArray: TZMetadataColumnDefs;
489  CatalogColumnsDynArray: TZMetadataColumnDefs;
490  TableTypeColumnsDynArray: TZMetadataColumnDefs;
491  TableColColumnsDynArray: TZMetadataColumnDefs;
492  TableColPrivColumnsDynArray: TZMetadataColumnDefs;
493  TablePrivColumnsDynArray: TZMetadataColumnDefs;
494  BestRowIdentColumnsDynArray: TZMetadataColumnDefs;
495  TableColVerColumnsDynArray: TZMetadataColumnDefs;
496  PrimaryKeyColumnsDynArray: TZMetadataColumnDefs;
497  ImportedKeyColumnsDynArray: TZMetadataColumnDefs;
498  ExportedKeyColumnsDynArray: TZMetadataColumnDefs;
499  CrossRefColumnsDynArray: TZMetadataColumnDefs;
500  TypeInfoColumnsDynArray: TZMetadataColumnDefs;
501  IndexInfoColumnsDynArray: TZMetadataColumnDefs;
502  SequenceColumnsDynArray: TZMetadataColumnDefs;
503  UDTColumnsDynArray: TZMetadataColumnDefs;
504 
505 implementation
506 
507 uses ZVariant, ZCollections, ZMessages;
508 
509 { TZAbstractDatabaseInfo }
510 
511 {**
512  Constructs this object.
513  @param Metadata the interface of the correpsonding database metadata object
514 }
515 constructor TZAbstractDatabaseInfo.Create(const Metadata: TZAbstractDatabaseMetadata);
516 begin
517  Create(MetaData, '"');
518 end;
519 
520 {**
521  Constructs this object.
522  @param Metadata the interface of the correpsonding database metadata object
523  @param IdentifierQuotes
524  What's the string used to quote SQL identifiers?
525  This returns a space " " if identifier quoting isn't supported.
526  A JDBC Compliant<sup><font size=-2>TM</font></sup>
527  driver always uses a double quote character.
528 }
529 constructor TZAbstractDatabaseInfo.Create(const Metadata: TZAbstractDatabaseMetadata;
530  const IdentifierQuotes: String);
531 begin
532  inherited Create;
533  FMetadata := Metadata;
534  if FMetaData.FUrl.Properties.IndexOfName('identifier_quotes') > -1 then //prevent to loose emty quotes '' !!!
535  FIdentifierQuotes := FMetaData.FUrl.Properties.Values['identifier_quotes']
536  else
537  if IdentifierQuotes = '' then
538  FIdentifierQuotes := '"'
539  else
540  FIdentifierQuotes := IdentifierQuotes;
541 end;
542 
543 {**
544  Destroys this object and cleanups the memory.
545 }
546 destructor TZAbstractDatabaseInfo.Destroy;
547 begin
548  FMetadata := nil;
549  inherited;
550 end;
551 
552 //----------------------------------------------------------------------
553 // First, a variety of minor information about the target database.
554 
555 {**
556  Can all the procedures returned by getProcedures be called by the
557  current user?
558  @return <code>true</code> if so; <code>false</code> otherwise
559 }
560 function TZAbstractDatabaseInfo.AllProceduresAreCallable: Boolean;
561 begin
562  Result := True;
563 end;
564 
565 {**
566  Can all the tables returned by getTable be SELECTed by the
567  current user?
568  @return <code>true</code> if so; <code>false</code> otherwise
569 }
570 function TZAbstractDatabaseInfo.AllTablesAreSelectable: Boolean;
571 begin
572  Result := True;
573 end;
574 
575 {**
576  Is the database in read-only mode?
577  @return <code>true</code> if so; <code>false</code> otherwise
578 }
579 function TZAbstractDatabaseInfo.IsReadOnly: Boolean;
580 begin
581  Result := False;
582 end;
583 
584 {**
585  Are NULL values sorted high?
586  @return <code>true</code> if so; <code>false</code> otherwise
587 }
588 function TZAbstractDatabaseInfo.NullsAreSortedHigh: Boolean;
589 begin
590  Result := False;
591 end;
592 
593 {**
594  Are NULL values sorted low?
595  @return <code>true</code> if so; <code>false</code> otherwise
596 }
597 function TZAbstractDatabaseInfo.NullsAreSortedLow: Boolean;
598 begin
599  Result := False;
600 end;
601 
602 {**
603  Are NULL values sorted at the start regardless of sort order?
604  @return <code>true</code> if so; <code>false</code> otherwise
605 }
606 function TZAbstractDatabaseInfo.NullsAreSortedAtStart: Boolean;
607 begin
608  Result := False;
609 end;
610 
611 {**
612  Are NULL values sorted at the end regardless of sort order?
613  @return <code>true</code> if so; <code>false</code> otherwise
614 }
615 function TZAbstractDatabaseInfo.NullsAreSortedAtEnd: Boolean;
616 begin
617  Result := False;
618 end;
619 
620 {**
621  What's the name of this database product?
622  @return database product name
623 }
624 function TZAbstractDatabaseInfo.GetDatabaseProductName: string;
625 begin
626  Result := '';
627 end;
628 
629 {**
630  What's the version of this database product?
631  @return database version
632 }
633 function TZAbstractDatabaseInfo.GetDatabaseProductVersion: string;
634 begin
635  Result := '';
636 end;
637 
638 {**
639  What's the name of this JDBC driver?
640  @return JDBC driver name
641 }
642 function TZAbstractDatabaseInfo.GetDriverName: string;
643 begin
644  Result := 'Zeos Database Connectivity Driver';
645 end;
646 
647 {**
648  What's the version of this JDBC driver?
649  @return JDBC driver version
650 }
651 function TZAbstractDatabaseInfo.GetDriverVersion: string;
652 begin
653  Result := Format('%d.%d', [GetDriverMajorVersion, GetDriverMinorVersion]);
654 end;
655 
656 {**
657  What's this JDBC driver's major version number?
658  @return JDBC driver major version
659 }
660 function TZAbstractDatabaseInfo.GetDriverMajorVersion: Integer;
661 begin
662  Result := 1;
663 end;
664 
665 {**
666  What's this JDBC driver's minor version number?
667  @return JDBC driver minor version number
668 }
669 function TZAbstractDatabaseInfo.GetDriverMinorVersion: Integer;
670 begin
671  Result := 0;
672 end;
673 
674 {**
675  Returns the server version
676  @return the server version string
677 }
678 function TZAbstractDatabaseInfo.GetServerVersion: string;
679 begin
680  Result := '';
681 end;
682 
683 {**
684  Does the database store tables in a local file?
685  @return <code>true</code> if so; <code>false</code> otherwise
686 }
687 function TZAbstractDatabaseInfo.UsesLocalFiles: Boolean;
688 begin
689  Result := True;
690 end;
691 
692 {**
693  Does the database use a file for each table?
694  @return true if the database uses a local file for each table
695 }
696 function TZAbstractDatabaseInfo.UsesLocalFilePerTable: Boolean;
697 begin
698  Result := False;
699 end;
700 
701 {**
702  Does the database treat mixed case unquoted SQL identifiers as
703  case sensitive and as a result store them in mixed case?
704  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will always return false.
705  @return <code>true</code> if so; <code>false</code> otherwise
706 }
707 function TZAbstractDatabaseInfo.SupportsMixedCaseIdentifiers: Boolean;
708 begin
709  Result := False;
710 end;
711 
712 {**
713  Does the database treat mixed case unquoted SQL identifiers as
714  case insensitive and store them in upper case?
715  @return <code>true</code> if so; <code>false</code> otherwise
716 }
717 function TZAbstractDatabaseInfo.StoresUpperCaseIdentifiers: Boolean;
718 begin
719  Result := False;
720 end;
721 
722 {**
723  Does the database treat mixed case unquoted SQL identifiers as
724  case insensitive and store them in lower case?
725  @return <code>true</code> if so; <code>false</code> otherwise
726 }
727 function TZAbstractDatabaseInfo.StoresLowerCaseIdentifiers: Boolean;
728 begin
729  Result := False;
730 end;
731 
732 {**
733  Does the database treat mixed case unquoted SQL identifiers as
734  case insensitive and store them in mixed case?
735  @return <code>true</code> if so; <code>false</code> otherwise
736 }
737 function TZAbstractDatabaseInfo.StoresMixedCaseIdentifiers: Boolean;
738 begin
739  Result := True;
740 end;
741 
742 {**
743  Does the database treat mixed case quoted SQL identifiers as
744  case sensitive and as a result store them in mixed case?
745  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will always return true.
746  @return <code>true</code> if so; <code>false</code> otherwise
747 }
748 function TZAbstractDatabaseInfo.SupportsMixedCaseQuotedIdentifiers: Boolean;
749 begin
750  Result := True;
751 end;
752 
753 {**
754  Does the database treat mixed case quoted SQL identifiers as
755  case insensitive and store them in upper case?
756  @return <code>true</code> if so; <code>false</code> otherwise
757 }
758 function TZAbstractDatabaseInfo.StoresUpperCaseQuotedIdentifiers: Boolean;
759 begin
760  Result := False;
761 end;
762 
763 {**
764  Does the database treat mixed case quoted SQL identifiers as
765  case insensitive and store them in lower case?
766  @return <code>true</code> if so; <code>false</code> otherwise
767 }
768 function TZAbstractDatabaseInfo.StoresLowerCaseQuotedIdentifiers: Boolean;
769 begin
770  Result := False;
771 end;
772 
773 {**
774  Does the database treat mixed case quoted SQL identifiers as
775  case insensitive and store them in mixed case?
776  @return <code>true</code> if so; <code>false</code> otherwise
777 }
778 function TZAbstractDatabaseInfo.StoresMixedCaseQuotedIdentifiers: Boolean;
779 begin
780  Result := False;
781 end;
782 
783 {**
784  What's the string used to quote SQL identifiers?
785  This returns a space " " if identifier quoting isn't supported.
786  A JDBC Compliant<sup><font size=-2>TM</font></sup>
787  driver always uses a double quote character.
788  @return the quoting string
789 }
790 function TZAbstractDatabaseInfo.GetIdentifierQuoteString: string;
791 begin
792  Result := FIdentifierQuotes;
793 end;
794 
795 {**
796  Gets a comma-separated list of all a database's SQL keywords
797  that are NOT also SQL92 keywords.
798  @return the list
799 }
800 function TZAbstractDatabaseInfo.GetSQLKeywords: string;
801 begin
802  Result := '';
803 end;
804 
805 {**
806  Gets a comma-separated list of math functions. These are the
807  X/Open CLI math function names used in the JDBC function escape
808  clause.
809  @return the list
810 }
811 function TZAbstractDatabaseInfo.GetNumericFunctions: string;
812 begin
813  Result := '';
814 end;
815 
816 {**
817  Gets a comma-separated list of string functions. These are the
818  X/Open CLI string function names used in the JDBC function escape
819  clause.
820  @return the list
821 }
822 function TZAbstractDatabaseInfo.GetStringFunctions: string;
823 begin
824  Result := '';
825 end;
826 
827 {**
828  Gets a comma-separated list of system functions. These are the
829  X/Open CLI system function names used in the JDBC function escape
830  clause.
831  @return the list
832 }
833 function TZAbstractDatabaseInfo.GetSystemFunctions: string;
834 begin
835  Result := '';
836 end;
837 
838 {**
839  Gets a comma-separated list of time and date functions.
840  @return the list
841 }
842 function TZAbstractDatabaseInfo.GetTimeDateFunctions: string;
843 begin
844  Result := '';
845 end;
846 
847 {**
848  Gets the string that can be used to escape wildcard characters.
849  This is the string that can be used to escape '_' or '%' in
850  the string pattern style catalog search parameters.
851 
852  <P>The '_' character represents any single character.
853  <P>The '%' character represents any sequence of zero or
854  more characters.
855 
856  @return the string used to escape wildcard characters
857 }
858 function TZAbstractDatabaseInfo.GetSearchStringEscape: string;
859 begin
860  Result := '%';
861 end;
862 
863 {**
864  Gets all the "extra" characters that can be used in unquoted
865  identifier names (those beyond a-z, A-Z, 0-9 and _).
866  @return the string containing the extra characters
867 }
868 function TZAbstractDatabaseInfo.GetExtraNameCharacters: string;
869 begin
870  Result := '';
871 end;
872 
873 //--------------------------------------------------------------------
874 // Functions describing which features are supported.
875 
876 {**
877  Is "ALTER TABLE" with add column supported?
878  @return <code>true</code> if so; <code>false</code> otherwise
879 }
880 function TZAbstractDatabaseInfo.SupportsAlterTableWithAddColumn: Boolean;
881 begin
882  Result := True;
883 end;
884 
885 {**
886  Is "ALTER TABLE" with drop column supported?
887  @return <code>true</code> if so; <code>false</code> otherwise
888 }
889 function TZAbstractDatabaseInfo.SupportsAlterTableWithDropColumn: Boolean;
890 begin
891  Result := True;
892 end;
893 
894 {**
895  Is column aliasing supported?
896 
897  <P>If so, the SQL AS clause can be used to provide names for
898  computed columns or to provide alias names for columns as
899  required.
900  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
901  @return <code>true</code> if so; <code>false</code> otherwise
902 }
903 function TZAbstractDatabaseInfo.SupportsColumnAliasing: Boolean;
904 begin
905  Result := True;
906 end;
907 
908 {**
909  Are concatenations between NULL and non-NULL values NULL?
910  For SQL-92 compliance, a JDBC technology-enabled driver will
911  return <code>true</code>.
912  @return <code>true</code> if so; <code>false</code> otherwise
913 }
914 function TZAbstractDatabaseInfo.NullPlusNonNullIsNull: Boolean;
915 begin
916  Result := True;
917 end;
918 
919 {**
920  Is the CONVERT function between SQL types supported?
921  @return <code>true</code> if so; <code>false</code> otherwise
922 }
923 function TZAbstractDatabaseInfo.SupportsConvert: Boolean;
924 begin
925  Result := False;
926 end;
927 
928 {**
929  Is CONVERT between the given SQL types supported?
930  @param fromType the type to convert from
931  @param toType the type to convert to
932  @return <code>true</code> if so; <code>false</code> otherwise
933  @see Types
934 }
935 function TZAbstractDatabaseInfo.SupportsConvertForTypes(
936  FromType: TZSQLType; ToType: TZSQLType): Boolean;
937 begin
938  Result := False;
939 end;
940 
941 {**
942  Are table correlation names supported?
943  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
944  @return <code>true</code> if so; <code>false</code> otherwise
945 }
946 function TZAbstractDatabaseInfo.SupportsTableCorrelationNames: Boolean;
947 begin
948  Result := True;
949 end;
950 
951 {**
952  If table correlation names are supported, are they restricted
953  to be different from the names of the tables?
954  @return <code>true</code> if so; <code>false</code> otherwise
955 }
956 function TZAbstractDatabaseInfo.SupportsDifferentTableCorrelationNames: Boolean;
957 begin
958  Result := False;
959 end;
960 
961 {**
962  Are expressions in "ORDER BY" lists supported?
963  @return <code>true</code> if so; <code>false</code> otherwise
964 }
965 function TZAbstractDatabaseInfo.SupportsExpressionsInOrderBy: Boolean;
966 begin
967  Result := True;
968 end;
969 
970 {**
971  Can an "ORDER BY" clause use columns not in the SELECT statement?
972  @return <code>true</code> if so; <code>false</code> otherwise
973 }
974 function TZAbstractDatabaseInfo.SupportsOrderByUnrelated: Boolean;
975 begin
976  Result := True;
977 end;
978 
979 {**
980  Is some form of "GROUP BY" clause supported?
981  @return <code>true</code> if so; <code>false</code> otherwise
982 }
983 function TZAbstractDatabaseInfo.SupportsGroupBy: Boolean;
984 begin
985  Result := True;
986 end;
987 
988 {**
989  Can a "GROUP BY" clause use columns not in the SELECT?
990  @return <code>true</code> if so; <code>false</code> otherwise
991 }
992 function TZAbstractDatabaseInfo.SupportsGroupByUnrelated: Boolean;
993 begin
994  Result := True;
995 end;
996 
997 {**
998  Can a "GROUP BY" clause add columns not in the SELECT
999  provided it specifies all the columns in the SELECT?
1000  @return <code>true</code> if so; <code>false</code> otherwise
1001 }
1002 function TZAbstractDatabaseInfo.SupportsGroupByBeyondSelect: Boolean;
1003 begin
1004  Result := False;
1005 end;
1006 
1007 {**
1008  Is the escape character in "LIKE" clauses supported?
1009  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
1010  @return <code>true</code> if so; <code>false</code> otherwise
1011 }
1012 function TZAbstractDatabaseInfo.SupportsLikeEscapeClause: Boolean;
1013 begin
1014  Result := True;
1015 end;
1016 
1017 {**
1018  Are multiple <code>ResultSet</code> from a single execute supported?
1019  @return <code>true</code> if so; <code>false</code> otherwise
1020 }
1021 function TZAbstractDatabaseInfo.SupportsMultipleResultSets: Boolean;
1022 begin
1023  Result := True;
1024 end;
1025 
1026 {**
1027  Can we have multiple transactions open at once (on different
1028  connections)?
1029  @return <code>true</code> if so; <code>false</code> otherwise
1030 }
1031 function TZAbstractDatabaseInfo.SupportsMultipleTransactions: Boolean;
1032 begin
1033  Result := True;
1034 end;
1035 
1036 {**
1037  Can columns be defined as non-nullable?
1038  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
1039  @return <code>true</code> if so; <code>false</code> otherwise
1040 }
1041 function TZAbstractDatabaseInfo.SupportsNonNullableColumns: Boolean;
1042 begin
1043  Result := True;
1044 end;
1045 
1046 {**
1047  Is the ODBC Minimum SQL grammar supported?
1048  All JDBC Compliant<sup><font size=-2>TM</font></sup> drivers must return true.
1049  @return <code>true</code> if so; <code>false</code> otherwise
1050 }
1051 function TZAbstractDatabaseInfo.SupportsMinimumSQLGrammar: Boolean;
1052 begin
1053  Result := True;
1054 end;
1055 
1056 {**
1057  Is the ODBC Core SQL grammar supported?
1058  @return <code>true</code> if so; <code>false</code> otherwise
1059 }
1060 function TZAbstractDatabaseInfo.SupportsCoreSQLGrammar: Boolean;
1061 begin
1062  Result := True;
1063 end;
1064 
1065 {**
1066  Is the ODBC Extended SQL grammar supported?
1067  @return <code>true</code> if so; <code>false</code> otherwise
1068 }
1069 function TZAbstractDatabaseInfo.SupportsExtendedSQLGrammar: Boolean;
1070 begin
1071  Result := True;
1072 end;
1073 
1074 {**
1075  Is the ANSI92 entry level SQL grammar supported?
1076  All JDBC Compliant<sup><font size=-2>TM</font></sup> drivers must return true.
1077  @return <code>true</code> if so; <code>false</code> otherwise
1078 }
1079 function TZAbstractDatabaseInfo.SupportsANSI92EntryLevelSQL: Boolean;
1080 begin
1081  Result := True;
1082 end;
1083 
1084 {**
1085  Is the ANSI92 intermediate SQL grammar supported?
1086  @return <code>true</code> if so; <code>false</code> otherwise
1087 }
1088 function TZAbstractDatabaseInfo.SupportsANSI92IntermediateSQL: Boolean;
1089 begin
1090  Result := True;
1091 end;
1092 
1093 {**
1094  Is the ANSI92 full SQL grammar supported?
1095  @return <code>true</code> if so; <code>false</code> otherwise
1096 }
1097 function TZAbstractDatabaseInfo.SupportsANSI92FullSQL: Boolean;
1098 begin
1099  Result := True;
1100 end;
1101 
1102 {**
1103  Is the SQL Integrity Enhancement Facility supported?
1104  @return <code>true</code> if so; <code>false</code> otherwise
1105 }
1106 function TZAbstractDatabaseInfo.SupportsIntegrityEnhancementFacility: Boolean;
1107 begin
1108  Result := False;
1109 end;
1110 
1111 {**
1112  Is some form of outer join supported?
1113  @return <code>true</code> if so; <code>false</code> otherwise
1114 }
1115 function TZAbstractDatabaseInfo.SupportsOuterJoins: Boolean;
1116 begin
1117  Result := True;
1118 end;
1119 
1120 {**
1121  Are full nested outer joins supported?
1122  @return <code>true</code> if so; <code>false</code> otherwise
1123 }
1124 function TZAbstractDatabaseInfo.SupportsFullOuterJoins: Boolean;
1125 begin
1126  Result := True;
1127 end;
1128 
1129 {**
1130  Is there limited support for outer joins? (This will be true
1131  if supportFullOuterJoins is true.)
1132  @return <code>true</code> if so; <code>false</code> otherwise
1133 }
1134 function TZAbstractDatabaseInfo.SupportsLimitedOuterJoins: Boolean;
1135 begin
1136  Result := True;
1137 end;
1138 
1139 {**
1140  What's the database vendor's preferred term for "schema"?
1141  @return the vendor term
1142 }
1143 function TZAbstractDatabaseInfo.GetSchemaTerm: string;
1144 begin
1145  Result := 'Schema';
1146 end;
1147 
1148 {**
1149  What's the database vendor's preferred term for "procedure"?
1150  @return the vendor term
1151 }
1152 function TZAbstractDatabaseInfo.GetProcedureTerm: string;
1153 begin
1154  Result := 'Procedure';
1155 end;
1156 
1157 {**
1158  What's the database vendor's preferred term for "catalog"?
1159  @return the vendor term
1160 }
1161 function TZAbstractDatabaseInfo.GetCatalogTerm: string;
1162 begin
1163  Result := 'Catalog';
1164 end;
1165 
1166 {**
1167  Does a catalog appear at the start of a qualified table name?
1168  (Otherwise it appears at the end)
1169  @return true if it appears at the start
1170 }
1171 function TZAbstractDatabaseInfo.IsCatalogAtStart: Boolean;
1172 begin
1173  Result := False;
1174 end;
1175 
1176 {**
1177  What's the separator between catalog and table name?
1178  @return the separator string
1179 }
1180 function TZAbstractDatabaseInfo.GetCatalogSeparator: string;
1181 begin
1182  Result := '.';
1183 end;
1184 
1185 {**
1186  Can a schema name be used in a data manipulation statement?
1187  @return <code>true</code> if so; <code>false</code> otherwise
1188 }
1189 function TZAbstractDatabaseInfo.SupportsSchemasInDataManipulation: Boolean;
1190 begin
1191  Result := False;
1192 end;
1193 
1194 {**
1195  Can a schema name be used in a procedure call statement?
1196  @return <code>true</code> if so; <code>false</code> otherwise
1197 }
1198 function TZAbstractDatabaseInfo.SupportsSchemasInProcedureCalls: Boolean;
1199 begin
1200  Result := False;
1201 end;
1202 
1203 {**
1204  Can a schema name be used in a table definition statement?
1205  @return <code>true</code> if so; <code>false</code> otherwise
1206 }
1207 function TZAbstractDatabaseInfo.SupportsSchemasInTableDefinitions: Boolean;
1208 begin
1209  Result := False;
1210 end;
1211 
1212 {**
1213  Can a schema name be used in an index definition statement?
1214  @return <code>true</code> if so; <code>false</code> otherwise
1215 }
1216 function TZAbstractDatabaseInfo.SupportsSchemasInIndexDefinitions: Boolean;
1217 begin
1218  Result := False;
1219 end;
1220 
1221 {**
1222  Can a schema name be used in a privilege definition statement?
1223  @return <code>true</code> if so; <code>false</code> otherwise
1224 }
1225 function TZAbstractDatabaseInfo.SupportsSchemasInPrivilegeDefinitions: Boolean;
1226 begin
1227  Result := False;
1228 end;
1229 
1230 {**
1231  Can a catalog name be used in a data manipulation statement?
1232  @return <code>true</code> if so; <code>false</code> otherwise
1233 }
1234 function TZAbstractDatabaseInfo.SupportsCatalogsInDataManipulation: Boolean;
1235 begin
1236  Result := False;
1237 end;
1238 
1239 {**
1240  Can a catalog name be used in a procedure call statement?
1241  @return <code>true</code> if so; <code>false</code> otherwise
1242 }
1243 function TZAbstractDatabaseInfo.SupportsCatalogsInProcedureCalls: Boolean;
1244 begin
1245  Result := False;
1246 end;
1247 
1248 {**
1249  Can a catalog name be used in a table definition statement?
1250  @return <code>true</code> if so; <code>false</code> otherwise
1251 }
1252 function TZAbstractDatabaseInfo.SupportsCatalogsInTableDefinitions: Boolean;
1253 begin
1254  Result := False;
1255 end;
1256 
1257 {**
1258  Can a catalog name be used in an index definition statement?
1259  @return <code>true</code> if so; <code>false</code> otherwise
1260 }
1261 function TZAbstractDatabaseInfo.SupportsCatalogsInIndexDefinitions: Boolean;
1262 begin
1263  Result := False;
1264 end;
1265 
1266 {**
1267  Can a catalog name be used in a privilege definition statement?
1268  @return <code>true</code> if so; <code>false</code> otherwise
1269 }
1270 function TZAbstractDatabaseInfo.SupportsCatalogsInPrivilegeDefinitions: Boolean;
1271 begin
1272  Result := False;
1273 end;
1274 
1275 {**
1276  Can a stored procedure have an additional overload suffix?
1277  @return <code>true</code> if so; <code>false</code> otherwise
1278 }
1279 function TZAbstractDatabaseInfo.SupportsOverloadPrefixInStoredProcedureName: Boolean;
1280 begin
1281  Result := False;
1282 end;
1283 
1284 {**
1285  Is positioned DELETE supported?
1286  @return <code>true</code> if so; <code>false</code> otherwise
1287 }
1288 function TZAbstractDatabaseInfo.SupportsPositionedDelete: Boolean;
1289 begin
1290  Result := False;
1291 end;
1292 
1293 {**
1294  Is positioned UPDATE supported?
1295  @return <code>true</code> if so; <code>false</code> otherwise
1296 }
1297 function TZAbstractDatabaseInfo.SupportsPositionedUpdate: Boolean;
1298 begin
1299  Result := False;
1300 end;
1301 
1302 {**
1303  Is SELECT for UPDATE supported?
1304  @return <code>true</code> if so; <code>false</code> otherwise
1305 }
1306 function TZAbstractDatabaseInfo.SupportsSelectForUpdate: Boolean;
1307 begin
1308  Result := False;
1309 end;
1310 
1311 {**
1312  Are stored procedure calls using the stored procedure escape
1313  syntax supported?
1314  @return <code>true</code> if so; <code>false</code> otherwise
1315 }
1316 function TZAbstractDatabaseInfo.SupportsStoredProcedures: Boolean;
1317 begin
1318  Result := False;
1319 end;
1320 
1321 {**
1322  Are subqueries in comparison expressions supported?
1323  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
1324  @return <code>true</code> if so; <code>false</code> otherwise
1325 }
1326 function TZAbstractDatabaseInfo.SupportsSubqueriesInComparisons: Boolean;
1327 begin
1328  Result := False;
1329 end;
1330 
1331 {**
1332  Are subqueries in 'exists' expressions supported?
1333  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
1334  @return <code>true</code> if so; <code>false</code> otherwise
1335 }
1336 function TZAbstractDatabaseInfo.SupportsSubqueriesInExists: Boolean;
1337 begin
1338  Result := False;
1339 end;
1340 
1341 {**
1342  Are subqueries in 'in' statements supported?
1343  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
1344  @return <code>true</code> if so; <code>false</code> otherwise
1345 }
1346 function TZAbstractDatabaseInfo.SupportsSubqueriesInIns: Boolean;
1347 begin
1348  Result := False;
1349 end;
1350 
1351 {**
1352  Are subqueries in quantified expressions supported?
1353  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
1354  @return <code>true</code> if so; <code>false</code> otherwise
1355 }
1356 function TZAbstractDatabaseInfo.SupportsSubqueriesInQuantifieds: Boolean;
1357 begin
1358  Result := False;
1359 end;
1360 
1361 {**
1362  Are correlated subqueries supported?
1363  A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
1364  @return <code>true</code> if so; <code>false</code> otherwise
1365 }
1366 function TZAbstractDatabaseInfo.SupportsCorrelatedSubqueries: Boolean;
1367 begin
1368  Result := False;
1369 end;
1370 
1371 {**
1372  Is SQL UNION supported?
1373  @return <code>true</code> if so; <code>false</code> otherwise
1374 }
1375 function TZAbstractDatabaseInfo.SupportsUnion: Boolean;
1376 begin
1377  Result := False;
1378 end;
1379 
1380 {**
1381  Is SQL UNION ALL supported?
1382  @return <code>true</code> if so; <code>false</code> otherwise
1383 }
1384 function TZAbstractDatabaseInfo.SupportsUnionAll: Boolean;
1385 begin
1386  Result := False;
1387 end;
1388 
1389 {**
1390  Can cursors remain open across commits?
1391  @return <code>true</code> if cursors always remain open;
1392  <code>false</code> if they might not remain open
1393 }
1394 function TZAbstractDatabaseInfo.SupportsOpenCursorsAcrossCommit: Boolean;
1395 begin
1396  Result := False;
1397 end;
1398 
1399 {**
1400  Can cursors remain open across rollbacks?
1401  @return <code>true</code> if cursors always remain open;
1402  <code>false</code> if they might not remain open
1403 }
1404 function TZAbstractDatabaseInfo.SupportsOpenCursorsAcrossRollback: Boolean;
1405 begin
1406  Result := False;
1407 end;
1408 
1409 {**
1410  Can statements remain open across commits?
1411  @return <code>true</code> if statements always remain open;
1412  <code>false</code> if they might not remain open
1413 }
1414 function TZAbstractDatabaseInfo.SupportsOpenStatementsAcrossCommit: Boolean;
1415 begin
1416  Result := True;
1417 end;
1418 
1419 {**
1420  Can statements remain open across rollbacks?
1421  @return <code>true</code> if statements always remain open;
1422  <code>false</code> if they might not remain open
1423 }
1424 function TZAbstractDatabaseInfo.SupportsOpenStatementsAcrossRollback: Boolean;
1425 begin
1426  Result := True;
1427 end;
1428 
1429 //----------------------------------------------------------------------
1430 // The following group of methods exposes various limitations
1431 // based on the target database with the current driver.
1432 // Unless otherwise specified, a result of zero means there is no
1433 // limit, or the limit is not known.
1434 
1435 {**
1436  How many hex characters can you have in an inline binary literal?
1437  @return max binary literal length in hex characters;
1438  a result of zero means that there is no limit or the limit is not known
1439 }
1440 function TZAbstractDatabaseInfo.GetMaxBinaryLiteralLength: Integer;
1441 begin
1442  Result := 0;
1443 end;
1444 
1445 {**
1446  What's the max length for a character literal?
1447  @return max literal length;
1448  a result of zero means that there is no limit or the limit is not known
1449 }
1450 function TZAbstractDatabaseInfo.GetMaxCharLiteralLength: Integer;
1451 begin
1452  Result := 0;
1453 end;
1454 
1455 {**
1456  What's the limit on column name length?
1457  @return max column name length;
1458  a result of zero means that there is no limit or the limit is not known
1459 }
1460 function TZAbstractDatabaseInfo.GetMaxColumnNameLength: Integer;
1461 begin
1462  Result := 0;
1463 end;
1464 
1465 {**
1466  What's the maximum number of columns in a "GROUP BY" clause?
1467  @return max number of columns;
1468  a result of zero means that there is no limit or the limit is not known
1469 }
1470 function TZAbstractDatabaseInfo.GetMaxColumnsInGroupBy: Integer;
1471 begin
1472  Result := 0;
1473 end;
1474 
1475 {**
1476  What's the maximum number of columns allowed in an index?
1477  @return max number of columns;
1478  a result of zero means that there is no limit or the limit is not known
1479 }
1480 function TZAbstractDatabaseInfo.GetMaxColumnsInIndex: Integer;
1481 begin
1482  Result := 0;
1483 end;
1484 
1485 {**
1486  What's the maximum number of columns in an "ORDER BY" clause?
1487  @return max number of columns;
1488  a result of zero means that there is no limit or the limit is not known
1489 }
1490 function TZAbstractDatabaseInfo.GetMaxColumnsInOrderBy: Integer;
1491 begin
1492  Result := 0;
1493 end;
1494 
1495 {**
1496  What's the maximum number of columns in a "SELECT" list?
1497  @return max number of columns;
1498  a result of zero means that there is no limit or the limit is not known
1499 }
1500 function TZAbstractDatabaseInfo.GetMaxColumnsInSelect: Integer;
1501 begin
1502  Result := 0;
1503 end;
1504 
1505 {**
1506  What's the maximum number of columns in a table?
1507  @return max number of columns;
1508  a result of zero means that there is no limit or the limit is not known
1509 }
1510 function TZAbstractDatabaseInfo.GetMaxColumnsInTable: Integer;
1511 begin
1512  Result := 0;
1513 end;
1514 
1515 {**
1516  How many active connections can we have at a time to this database?
1517  @return max number of active connections;
1518  a result of zero means that there is no limit or the limit is not known
1519 }
1520 function TZAbstractDatabaseInfo.GetMaxConnections: Integer;
1521 begin
1522  Result := 0;
1523 end;
1524 
1525 {**
1526  What's the maximum cursor name length?
1527  @return max cursor name length in bytes;
1528  a result of zero means that there is no limit or the limit is not known
1529 }
1530 function TZAbstractDatabaseInfo.GetMaxCursorNameLength: Integer;
1531 begin
1532  Result := 0;
1533 end;
1534 
1535 {**
1536  Retrieves the maximum number of bytes for an index, including all
1537  of the parts of the index.
1538  @return max index length in bytes, which includes the composite of all
1539  the constituent parts of the index;
1540  a result of zero means that there is no limit or the limit is not known
1541 }
1542 function TZAbstractDatabaseInfo.GetMaxIndexLength: Integer;
1543 begin
1544  Result := 0;
1545 end;
1546 
1547 {**
1548  What's the maximum length allowed for a schema name?
1549  @return max name length in bytes;
1550  a result of zero means that there is no limit or the limit is not known
1551 }
1552 function TZAbstractDatabaseInfo.GetMaxSchemaNameLength: Integer;
1553 begin
1554  Result := 0;
1555 end;
1556 
1557 {**
1558  What's the maximum length of a procedure name?
1559  @return max name length in bytes;
1560  a result of zero means that there is no limit or the limit is not known
1561 }
1562 function TZAbstractDatabaseInfo.GetMaxProcedureNameLength: Integer;
1563 begin
1564  Result := 0;
1565 end;
1566 
1567 {**
1568  What's the maximum length of a catalog name?
1569  @return max name length in bytes;
1570  a result of zero means that there is no limit or the limit is not known
1571 }
1572 function TZAbstractDatabaseInfo.GetMaxCatalogNameLength: Integer;
1573 begin
1574  Result := 0;
1575 end;
1576 
1577 {**
1578  What's the maximum length of a single row?
1579  @return max row size in bytes;
1580  a result of zero means that there is no limit or the limit is not known
1581 }
1582 function TZAbstractDatabaseInfo.GetMaxRowSize: Integer;
1583 begin
1584  Result := 0;
1585 end;
1586 
1587 {**
1588  Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
1589  blobs?
1590  @return <code>true</code> if so; <code>false</code> otherwise
1591 }
1592 function TZAbstractDatabaseInfo.DoesMaxRowSizeIncludeBlobs: Boolean;
1593 begin
1594  Result := True;
1595 end;
1596 
1597 {**
1598  What's the maximum length of an SQL statement?
1599  @return max length in bytes;
1600  a result of zero means that there is no limit or the limit is not known
1601 }
1602 function TZAbstractDatabaseInfo.GetMaxStatementLength: Integer;
1603 begin
1604  Result := 0;
1605 end;
1606 
1607 {**
1608  How many active statements can we have open at one time to this
1609  database?
1610  @return the maximum number of statements that can be open at one time;
1611  a result of zero means that there is no limit or the limit is not known
1612 }
1613 function TZAbstractDatabaseInfo.GetMaxStatements: Integer;
1614 begin
1615  Result := 0;
1616 end;
1617 
1618 {**
1619  What's the maximum length of a table name?
1620  @return max name length in bytes;
1621  a result of zero means that there is no limit or the limit is not known
1622 }
1623 function TZAbstractDatabaseInfo.GetMaxTableNameLength: Integer;
1624 begin
1625  Result := 0;
1626 end;
1627 
1628 {**
1629  What's the maximum number of tables in a SELECT statement?
1630  @return the maximum number of tables allowed in a SELECT statement;
1631  a result of zero means that there is no limit or the limit is not known
1632 }
1633 function TZAbstractDatabaseInfo.GetMaxTablesInSelect: Integer;
1634 begin
1635  Result := 0;
1636 end;
1637 
1638 {**
1639  What's the maximum length of a user name?
1640  @return max user name length in bytes;
1641  a result of zero means that there is no limit or the limit is not known
1642 }
1643 function TZAbstractDatabaseInfo.GetMaxUserNameLength: Integer;
1644 begin
1645  Result := 0;
1646 end;
1647 
1648 //----------------------------------------------------------------------
1649 
1650 {**
1651  What's the database's default transaction isolation level? The
1652  values are defined in <code>java.sql.Connection</code>.
1653  @return the default isolation level
1654  @see Connection
1655 }
1656 function TZAbstractDatabaseInfo.GetDefaultTransactionIsolation:
1657  TZTransactIsolationLevel;
1658 begin
1659  Result := tiReadCommitted;
1660 end;
1661 
1662 {**
1663  Are transactions supported? If not, invoking the method
1664  <code>commit</code> is a noop and the isolation level is TRANSACTION_NONE.
1665  @return <code>true</code> if transactions are supported; <code>false</code> otherwise
1666 }
1667 function TZAbstractDatabaseInfo.SupportsTransactions: Boolean;
1668 begin
1669  Result := True;
1670 end;
1671 
1672 {**
1673  Does this database support the given transaction isolation level?
1674  @param level the values are defined in <code>java.sql.Connection</code>
1675  @return <code>true</code> if so; <code>false</code> otherwise
1676  @see Connection
1677 }
1678 function TZAbstractDatabaseInfo.SupportsTransactionIsolationLevel(
1679  Level: TZTransactIsolationLevel): Boolean;
1680 begin
1681  Result := True;
1682 end;
1683 
1684 {**
1685  Are both data definition and data manipulation statements
1686  within a transaction supported?
1687  @return <code>true</code> if so; <code>false</code> otherwise
1688 }
1689 function TZAbstractDatabaseInfo.
1690  SupportsDataDefinitionAndDataManipulationTransactions: Boolean;
1691 begin
1692  Result := True;
1693 end;
1694 
1695 {**
1696  Are only data manipulation statements within a transaction
1697  supported?
1698  @return <code>true</code> if so; <code>false</code> otherwise
1699 }
1700 function TZAbstractDatabaseInfo.
1701  SupportsDataManipulationTransactionsOnly: Boolean;
1702 begin
1703  Result := False;
1704 end;
1705 
1706 {**
1707  Does a data definition statement within a transaction force the
1708  transaction to commit?
1709  @return <code>true</code> if so; <code>false</code> otherwise
1710 }
1711 function TZAbstractDatabaseInfo.DataDefinitionCausesTransactionCommit: Boolean;
1712 begin
1713  Result := True;
1714 end;
1715 
1716 {**
1717  Is a data definition statement within a transaction ignored?
1718  @return <code>true</code> if so; <code>false</code> otherwise
1719 }
1720 function TZAbstractDatabaseInfo.DataDefinitionIgnoredInTransactions: Boolean;
1721 begin
1722  Result := False;
1723 end;
1724 
1725 {**
1726  Does the database support the given result set type?
1727  @param type defined in <code>java.sql.ResultSet</code>
1728  @return <code>true</code> if so; <code>false</code> otherwise
1729 }
1730 function TZAbstractDatabaseInfo.SupportsResultSetType(
1731  _Type: TZResultSetType): Boolean;
1732 begin
1733  Result := True;
1734 end;
1735 
1736 {**
1737  Does the database support the concurrency type in combination
1738  with the given result set type?
1739 
1740  @param type defined in <code>java.sql.ResultSet</code>
1741  @param concurrency type defined in <code>java.sql.ResultSet</code>
1742  @return <code>true</code> if so; <code>false</code> otherwise
1743 }
1744 function TZAbstractDatabaseInfo.SupportsResultSetConcurrency(
1745  _Type: TZResultSetType; Concurrency: TZResultSetConcurrency): Boolean;
1746 begin
1747  Result := True;
1748 end;
1749 
1750 {**
1751  Indicates whether the driver supports batch updates.
1752  @return true if the driver supports batch updates; false otherwise
1753 }
1754 function TZAbstractDatabaseInfo.SupportsBatchUpdates: Boolean;
1755 begin
1756  Result := True;
1757 end;
1758 
1759 {**
1760  Does the Database or Actual Version understand non escaped search strings?
1761  @return <code>true</code> if the DataBase does understand non escaped
1762  search strings
1763 }
1764 function TZAbstractDatabaseInfo.SupportsNonEscapedSearchStrings: Boolean;
1765 begin
1766  Result := False;
1767 end;
1768 
1769 {**
1770  Does the Database support updating auto incremental fields?
1771  @return <code>true</code> if the DataBase allows it.
1772 }
1773 function TZAbstractDatabaseInfo.SupportsUpdateAutoIncrementFields: Boolean;
1774 begin
1775  Result := True;
1776 end;
1777 
1778 { TZAbstractDatabaseMetadata }
1779 
1780 {**
1781  Constructs this object and assignes the main properties.
1782  @param Connection a database connection object.
1783  @param Url a database connection url string.
1784 }
1785 constructor TZAbstractDatabaseMetadata.Create(Connection: TZAbstractConnection;
1786  const Url: TZURL);
1787 begin
1788  inherited Create(Connection as IZConnection);
1789  FIC := Self.GetIdentifierConvertor;
1790  FConnection := Pointer(Connection as IZConnection);
1791  FUrl := Url;
1792  FCachedResultSets := TZHashMap.Create;
1793  FDatabaseInfo := CreateDatabaseInfo;
1794  FDatabase := Url.Database;
1795  FConSettings := IZConnection(FConnection).GetConSettings;
1796  FillWildcards;
1797 end;
1798 
1799 function TZAbstractDatabaseMetadata.GetInfo: TStrings;
1800 begin
1801  Result := FURL.Properties;
1802 end;
1803 
1804 function TZAbstractDatabaseMetadata.GetURLString: String;
1805 begin
1806  Result := FURL.URL;
1807 end;
1808 
1809 {**
1810  Remove escapes from pattren string
1811  @param Pattern a sql pattern
1812  @return string without escapes
1813 }
1814 function TZAbstractDatabaseMetadata.StripEscape(const Pattern: string): string;
1815 var
1816  I: Integer;
1817  PreviousChar: Char;
1818  EscapeChar: string;
1819 begin
1820  PreviousChar := #0;
1821  Result := '';
1822  EscapeChar := GetDatabaseInfo.GetSearchStringEscape;
1823  for I := 1 to Length(Pattern) do
1824  begin
1825  if (Pattern[i] <> EscapeChar) then
1826  begin
1827  Result := Result + Pattern[I];
1828  PreviousChar := Pattern[I];
1829  end
1830  else
1831  begin
1832  if (PreviousChar = EscapeChar) then
1833  begin
1834  Result := Result + Pattern[I];
1835  PreviousChar := #0;
1836  end
1837  else
1838  PreviousChar := Pattern[i];
1839  end;
1840  end;
1841 end;
1842 
1843 {**
1844  Check if pattern does not contain wildcards
1845  @param Pattern a sql pattern
1846  @return if pattern contain wildcards return true otherwise false
1847 }
1848 function TZAbstractDatabaseMetadata.HasNoWildcards(const Pattern: string
1849  ): boolean;
1850 var
1851  I: Integer;
1852  PreviousCharWasEscape: Boolean;
1853  EscapeChar,PreviousChar: Char;
1854  WildcardsSet: TZWildcardsSet;
1855 begin
1856  Result := False;
1857  PreviousChar := #0;
1858  PreviousCharWasEscape := False;
1859  EscapeChar := Char(GetDatabaseInfo.GetSearchStringEscape[1]);
1860  WildcardsSet := GetWildcardsSet;
1861  for I := 1 to Length(Pattern) do
1862  begin
1863  if (not PreviousCharWasEscape) and CharInset(Pattern[I], WildcardsSet) then
1864  Exit;
1865 
1866  PreviousCharWasEscape := (Pattern[I] = EscapeChar) and (PreviousChar <> EscapeChar);
1867  if (PreviousCharWasEscape) and (Pattern[I] = EscapeChar) then
1868  PreviousChar := #0
1869  else
1870  PreviousChar := Pattern[I];
1871  end;
1872  Result := True;
1873 end;
1874 
1875 function TZAbstractDatabaseMetadata.EscapeString(const S: string): string;
1876 begin
1877  Result := '''' + S + '''';
1878 end;
1879 
1880 function TZAbstractDatabaseMetadata.DecomposeObjectString(const S: String): String;
1881 begin
1882  if IC.IsQuoted(s) then
1883  Result := IC.ExtractQuote(s)
1884  else
1885  Result := s;
1886 end;
1887 
1888 {** Destroys this object and cleanups the memory.}
1889 destructor TZAbstractDatabaseMetadata.Destroy;
1890 begin
1891  FIC := nil;
1892  FUrl := nil;
1893  FCachedResultSets.Clear;
1894  FCachedResultSets := nil;
1895  FDatabaseInfo := nil;
1896 
1897  inherited Destroy;
1898 end;
1899 
1900 {**
1901  Constructs a database information object and returns the interface to it. Used
1902  internally by the constructor.
1903  @return the database information object interface
1904 }
1905 function TZAbstractDatabaseMetadata.CreateDatabaseInfo: IZDatabaseInfo;
1906 begin
1907  Result := TZAbstractDatabaseInfo.Create(Self);
1908 end;
1909 
1910 {**
1911  Creates and returns a statement object.
1912  @return the statement object
1913 }
1914 function TZAbstractDatabaseMetadata.GetStatement: IZSTatement;
1915 begin
1916  Result := GetConnection.CreateStatement;
1917 end;
1918 
1919 {**
1920  Retrieves the connection that produced this metadata object.
1921  @return the connection that produced this metadata object
1922 }
1923 function TZAbstractDatabaseMetadata.GetConnection: IZConnection;
1924 begin
1925  Result := IZConnection(FConnection);
1926 end;
1927 
1928 {**
1929  Constructs a virtual result set object.
1930  @param ColumnsDefs an array of column definition objects.
1931  @return a created result set.
1932 }
1933 function TZAbstractDatabaseMetadata.ConstructVirtualResultSet(
1934  ColumnsDefs: TZMetadataColumnDefs): IZVirtualResultSet;
1935 var
1936  I: Integer;
1937  ColumnInfo: TZColumnInfo;
1938  ColumnsInfo: TObjectList;
1939 begin
1940  ColumnsInfo := TObjectList.Create(True);
1941  try
1942  for I := 0 to High(ColumnsDefs) do
1943  begin
1944  ColumnInfo := TZColumnInfo.Create;
1945  with ColumnInfo do
1946  begin
1947  ColumnLabel := ColumnsDefs[I].Name;
1948  ColumnType := ColumnsDefs[I].SQLType;
1949  ColumnDisplaySize := ColumnsDefs[I].Length;
1950  Precision := ColumnsDefs[I].Length;
1951  end;
1952  ColumnsInfo.Add(ColumnInfo);
1953  end;
1954 
1955  Result := TZVirtualResultSet.CreateWithColumns(ColumnsInfo, '',
1956  IZConnection(FConnection).GetConSettings);
1957  with Result do
1958  begin
1959  SetType(rtScrollInsensitive);
1960  SetConcurrency(rcUpdatable);
1961  end;
1962  finally
1963  ColumnsInfo.Free;
1964  end;
1965 end;
1966 
1967 {**
1968  Clears all cached metadata.
1969 }
1970 procedure TZAbstractDatabaseMetadata.ClearCache;
1971 begin
1972  FCachedResultSets.Clear;
1973 end;
1974 
1975 {**
1976  Clears specific cached metadata.
1977 }
1978 procedure TZAbstractDatabaseMetadata.ClearCache(const Key: string);
1979 var
1980  TempKey: IZAnyValue;
1981 begin
1982  TempKey := TZAnyValue.CreateWithString(Key);
1983  FCachedResultSets.Remove(TempKey);
1984 end;
1985 
1986 {**
1987  Adds resultset to the internal cache.
1988  @param Key a resultset unique key value.
1989  @param ResultSet a resultset interface.
1990 }
1991 procedure TZAbstractDatabaseMetadata.AddResultSetToCache(const Key: string;
1992  ResultSet: IZResultSet);
1993 var
1994  TempKey: IZAnyValue;
1995 begin
1996  TempKey := TZAnyValue.CreateWithString(Key);
1997  FCachedResultSets.Put(TempKey, CloneCachedResultSet(ResultSet));
1998 end;
1999 
2000 {**
2001  Gets a resultset interface from the internal cache by key.
2002  @param Key a resultset unique key value.
2003  @returns a cached resultset interface or <code>nil</code> otherwise.
2004 }
2005 function TZAbstractDatabaseMetadata.GetResultSetFromCache(
2006  const Key: string): IZResultSet;
2007 var
2008  TempKey: IZAnyValue;
2009 begin
2010  TempKey := TZAnyValue.CreateWithString(Key);
2011  Result := FCachedResultSets.Get(TempKey) as IZResultSet;
2012  if Result <> nil then
2013  Result := CloneCachedResultSet(Result);
2014 end;
2015 
2016 {**
2017  Copies on result set to another one from the current position.
2018  @param SrcResultSet a source result set.
2019  @param DestResultSet a destination result set.
2020  @returns a destination result set.
2021 }
2022 function TZAbstractDatabaseMetadata.CopyToVirtualResultSet(
2023  SrcResultSet: IZResultSet; DestResultSet: IZVirtualResultSet):
2024  IZVirtualResultSet;
2025 var
2026  I: Integer;
2027  Metadata: IZResultSetMetadata;
2028 begin
2029  DestResultSet.SetType(rtScrollInsensitive);
2030  DestResultSet.SetConcurrency(rcUpdatable);
2031 
2032  Metadata := SrcResultSet.GetMetadata;
2033  while SrcResultSet.Next do
2034  begin
2035  DestResultSet.MoveToInsertRow;
2036  for I := 1 to Metadata.GetColumnCount do
2037  begin
2038  case Metadata.GetColumnType(I) of
2039  stBoolean:
2040  DestResultSet.UpdateBoolean(I, SrcResultSet.GetBoolean(I));
2041  stByte:
2042  DestResultSet.UpdateByte(I, SrcResultSet.GetByte(I));
2043  stShort:
2044  DestResultSet.UpdateShort(I, SrcResultSet.GetShort(I));
2045  stInteger:
2046  DestResultSet.UpdateInt(I, SrcResultSet.GetInt(I));
2047  stLong:
2048  DestResultSet.UpdateLong(I, SrcResultSet.GetLong(I));
2049  stFloat:
2050  DestResultSet.UpdateFloat(I, SrcResultSet.GetFloat(I));
2051  stDouble:
2052  DestResultSet.UpdateDouble(I, SrcResultSet.GetDouble(I));
2053  stBigDecimal:
2054  DestResultSet.UpdateBigDecimal(I, SrcResultSet.GetBigDecimal(I));
2055  stString:
2056  DestResultSet.UpdateString(I, SrcResultSet.GetString(I));
2057  stUnicodeString:
2058  DestResultSet.UpdateUnicodeString(I, SrcResultSet.GetUnicodeString(I));
2059  stBytes:
2060  DestResultSet.UpdateBytes(I, SrcResultSet.GetBytes(I));
2061  stDate:
2062  DestResultSet.UpdateDate(I, SrcResultSet.GetDate(I));
2063  stTime:
2064  DestResultSet.UpdateTime(I, SrcResultSet.GetTime(I));
2065  stTimestamp:
2066  DestResultSet.UpdateTimestamp(I, SrcResultSet.GetTimestamp(I));
2067  stAsciiStream,
2068  stUnicodeStream,
2069  stBinaryStream:
2070  DestResultSet.UpdateString(I, SrcResultSet.GetString(I));
2071  end;
2072  if SrcResultSet.WasNull then
2073  DestResultSet.UpdateNull(I);
2074  end;
2075  DestResultSet.InsertRow;
2076  end;
2077 
2078  DestResultSet.BeforeFirst;
2079  DestResultSet.SetConcurrency(rcReadOnly);
2080  Result := DestResultSet;
2081 end;
2082 
2083 {**
2084  Clones the cached resultset.
2085  @param ResultSet the resultset to be cloned.
2086  @returns the clone of the specified resultset.
2087 }
2088 function TZAbstractDatabaseMetadata.CloneCachedResultSet(
2089  ResultSet: IZResultSet): IZResultSet;
2090 var
2091  I: Integer;
2092  Metadata: IZResultSetMetadata;
2093  ColumnInfo: TZColumnInfo;
2094  ColumnsInfo: TObjectList;
2095 begin
2096  Result := nil;
2097  Metadata := ResultSet.GetMetadata;
2098  ColumnsInfo := TObjectList.Create(True);
2099  try
2100  for I := 1 to Metadata.GetColumnCount do
2101  begin
2102  ColumnInfo := TZColumnInfo.Create;
2103  with ColumnInfo do
2104  begin
2105  ColumnLabel := Metadata.GetColumnLabel(I);
2106  ColumnType := Metadata.GetColumnType(I);
2107  ColumnDisplaySize := Metadata.GetPrecision(I);
2108  Precision := Metadata.GetPrecision(I);
2109  end;
2110  ColumnsInfo.Add(ColumnInfo);
2111  end;
2112 
2113  ResultSet.BeforeFirst;
2114  Result := CopyToVirtualResultSet(ResultSet,
2115  TZVirtualResultSet.CreateWithColumns(ColumnsInfo, '',
2116  IZConnection(Self.FConnection).GetConSettings));
2117  ResultSet.BeforeFirst;
2118  finally
2119  ColumnsInfo.Free;
2120  end;
2121 end;
2122 
2123 {**
2124  Takes a name patternand column name and retuen an appropriate SQL clause
2125  @param Pattern a sql pattren
2126  @parma Column a sql column name
2127  @return processed string for query
2128 }
2129 function TZAbstractDatabaseMetadata.ConstructNameCondition(Pattern: string;
2130  Column: string): string;
2131 const
2132  Spaces = '';
2133 var
2134  WorkPattern: string;
2135 begin
2136  Result := '';
2137  if (Length(Pattern) > 2 * 31) then
2138  raise EZSQLException.Create(SPattern2Long);
2139 
2140  if (Pattern = '%') or (Pattern = '') then
2141  Exit;
2142  WorkPattern:=NormalizePatternCase(Pattern);
2143  if HasNoWildcards(WorkPattern) then
2144  begin
2145  WorkPattern := StripEscape(WorkPattern);
2146  Result := Format('%s = %s', [Column, EscapeString(WorkPattern)]);
2147  end
2148  else
2149  begin
2150  Result := Format('%s like %s',
2151  [Column, EscapeString(WorkPattern+'%')]);
2152  end;
2153 end;
2154 
2155 {**
2156  What's the url for this database?
2157  @return the url or null if it cannot be generated
2158 }
2159 function TZAbstractDatabaseMetadata.GetURL: string;
2160 begin
2161  Result := GetURLString;
2162 end;
2163 
2164 {**
2165  What's our user name as known to the database?
2166  @return our database user name
2167 }
2168 function TZAbstractDatabaseMetadata.GetUserName: string;
2169 begin
2170  Result := FURL.UserName;
2171 end;
2172 
2173 {**
2174  Returns general information about the database (version, capabilities,
2175  policies, etc).
2176  @return the database information object interface.
2177 }
2178 function TZAbstractDatabaseMetadata.GetDatabaseInfo: IZDatabaseInfo;
2179 begin
2180  Result := FDatabaseInfo;
2181 end;
2182 
2183 {**
2184  Gets a description of the stored procedures available in a
2185  catalog.
2186 
2187  <P>Only procedure descriptions matching the schema and
2188  procedure name criteria are returned. They are ordered by
2189  PROCEDURE_SCHEM, and PROCEDURE_NAME.
2190 
2191  <P>Each procedure description has the the following columns:
2192  <OL>
2193  <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
2194  <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
2195  <LI><B>PROCEDURE_NAME</B> String => procedure name
2196  <LI> reserved for future use
2197  <LI> reserved for future use
2198  <LI> reserved for future use
2199  <LI><B>REMARKS</B> String => explanatory comment on the procedure
2200  <LI><B>PROCEDURE_TYPE</B> short => kind of procedure:
2201  <UL>
2202  <LI> procedureResultUnknown - May return a result
2203  <LI> procedureNoResult - Does not return a result
2204  <LI> procedureReturnsResult - Returns a result
2205  </UL>
2206  </OL>
2207 
2208  @param catalog a catalog name; "" retrieves those without a
2209  catalog; null means drop catalog name from the selection criteria
2210  @param schemaPattern a schema name pattern; "" retrieves those
2211  without a schema
2212  @param procedureNamePattern a procedure name pattern
2213  @return <code>ResultSet</code> - each row is a procedure description
2214  @see #getSearchStringEscape
2215 }
2216 function TZAbstractDatabaseMetadata.GetProcedures(const Catalog: string;
2217  const SchemaPattern: string; const ProcedureNamePattern: string): IZResultSet;
2218 var
2219  Key: string;
2220 begin
2221  if not GetConnection.UseMetadata then
2222  begin
2223  Result := ConstructVirtualResultSet(ProceduresColumnsDynArray);
2224  exit;
2225  end;
2226 
2227  Key := GetProceduresCacheKey(Catalog, SchemaPattern, ProcedureNamePattern);
2228 
2229  Result := GetResultSetFromCache(Key);
2230  if Result = nil then
2231  begin
2232  Result := UncachedGetProcedures(Catalog, SchemaPattern, ProcedureNamePattern);
2233  AddResultSetToCache(Key, Result);
2234  end;
2235 end;
2236 
2237 {**
2238  Gets a description of the stored procedures available in a
2239  catalog.
2240 
2241  <P>Only procedure descriptions matching the schema and
2242  procedure name criteria are returned. They are ordered by
2243  PROCEDURE_SCHEM, and PROCEDURE_NAME.
2244 
2245  <P>Each procedure description has the the following columns:
2246  <OL>
2247  <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
2248  <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
2249  <LI><B>PROCEDURE_NAME</B> String => procedure name
2250  <LI> reserved for future use
2251  <LI> reserved for future use
2252  <LI> reserved for future use
2253  <LI><B>REMARKS</B> String => explanatory comment on the procedure
2254  <LI><B>PROCEDURE_TYPE</B> short => kind of procedure:
2255  <UL>
2256  <LI> procedureResultUnknown - May return a result
2257  <LI> procedureNoResult - Does not return a result
2258  <LI> procedureReturnsResult - Returns a result
2259  </UL>
2260  </OL>
2261 
2262  @param catalog a catalog name; "" retrieves those without a
2263  catalog; null means drop catalog name from the selection criteria
2264  @param schemaPattern a schema name pattern; "" retrieves those
2265  without a schema
2266  @param procedureNamePattern a procedure name pattern
2267  @return <code>ResultSet</code> - each row is a procedure description
2268  @see #getSearchStringEscape
2269 }
2270 function TZAbstractDatabaseMetadata.UncachedGetProcedures(const Catalog: string;
2271  const SchemaPattern: string; const ProcedureNamePattern: string): IZResultSet;
2272 begin
2273  Result := ConstructVirtualResultSet(ProceduresColumnsDynArray);
2274 end;
2275 
2276 {**
2277  Gets a description of a catalog's stored procedure parameters
2278  and result columns.
2279 
2280  <P>Only descriptions matching the schema, procedure and
2281  parameter name criteria are returned. They are ordered by
2282  PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value,
2283  if any, is first. Next are the parameter descriptions in call
2284  order. The column descriptions follow in column number order.
2285 
2286  <P>Each row in the <code>ResultSet</code> is a parameter description or
2287  column description with the following fields:
2288  <OL>
2289  <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
2290  <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
2291  <LI><B>PROCEDURE_NAME</B> String => procedure name
2292  <LI><B>COLUMN_NAME</B> String => column/parameter name
2293  <LI><B>COLUMN_TYPE</B> Short => kind of column/parameter:
2294  <UL>
2295  <LI> procedureColumnUnknown - nobody knows
2296  <LI> procedureColumnIn - IN parameter
2297  <LI> procedureColumnInOut - INOUT parameter
2298  <LI> procedureColumnOut - OUT parameter
2299  <LI> procedureColumnReturn - procedure return value
2300  <LI> procedureColumnResult - result column in <code>ResultSet</code>
2301  </UL>
2302  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
2303  <LI><B>TYPE_NAME</B> String => SQL type name, for a UDT type the
2304  type name is fully qualified
2305  <LI><B>PRECISION</B> int => precision
2306  <LI><B>LENGTH</B> int => length in bytes of data
2307  <LI><B>SCALE</B> short => scale
2308  <LI><B>RADIX</B> short => radix
2309  <LI><B>NULLABLE</B> short => can it contain NULL?
2310  <UL>
2311  <LI> procedureNoNulls - does not allow NULL values
2312  <LI> procedureNullable - allows NULL values
2313  <LI> procedureNullableUnknown - nullability unknown
2314  </UL>
2315  <LI><B>REMARKS</B> String => comment describing parameter/column
2316  </OL>
2317 
2318  <P><B>Note:</B> Some databases may not return the column
2319  descriptions for a procedure. Additional columns beyond
2320  REMARKS can be defined by the database.
2321 
2322  @param catalog a catalog name; "" retrieves those without a
2323  catalog; null means drop catalog name from the selection criteria
2324  @param schemaPattern a schema name pattern; "" retrieves those
2325  without a schema
2326  @param procedureNamePattern a procedure name pattern
2327  @param columnNamePattern a column name pattern
2328  @return <code>ResultSet</code> - each row describes a stored procedure parameter or
2329  column
2330  @see #getSearchStringEscape
2331 }
2332 function TZAbstractDatabaseMetadata.GetProcedureColumns(const Catalog: string;
2333  const SchemaPattern: string; const ProcedureNamePattern: string;
2334  const ColumnNamePattern: string): IZResultSet;
2335 var
2336  Key: string;
2337 begin
2338  if not GetConnection.UseMetadata then
2339  begin
2340  Result := ConstructVirtualResultSet(ProceduresColColumnsDynArray);
2341  exit;
2342  end;
2343 
2344  Key := GetProcedureColumnsCacheKey(Catalog, SchemaPattern, ProcedureNamePattern,
2345  ColumnNamePattern);
2346  Result := GetResultSetFromCache(Key);
2347  if Result = nil then
2348  begin
2349  Result := UncachedGetProcedureColumns(Catalog, SchemaPattern, ProcedureNamePattern, ColumnNamePattern);
2350  AddResultSetToCache(Key, Result);
2351  end;
2352 end;
2353 
2354 {**
2355  Gets a description of a catalog's stored procedure parameters
2356  and result columns.
2357 
2358  <P>Only descriptions matching the schema, procedure and
2359  parameter name criteria are returned. They are ordered by
2360  PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value,
2361  if any, is first. Next are the parameter descriptions in call
2362  order. The column descriptions follow in column number order.
2363 
2364  <P>Each row in the <code>ResultSet</code> is a parameter description or
2365  column description with the following fields:
2366  <OL>
2367  <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
2368  <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
2369  <LI><B>PROCEDURE_NAME</B> String => procedure name
2370  <LI><B>COLUMN_NAME</B> String => column/parameter name
2371  <LI><B>COLUMN_TYPE</B> Short => kind of column/parameter:
2372  <UL>
2373  <LI> procedureColumnUnknown - nobody knows
2374  <LI> procedureColumnIn - IN parameter
2375  <LI> procedureColumnInOut - INOUT parameter
2376  <LI> procedureColumnOut - OUT parameter
2377  <LI> procedureColumnReturn - procedure return value
2378  <LI> procedureColumnResult - result column in <code>ResultSet</code>
2379  </UL>
2380  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
2381  <LI><B>TYPE_NAME</B> String => SQL type name, for a UDT type the
2382  type name is fully qualified
2383  <LI><B>PRECISION</B> int => precision
2384  <LI><B>LENGTH</B> int => length in bytes of data
2385  <LI><B>SCALE</B> short => scale
2386  <LI><B>RADIX</B> short => radix
2387  <LI><B>NULLABLE</B> short => can it contain NULL?
2388  <UL>
2389  <LI> procedureNoNulls - does not allow NULL values
2390  <LI> procedureNullable - allows NULL values
2391  <LI> procedureNullableUnknown - nullability unknown
2392  </UL>
2393  <LI><B>REMARKS</B> String => comment describing parameter/column
2394  </OL>
2395 
2396  <P><B>Note:</B> Some databases may not return the column
2397  descriptions for a procedure. Additional columns beyond
2398  REMARKS can be defined by the database.
2399 
2400  @param catalog a catalog name; "" retrieves those without a
2401  catalog; null means drop catalog name from the selection criteria
2402  @param schemaPattern a schema name pattern; "" retrieves those
2403  without a schema
2404  @param procedureNamePattern a procedure name pattern
2405  @param columnNamePattern a column name pattern
2406  @return <code>ResultSet</code> - each row describes a stored procedure parameter or
2407  column
2408  @see #getSearchStringEscape
2409 }
2410 function TZAbstractDatabaseMetadata.UncachedGetProcedureColumns(const Catalog: string;
2411  const SchemaPattern: string; const ProcedureNamePattern: string;
2412  const ColumnNamePattern: string): IZResultSet;
2413 begin
2414  Result := ConstructVirtualResultSet(ProceduresColColumnsDynArray);
2415 end;
2416 
2417 function TZAbstractDatabaseMetadata.GetTriggers(const Catalog: string; const SchemaPattern: string;
2418  const TableNamePattern: string; const TriggerNamePattern: string): IZResultSet;
2419 var
2420  Key: string;
2421 begin
2422  if not GetConnection.UseMetadata then
2423  begin
2424  Result := ConstructVirtualResultSet(TriggersColumnsDynArray);
2425  exit;
2426  end;
2427 
2428  Key := GetTriggersCacheKey(Catalog, SchemaPattern, TableNamePattern, TriggerNamePattern);
2429  Result := GetResultSetFromCache(Key);
2430  if Result = nil then
2431  begin
2432  Result := UncachedGetTriggers(Catalog, SchemaPattern, TableNamePattern, TriggerNamePattern);
2433  AddResultSetToCache(Key, Result);
2434  end;
2435 end;
2436 
2437 function TZAbstractDatabaseMetadata.UncachedGetTriggers(const Catalog: string; const SchemaPattern: string;
2438  const TableNamePattern: string; const TriggerNamePattern: string): IZResultSet;
2439 begin
2440  Result := ConstructVirtualResultSet(TriggersColumnsDynArray);
2441 end;
2442 
2443 function TZAbstractDatabaseMetadata.GetCollationAndCharSet(const Catalog, Schema,
2444  TableName, ColumnName: String): IZResultSet;
2445 var
2446  Key: string;
2447 begin
2448  if not GetConnection.UseMetadata then
2449  begin
2450  Result := ConstructVirtualResultSet(CollationCharSetColumnsDynArray);
2451  exit;
2452  end;
2453 
2454  Key := GetCollationAndCharSetCacheKey(Catalog, Schema, TableName, ColumnName);
2455  Result := GetResultSetFromCache(Key);
2456  if Result = nil then
2457  begin
2458  Result := UncachedGetCollationAndCharSet(Catalog, Schema, TableName, ColumnName);
2459  AddResultSetToCache(Key, Result);
2460  end;
2461 end;
2462 
2463 function TZAbstractDatabaseMetadata.GetCharacterSets: IZResultSet; //EgonHugeist
2464 var
2465  Key: string;
2466 begin
2467  if not GetConnection.UseMetadata then
2468  begin
2469  Result := ConstructVirtualResultSet(CharacterSetsColumnsDynArray);
2470  exit;
2471  end;
2472 
2473  Key := GetCharacterSetsCacheKey;
2474  Result := GetResultSetFromCache(Key);
2475  if Result = nil then
2476  begin
2477  Result := UncachedGetCharacterSets;
2478  AddResultSetToCache(Key, Result);
2479  end;
2480 end;
2481 
2482 function TZAbstractDatabaseMetadata.UncachedGetCollationAndCharSet(const Catalog, SchemaPattern,
2483  TableNamePattern, ColumnNamePattern: string): IZResultSet;
2484 begin
2485  Result := ConstructVirtualResultSet(CollationCharSetColumnsDynArray);
2486 end;
2487 
2488 function TZAbstractDatabaseMetadata.UncachedGetCharacterSets: IZResultSet; //EgonHugeist
2489 begin
2490  Result := ConstructVirtualResultSet(CharacterSetsColumnsDynArray);
2491 end;
2492 
2493 function TZAbstractDatabaseMetadata.GetCollationAndCharSetCacheKey(const Catalog, SchemaPattern,
2494  TableNamePattern, ColumnPattern: String): string;
2495 begin
2496  Result := Format('get-CollationAndCharSet:%s:%s:%s:%s',
2497  [Catalog, SchemaPattern, TableNamePattern, ColumnPattern]);
2498 end;
2499 
2500 function TZAbstractDatabaseMetadata.GetCharacterSetsCacheKey: String; //EgonHugeist
2501 begin
2502  Result := 'get-charactersets';
2503 end;
2504 
2505 function TZAbstractDatabaseMetadata.GetTriggersCacheKey(const Catalog: string;
2506  const SchemaPattern: string; const TableNamePattern: string;
2507  const TriggerNamePattern: string): string;
2508 begin
2509  Result := Format('get-trigger:%s:%s:%s:%s',
2510  [Catalog, SchemaPattern, TableNamePattern, TriggerNamePattern]);
2511 end;
2512 
2513 {**
2514  Gets a description of tables available in a catalog.
2515 
2516  <P>Only table descriptions matching the catalog, schema, table
2517  name and type criteria are returned. They are ordered by
2518  TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
2519 
2520  <P>Each table description has the following columns:
2521  <OL>
2522  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2523  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2524  <LI><B>TABLE_NAME</B> String => table name
2525  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
2526  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
2527  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
2528  <LI><B>REMARKS</B> String => explanatory comment on the table
2529  </OL>
2530 
2531  <P><B>Note:</B> Some databases may not return information for
2532  all tables.
2533 
2534  @param catalog a catalog name; "" retrieves those without a
2535  catalog; null means drop catalog name from the selection criteria
2536  @param schemaPattern a schema name pattern; "" retrieves those
2537  without a schema
2538  @param tableNamePattern a table name pattern
2539  @param types a list of table types to include; null returns all types
2540  @return <code>ResultSet</code> - each row is a table description
2541  @see #getSearchStringEscape
2542 }
2543 function TZAbstractDatabaseMetadata.GetTables(const Catalog: string;
2544  const SchemaPattern: string; const TableNamePattern: string;
2545  const Types: TStringDynArray): IZResultSet;
2546 var
2547  Key: string;
2548 begin
2549  if not GetConnection.UseMetadata then
2550  begin
2551  Result := ConstructVirtualResultSet(TableColumnsDynArray);
2552  exit;
2553  end;
2554 
2555  Key := GetTablesCacheKey(Catalog, SchemaPattern, TableNamePattern, Types);
2556  Result := GetResultSetFromCache(Key);
2557  if Result = nil then
2558  begin
2559  Result := UncachedGetTables(Catalog, SchemaPattern, TableNamePattern, Types);
2560  AddResultSetToCache(Key, Result);
2561  end;
2562 end;
2563 
2564 {**
2565  Gets a description of tables available in a catalog.
2566 
2567  <P>Only table descriptions matching the catalog, schema, table
2568  name and type criteria are returned. They are ordered by
2569  TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
2570 
2571  <P>Each table description has the following columns:
2572  <OL>
2573  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2574  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2575  <LI><B>TABLE_NAME</B> String => table name
2576  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
2577  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
2578  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
2579  <LI><B>REMARKS</B> String => explanatory comment on the table
2580  </OL>
2581 
2582  <P><B>Note:</B> Some databases may not return information for
2583  all tables.
2584 
2585  @param catalog a catalog name; "" retrieves those without a
2586  catalog; null means drop catalog name from the selection criteria
2587  @param schemaPattern a schema name pattern; "" retrieves those
2588  without a schema
2589  @param tableNamePattern a table name pattern
2590  @param types a list of table types to include; null returns all types
2591  @return <code>ResultSet</code> - each row is a table description
2592  @see #getSearchStringEscape
2593 }
2594 function TZAbstractDatabaseMetadata.UncachedGetTables(const Catalog: string;
2595  const SchemaPattern: string; const TableNamePattern: string;
2596  const Types: TStringDynArray): IZResultSet;
2597 begin
2598  Result := ConstructVirtualResultSet(TableColumnsDynArray);
2599 end;
2600 
2601 {**
2602  Gets the schema names available in this database. The results
2603  are ordered by schema name.
2604 
2605  <P>The schema column is:
2606  <OL>
2607  <LI><B>TABLE_SCHEM</B> String => schema name
2608  </OL>
2609 
2610  @return <code>ResultSet</code> - each row has a single String column that is a
2611  schema name
2612 }
2613 function TZAbstractDatabaseMetadata.GetSchemas: IZResultSet;
2614 var
2615  Key: string;
2616 begin
2617  if not GetConnection.UseMetadata then
2618  begin
2619  Result := ConstructVirtualResultSet(SchemaColumnsDynArray);
2620  exit;
2621  end;
2622 
2623  Key := GetSchemasCacheKey;
2624  Result := GetResultSetFromCache(Key);
2625  if Result = nil then
2626  begin
2627  Result := UncachedGetSchemas;
2628  AddResultSetToCache(Key, Result);
2629  end;
2630 end;
2631 
2632 {**
2633  Gets the schema names available in this database. The results
2634  are ordered by schema name.
2635 
2636  <P>The schema column is:
2637  <OL>
2638  <LI><B>TABLE_SCHEM</B> String => schema name
2639  </OL>
2640 
2641  @return <code>ResultSet</code> - each row has a single String column that is a
2642  schema name
2643 }
2644 function TZAbstractDatabaseMetadata.UncachedGetSchemas: IZResultSet;
2645 begin
2646  Result := ConstructVirtualResultSet(SchemaColumnsDynArray);
2647 end;
2648 
2649 {**
2650  Gets the catalog names available in this database. The results
2651  are ordered by catalog name.
2652 
2653  <P>The catalog column is:
2654  <OL>
2655  <LI><B>TABLE_CAT</B> String => catalog name
2656  </OL>
2657 
2658  @return <code>ResultSet</code> - each row has a single String column that is a
2659  catalog name
2660 }
2661 function TZAbstractDatabaseMetadata.GetCatalogs: IZResultSet;
2662 var
2663  Key: string;
2664 begin
2665  if not GetConnection.UseMetadata then
2666  begin
2667  Result := ConstructVirtualResultSet(CatalogColumnsDynArray);
2668  exit;
2669  end;
2670 
2671  Key := GetCatalogsCacheKey;
2672  Result := GetResultSetFromCache(Key);
2673  if Result = nil then
2674  begin
2675  Result := UncachedGetCatalogs;
2676  AddResultSetToCache(Key, Result);
2677  end;
2678 end;
2679 
2680 {**
2681  Gets the catalog names available in this database. The results
2682  are ordered by catalog name.
2683 
2684  <P>The catalog column is:
2685  <OL>
2686  <LI><B>TABLE_CAT</B> String => catalog name
2687  </OL>
2688 
2689  @return <code>ResultSet</code> - each row has a single String column that is a
2690  catalog name
2691 }
2692 function TZAbstractDatabaseMetadata.UncachedGetCatalogs: IZResultSet;
2693 begin
2694  Result := ConstructVirtualResultSet(CatalogColumnsDynArray);
2695 end;
2696 
2697 {**
2698  Gets the table types available in this database. The results
2699  are ordered by table type.
2700 
2701  <P>The table type is:
2702  <OL>
2703  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
2704  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
2705  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
2706  </OL>
2707 
2708  @return <code>ResultSet</code> - each row has a single String column that is a
2709  table type
2710 }
2711 function TZAbstractDatabaseMetadata.GetTableTypes: IZResultSet;
2712 var
2713  Key: string;
2714 begin
2715  if not GetConnection.UseMetadata then
2716  begin
2717  Result := ConstructVirtualResultSet(TableTypeColumnsDynArray);
2718  exit;
2719  end;
2720 
2721  Key := GetTableTypesCacheKey;
2722  Result := GetResultSetFromCache(Key);
2723  if Result = nil then
2724  begin
2725  Result := UncachedGetTableTypes;
2726  AddResultSetToCache(Key, Result);
2727  end;
2728 end;
2729 
2730 {**
2731  Gets the table types available in this database. The results
2732  are ordered by table type.
2733 
2734  <P>The table type is:
2735  <OL>
2736  <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
2737  "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
2738  "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
2739  </OL>
2740 
2741  @return <code>ResultSet</code> - each row has a single String column that is a
2742  table type
2743 }
2744 function TZAbstractDatabaseMetadata.UncachedGetTableTypes: IZResultSet;
2745 begin
2746  Result := ConstructVirtualResultSet(TableTypeColumnsDynArray);
2747 end;
2748 
2749 {**
2750  Gets a description of table columns available in
2751  the specified catalog.
2752 
2753  <P>Only column descriptions matching the catalog, schema, table
2754  and column name criteria are returned. They are ordered by
2755  TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
2756 
2757  <P>Each column description has the following columns:
2758  <OL>
2759  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2760  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2761  <LI><B>TABLE_NAME</B> String => table name
2762  <LI><B>COLUMN_NAME</B> String => column name
2763  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
2764  <LI><B>TYPE_NAME</B> String => Data source dependent type name,
2765  for a UDT the type name is fully qualified
2766  <LI><B>COLUMN_SIZE</B> int => column size. For char or date
2767  types this is the maximum number of characters, for numeric or
2768  decimal types this is precision.
2769  <LI><B>BUFFER_LENGTH</B> is not used.
2770  <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
2771  <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
2772  <LI><B>NULLABLE</B> int => is NULL allowed?
2773  <UL>
2774  <LI> columnNoNulls - might not allow NULL values
2775  <LI> columnNullable - definitely allows NULL values
2776  <LI> columnNullableUnknown - nullability unknown
2777  </UL>
2778  <LI><B>REMARKS</B> String => comment describing column (may be null)
2779  <LI><B>COLUMN_DEF</B> String => default value (may be null)
2780  <LI><B>SQL_DATA_TYPE</B> int => unused
2781  <LI><B>SQL_DATETIME_SUB</B> int => unused
2782  <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
2783  maximum number of bytes in the column
2784  <LI><B>ORDINAL_POSITION</B> int => index of column in table
2785  (starting at 1)
2786  <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
2787  does not allow NULL values; "YES" means the column might
2788  allow NULL values. An empty string means nobody knows.
2789  </OL>
2790 
2791  @param catalog a catalog name; "" retrieves those without a
2792  catalog; null means drop catalog name from the selection criteria
2793  @param schemaPattern a schema name pattern; "" retrieves those
2794  without a schema
2795  @param tableNamePattern a table name pattern
2796  @param columnNamePattern a column name pattern
2797  @return <code>ResultSet</code> - each row is a column description
2798  @see #getSearchStringEscape
2799 }
2800 function TZAbstractDatabaseMetadata.GetColumns(const Catalog: string;
2801  const SchemaPattern: string; const TableNamePattern: string;
2802  const ColumnNamePattern: string): IZResultSet;
2803 var
2804  Key: string;
2805 begin
2806  if not GetConnection.UseMetadata then
2807  begin
2808  Result := ConstructVirtualResultSet(TableColColumnsDynArray);
2809  exit;
2810  end;
2811 
2812  Key := GetColumnsCacheKey(Catalog, SchemaPattern, TableNamePattern,
2813  ColumnNamePattern);
2814  Result := GetResultSetFromCache(Key);
2815  if Result = nil then
2816  begin
2817  Result := UncachedGetColumns(Catalog, SchemaPattern, TableNamePattern, ColumnNamePattern);
2818  AddResultSetToCache(Key, Result);
2819  end;
2820 end;
2821 
2822 {**
2823  Gets a description of table columns available in
2824  the specified catalog.
2825 
2826  <P>Only column descriptions matching the catalog, schema, table
2827  and column name criteria are returned. They are ordered by
2828  TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
2829 
2830  <P>Each column description has the following columns:
2831  <OL>
2832  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2833  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2834  <LI><B>TABLE_NAME</B> String => table name
2835  <LI><B>COLUMN_NAME</B> String => column name
2836  <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
2837  <LI><B>TYPE_NAME</B> String => Data source dependent type name,
2838  for a UDT the type name is fully qualified
2839  <LI><B>COLUMN_SIZE</B> int => column size. For char or date
2840  types this is the maximum number of characters, for numeric or
2841  decimal types this is precision.
2842  <LI><B>BUFFER_LENGTH</B> is not used.
2843  <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
2844  <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
2845  <LI><B>NULLABLE</B> int => is NULL allowed?
2846  <UL>
2847  <LI> columnNoNulls - might not allow NULL values
2848  <LI> columnNullable - definitely allows NULL values
2849  <LI> columnNullableUnknown - nullability unknown
2850  </UL>
2851  <LI><B>REMARKS</B> String => comment describing column (may be null)
2852  <LI><B>COLUMN_DEF</B> String => default value (may be null)
2853  <LI><B>SQL_DATA_TYPE</B> int => unused
2854  <LI><B>SQL_DATETIME_SUB</B> int => unused
2855  <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
2856  maximum number of bytes in the column
2857  <LI><B>ORDINAL_POSITION</B> int => index of column in table
2858  (starting at 1)
2859  <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
2860  does not allow NULL values; "YES" means the column might
2861  allow NULL values. An empty string means nobody knows.
2862  </OL>
2863 
2864  @param catalog a catalog name; "" retrieves those without a
2865  catalog; null means drop catalog name from the selection criteria
2866  @param schemaPattern a schema name pattern; "" retrieves those
2867  without a schema
2868  @param tableNamePattern a table name pattern
2869  @param columnNamePattern a column name pattern
2870  @return <code>ResultSet</code> - each row is a column description
2871  @see #getSearchStringEscape
2872 }
2873 function TZAbstractDatabaseMetadata.UncachedGetColumns(const Catalog: string;
2874  const SchemaPattern: string; const TableNamePattern: string;
2875  const ColumnNamePattern: string): IZResultSet;
2876 begin
2877  Result := ConstructVirtualResultSet(TableColColumnsDynArray);
2878 end;
2879 
2880 {**
2881  Gets a description of the access rights for a table's columns.
2882 
2883  <P>Only privileges matching the column name criteria are
2884  returned. They are ordered by COLUMN_NAME and PRIVILEGE.
2885 
2886  <P>Each privilige description has the following columns:
2887  <OL>
2888  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2889  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2890  <LI><B>TABLE_NAME</B> String => table name
2891  <LI><B>COLUMN_NAME</B> String => column name
2892  <LI><B>GRANTOR</B> => grantor of access (may be null)
2893  <LI><B>GRANTEE</B> String => grantee of access
2894  <LI><B>PRIVILEGE</B> String => name of access (SELECT,
2895  INSERT, UPDATE, REFRENCES, ...)
2896  <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
2897  to grant to others; "NO" if not; null if unknown
2898  </OL>
2899 
2900  @param catalog a catalog name; "" retrieves those without a
2901  catalog; null means drop catalog name from the selection criteria
2902  @param schema a schema name; "" retrieves those without a schema
2903  @param table a table name
2904  @param columnNamePattern a column name pattern
2905  @return <code>ResultSet</code> - each row is a column privilege description
2906  @see #getSearchStringEscape
2907 }
2908 function TZAbstractDatabaseMetadata.GetColumnPrivileges(const Catalog: string;
2909  const Schema: string; const Table: string; const ColumnNamePattern: string): IZResultSet;
2910 var
2911  Key: string;
2912 begin
2913  if not GetConnection.UseMetadata then
2914  begin
2915  Result := ConstructVirtualResultSet(TableColPrivColumnsDynArray);
2916  exit;
2917  end;
2918 
2919  Key := GetColumnPrivilegesCacheKey(Catalog, Schema, Table,
2920  ColumnNamePattern);
2921  Result := GetResultSetFromCache(Key);
2922  if Result = nil then
2923  begin
2924  Result := UncachedGetColumnPrivileges(Catalog, Schema, Table, ColumnNamePattern);
2925  AddResultSetToCache(Key, Result);
2926  end;
2927 end;
2928 
2929 {**
2930  Gets a description of the access rights for a table's columns.
2931 
2932  <P>Only privileges matching the column name criteria are
2933  returned. They are ordered by COLUMN_NAME and PRIVILEGE.
2934 
2935  <P>Each privilige description has the following columns:
2936  <OL>
2937  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2938  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2939  <LI><B>TABLE_NAME</B> String => table name
2940  <LI><B>COLUMN_NAME</B> String => column name
2941  <LI><B>GRANTOR</B> => grantor of access (may be null)
2942  <LI><B>GRANTEE</B> String => grantee of access
2943  <LI><B>PRIVILEGE</B> String => name of access (SELECT,
2944  INSERT, UPDATE, REFRENCES, ...)
2945  <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
2946  to grant to others; "NO" if not; null if unknown
2947  </OL>
2948 
2949  @param catalog a catalog name; "" retrieves those without a
2950  catalog; null means drop catalog name from the selection criteria
2951  @param schema a schema name; "" retrieves those without a schema
2952  @param table a table name
2953  @param columnNamePattern a column name pattern
2954  @return <code>ResultSet</code> - each row is a column privilege description
2955  @see #getSearchStringEscape
2956 }
2957 function TZAbstractDatabaseMetadata.UncachedGetColumnPrivileges(const Catalog: string;
2958  const Schema: string; const Table: string; const ColumnNamePattern: string): IZResultSet;
2959 begin
2960  Result := ConstructVirtualResultSet(TableColPrivColumnsDynArray);
2961 end;
2962 
2963 {**
2964  Gets a description of the access rights for each table available
2965  in a catalog. Note that a table privilege applies to one or
2966  more columns in the table. It would be wrong to assume that
2967  this priviledge applies to all columns (this may be true for
2968  some systems but is not true for all.)
2969 
2970  <P>Only privileges matching the schema and table name
2971  criteria are returned. They are ordered by TABLE_SCHEM,
2972  TABLE_NAME, and PRIVILEGE.
2973 
2974  <P>Each privilige description has the following columns:
2975  <OL>
2976  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
2977  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
2978  <LI><B>TABLE_NAME</B> String => table name
2979  <LI><B>GRANTOR</B> => grantor of access (may be null)
2980  <LI><B>GRANTEE</B> String => grantee of access
2981  <LI><B>PRIVILEGE</B> String => name of access (SELECT,
2982  INSERT, UPDATE, REFRENCES, ...)
2983  <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
2984  to grant to others; "NO" if not; null if unknown
2985  </OL>
2986 
2987  @param catalog a catalog name; "" retrieves those without a
2988  catalog; null means drop catalog name from the selection criteria
2989  @param schemaPattern a schema name pattern; "" retrieves those
2990  without a schema
2991  @param tableNamePattern a table name pattern
2992  @return <code>ResultSet</code> - each row is a table privilege description
2993  @see #getSearchStringEscape
2994 }
2995 function TZAbstractDatabaseMetadata.GetTablePrivileges(const Catalog: string;
2996  const SchemaPattern: string; const TableNamePattern: string): IZResultSet;
2997 var
2998  Key: string;
2999 begin
3000  if not GetConnection.UseMetadata then
3001  begin
3002  Result := ConstructVirtualResultSet(TablePrivColumnsDynArray);
3003  exit;
3004  end;
3005 
3006  Key := GetTablePrivilegesCacheKey(Catalog, SchemaPattern,
3007  TableNamePattern);
3008  Result := GetResultSetFromCache(Key);
3009  if Result = nil then
3010  begin
3011  Result := UncachedGetTablePrivileges(Catalog, SchemaPattern, TableNamePattern);
3012  AddResultSetToCache(Key, Result);
3013  end;
3014 end;
3015 
3016 {**
3017  Gets a description of the access rights for each table available
3018  in a catalog. Note that a table privilege applies to one or
3019  more columns in the table. It would be wrong to assume that
3020  this priviledge applies to all columns (this may be true for
3021  some systems but is not true for all.)
3022 
3023  <P>Only privileges matching the schema and table name
3024  criteria are returned. They are ordered by TABLE_SCHEM,
3025  TABLE_NAME, and PRIVILEGE.
3026 
3027  <P>Each privilige description has the following columns:
3028  <OL>
3029  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
3030  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
3031  <LI><B>TABLE_NAME</B> String => table name
3032  <LI><B>GRANTOR</B> => grantor of access (may be null)
3033  <LI><B>GRANTEE</B> String => grantee of access
3034  <LI><B>PRIVILEGE</B> String => name of access (SELECT,
3035  INSERT, UPDATE, REFRENCES, ...)
3036  <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
3037  to grant to others; "NO" if not; null if unknown
3038  </OL>
3039 
3040  @param catalog a catalog name; "" retrieves those without a
3041  catalog; null means drop catalog name from the selection criteria
3042  @param schemaPattern a schema name pattern; "" retrieves those
3043  without a schema
3044  @param tableNamePattern a table name pattern
3045  @return <code>ResultSet</code> - each row is a table privilege description
3046  @see #getSearchStringEscape
3047 }
3048 function TZAbstractDatabaseMetadata.UncachedGetTablePrivileges(const Catalog: string;
3049  const SchemaPattern: string; const TableNamePattern: string): IZResultSet;
3050 begin
3051  Result := ConstructVirtualResultSet(TablePrivColumnsDynArray);
3052 end;
3053 
3054 {**
3055  Gets a description of a table's optimal set of columns that
3056  uniquely identifies a row. They are ordered by SCOPE.
3057 
3058  <P>Each column description has the following columns:
3059  <OL>
3060  <LI><B>SCOPE</B> short => actual scope of result
3061  <UL>
3062  <LI> bestRowTemporary - very temporary, while using row
3063  <LI> bestRowTransaction - valid for remainder of current transaction
3064  <LI> bestRowSession - valid for remainder of current session
3065  </UL>
3066  <LI><B>COLUMN_NAME</B> String => column name
3067  <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
3068  <LI><B>TYPE_NAME</B> String => Data source dependent type name,
3069  for a UDT the type name is fully qualified
3070  <LI><B>COLUMN_SIZE</B> int => precision
3071  <LI><B>BUFFER_LENGTH</B> int => not used
3072  <LI><B>DECIMAL_DIGITS</B> short => scale
3073  <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
3074  like an Oracle ROWID
3075  <UL>
3076  <LI> bestRowUnknown - may or may not be pseudo column
3077  <LI> bestRowNotPseudo - is NOT a pseudo column
3078  <LI> bestRowPseudo - is a pseudo column
3079  </UL>
3080  </OL>
3081 
3082  @param catalog a catalog name; "" retrieves those without a
3083  catalog; null means drop catalog name from the selection criteria
3084  @param schema a schema name; "" retrieves those without a schema
3085  @param table a table name
3086  @param scope the scope of interest; use same values as SCOPE
3087  @param nullable include columns that are nullable?
3088  @return <code>ResultSet</code> - each row is a column description
3089 }
3090 function TZAbstractDatabaseMetadata.GetBestRowIdentifier(const Catalog: string;
3091  const Schema: string; const Table: string; Scope: Integer; Nullable: Boolean): IZResultSet;
3092 var
3093  Key: string;
3094 begin
3095  if not GetConnection.UseMetadata then
3096  begin
3097  Result := ConstructVirtualResultSet(BestRowIdentColumnsDynArray);
3098  exit;
3099  end;
3100 
3101  Key := GetBestRowIdentifierCacheKey(Catalog, Schema, Table, Scope,
3102  Nullable);
3103  Result := GetResultSetFromCache(Key);
3104  if Result = nil then
3105  begin
3106  Result := UncachedGetBestRowIdentifier(Catalog, Schema, Table, Scope, Nullable);
3107  AddResultSetToCache(Key, Result);
3108  end;
3109 end;
3110 
3111 {**
3112  Gets a description of a table's optimal set of columns that
3113  uniquely identifies a row. They are ordered by SCOPE.
3114 
3115  <P>Each column description has the following columns:
3116  <OL>
3117  <LI><B>SCOPE</B> short => actual scope of result
3118  <UL>
3119  <LI> bestRowTemporary - very temporary, while using row
3120  <LI> bestRowTransaction - valid for remainder of current transaction
3121  <LI> bestRowSession - valid for remainder of current session
3122  </UL>
3123  <LI><B>COLUMN_NAME</B> String => column name
3124  <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
3125  <LI><B>TYPE_NAME</B> String => Data source dependent type name,
3126  for a UDT the type name is fully qualified
3127  <LI><B>COLUMN_SIZE</B> int => precision
3128  <LI><B>BUFFER_LENGTH</B> int => not used
3129  <LI><B>DECIMAL_DIGITS</B> short => scale
3130  <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
3131  like an Oracle ROWID
3132  <UL>
3133  <LI> bestRowUnknown - may or may not be pseudo column
3134  <LI> bestRowNotPseudo - is NOT a pseudo column
3135  <LI> bestRowPseudo - is a pseudo column
3136  </UL>
3137  </OL>
3138 
3139  @param catalog a catalog name; "" retrieves those without a
3140  catalog; null means drop catalog name from the selection criteria
3141  @param schema a schema name; "" retrieves those without a schema
3142  @param table a table name
3143  @param scope the scope of interest; use same values as SCOPE
3144  @param nullable include columns that are nullable?
3145  @return <code>ResultSet</code> - each row is a column description
3146 }
3147 function TZAbstractDatabaseMetadata.UncachedGetBestRowIdentifier(const Catalog: string;
3148  const Schema: string; const Table: string; Scope: Integer; Nullable: Boolean): IZResultSet;
3149 var
3150  IndexName: string;
3151  ColumnNames: TStrings;
3152 begin
3153  Result := ConstructVirtualResultSet(BestRowIdentColumnsDynArray);
3154  ColumnNames := TStringList.Create;
3155  try
3156  { Tries primary keys. }
3157  with GetPrimaryKeys(Catalog, Schema, Table) do
3158  begin
3159  while Next do
3160  ColumnNames.Add(GetStringByName('COLUMN_NAME'));
3161  Close;
3162  end;
3163 
3164  { Tries unique indices. }
3165  if ColumnNames.Count = 0 then
3166  begin
3167  with GetIndexInfo(Catalog, Schema, Table, True, False) do
3168  begin
3169  IndexName := '';
3170  while Next do
3171  begin
3172  if IndexName = '' then
3173  IndexName := GetStringByName('INDEX_NAME');
3174  if GetStringByName('INDEX_NAME') = IndexName then
3175  ColumnNames.Add(GetStringByName('COLUMN_NAME'));
3176  end;
3177  Close;
3178  end;
3179  end;
3180 
3181  with GetColumns(Catalog, Schema, Table, '') do
3182  begin
3183  while Next do
3184  begin
3185  if (ColumnNames.Count <> 0) and (ColumnNames.IndexOf(
3186  GetStringByName('COLUMN_NAME')) < 0) then
3187  Continue;
3188  if (ColumnNames.Count = 0)
3189  and (TZSQLType(GetIntByName('DATA_TYPE')) in
3190  [stBytes, stBinaryStream, stAsciiStream, stUnicodeStream]) then
3191  Continue;
3192 
3193  Result.MoveToInsertRow;
3194  Result.UpdateInt(1, Ord(sbrSession));
3195  Result.UpdateString(2, GetStringByName('COLUMN_NAME'));
3196  Result.UpdateInt(3, GetIntByName('DATA_TYPE'));
3197  Result.UpdateString(4, GetStringByName('TYPE_NAME'));
3198  Result.UpdateInt(5, GetIntByName('COLUMN_SIZE'));
3199  Result.UpdateInt(6, GetIntByName('BUFFER_LENGTH'));
3200  Result.UpdateInt(7, GetIntByName('DECIMAL_DIGITS'));
3201  Result.UpdateInt(8, Ord(brNotPseudo));
3202  Result.InsertRow;
3203  end;
3204  Close;
3205  end;
3206  finally
3207  ColumnNames.Free;
3208  end;
3209 end;
3210 
3211 {**
3212  Gets a description of a table's columns that are automatically
3213  updated when any value in a row is updated. They are
3214  unordered.
3215 
3216  <P>Each column description has the following columns:
3217  <OL>
3218  <LI><B>SCOPE</B> short => is not used
3219  <LI><B>COLUMN_NAME</B> String => column name
3220  <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
3221  <LI><B>TYPE_NAME</B> String => Data source dependent type name
3222  <LI><B>COLUMN_SIZE</B> int => precision
3223  <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
3224  <LI><B>DECIMAL_DIGITS</B> short => scale
3225  <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
3226  like an Oracle ROWID
3227  <UL>
3228  <LI> versionColumnUnknown - may or may not be pseudo column
3229  <LI> versionColumnNotPseudo - is NOT a pseudo column
3230  <LI> versionColumnPseudo - is a pseudo column
3231  </UL>
3232  </OL>
3233 
3234  @param catalog a catalog name; "" retrieves those without a
3235  catalog; null means drop catalog name from the selection criteria
3236  @param schema a schema name; "" retrieves those without a schema
3237  @param table a table name
3238  @return <code>ResultSet</code> - each row is a column description
3239  @exception SQLException if a database access error occurs
3240 }
3241 
3242 function TZAbstractDatabaseMetadata.GetVersionColumns(const Catalog: string;
3243  const Schema: string; const Table: string): IZResultSet;
3244 var
3245  Key: string;
3246 begin
3247  if not GetConnection.UseMetadata then
3248  begin
3249  Result := ConstructVirtualResultSet(TableColVerColumnsDynArray);
3250  exit;
3251  end;
3252 
3253  Key := GetVersionColumnsCacheKey(Catalog, Schema, Table);
3254  Result := GetResultSetFromCache(Key);
3255  if Result = nil then
3256  begin
3257  Result := UncachedGetVersionColumns(Catalog, Schema, Table);
3258  AddResultSetToCache(Key, Result);
3259  end;
3260 end;
3261 
3262 {**
3263  Gets a description of a table's columns that are automatically
3264  updated when any value in a row is updated. They are
3265  unordered.
3266 
3267  <P>Each column description has the following columns:
3268  <OL>
3269  <LI><B>SCOPE</B> short => is not used
3270  <LI><B>COLUMN_NAME</B> String => column name
3271  <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
3272  <LI><B>TYPE_NAME</B> String => Data source dependent type name
3273  <LI><B>COLUMN_SIZE</B> int => precision
3274  <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
3275  <LI><B>DECIMAL_DIGITS</B> short => scale
3276  <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
3277  like an Oracle ROWID
3278  <UL>
3279  <LI> versionColumnUnknown - may or may not be pseudo column
3280  <LI> versionColumnNotPseudo - is NOT a pseudo column
3281  <LI> versionColumnPseudo - is a pseudo column
3282  </UL>
3283  </OL>
3284 
3285  @param catalog a catalog name; "" retrieves those without a
3286  catalog; null means drop catalog name from the selection criteria
3287  @param schema a schema name; "" retrieves those without a schema
3288  @param table a table name
3289  @return <code>ResultSet</code> - each row is a column description
3290  @exception SQLException if a database access error occurs
3291 }
3292 function TZAbstractDatabaseMetadata.UncachedGetVersionColumns(const Catalog: string;
3293  const Schema: string; const Table: string): IZResultSet;
3294 begin
3295  Result := ConstructVirtualResultSet(TableColVerColumnsDynArray);
3296 end;
3297 
3298 {**
3299  Gets a description of a table's primary key columns. They
3300  are ordered by COLUMN_NAME.
3301 
3302  <P>Each primary key column description has the following columns:
3303  <OL>
3304  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
3305  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
3306  <LI><B>TABLE_NAME</B> String => table name
3307  <LI><B>COLUMN_NAME</B> String => column name
3308  <LI><B>KEY_SEQ</B> short => sequence number within primary key
3309  <LI><B>PK_NAME</B> String => primary key name (may be null)
3310  </OL>
3311 
3312  @param catalog a catalog name; "" retrieves those without a
3313  catalog; null means drop catalog name from the selection criteria
3314  @param schema a schema name; "" retrieves those
3315  without a schema
3316  @param table a table name
3317  @return <code>ResultSet</code> - each row is a primary key column description
3318  @exception SQLException if a database access error occurs
3319 }
3320 function TZAbstractDatabaseMetadata.GetPrimaryKeys(const Catalog: string;
3321  const Schema: string; const Table: string): IZResultSet;
3322 var
3323  Key: string;
3324 begin
3325  if not GetConnection.UseMetadata then
3326  begin
3327  Result := ConstructVirtualResultSet(PrimaryKeyColumnsDynArray);
3328  exit;
3329  end;
3330 
3331  Key := GetPrimaryKeysCacheKey(Catalog, Schema, Table);
3332  Result := GetResultSetFromCache(Key);
3333  if Result = nil then
3334  begin
3335  Result := UncachedGetPrimaryKeys(Catalog, Schema, Table);
3336  AddResultSetToCache(Key, Result);
3337  end;
3338 end;
3339 
3340 {**
3341  Gets a description of a table's primary key columns. They
3342  are ordered by COLUMN_NAME.
3343 
3344  <P>Each primary key column description has the following columns:
3345  <OL>
3346  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
3347  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
3348  <LI><B>TABLE_NAME</B> String => table name
3349  <LI><B>COLUMN_NAME</B> String => column name
3350  <LI><B>KEY_SEQ</B> short => sequence number within primary key
3351  <LI><B>PK_NAME</B> String => primary key name (may be null)
3352  </OL>
3353 
3354  @param catalog a catalog name; "" retrieves those without a
3355  catalog; null means drop catalog name from the selection criteria
3356  @param schema a schema name; "" retrieves those
3357  without a schema
3358  @param table a table name
3359  @return <code>ResultSet</code> - each row is a primary key column description
3360  @exception SQLException if a database access error occurs
3361 }
3362 function TZAbstractDatabaseMetadata.UncachedGetPrimaryKeys(const Catalog: string;
3363  const Schema: string; const Table: string): IZResultSet;
3364 begin
3365  Result := ConstructVirtualResultSet(PrimaryKeyColumnsDynArray);
3366 end;
3367 
3368 {**
3369  Gets a description of the primary key columns that are
3370  referenced by a table's foreign key columns (the primary keys
3371  imported by a table). They are ordered by PKTABLE_CAT,
3372  PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
3373 
3374  <P>Each primary key column description has the following columns:
3375  <OL>
3376  <LI><B>PKTABLE_CAT</B> String => primary key table catalog
3377  being imported (may be null)
3378  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema
3379  being imported (may be null)
3380  <LI><B>PKTABLE_NAME</B> String => primary key table name
3381  being imported
3382  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
3383  being imported
3384  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
3385  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
3386  <LI><B>FKTABLE_NAME</B> String => foreign key table name
3387  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
3388  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
3389  <LI><B>UPDATE_RULE</B> short => What happens to
3390  foreign key when primary is updated:
3391  <UL>
3392  <LI> importedNoAction - do not allow update of primary
3393  key if it has been imported
3394  <LI> importedKeyCascade - change imported key to agree
3395  with primary key update
3396  <LI> importedKeySetNull - change imported key to NULL if
3397  its primary key has been updated
3398  <LI> importedKeySetDefault - change imported key to default values
3399  if its primary key has been updated
3400  <LI> importedKeyRestrict - same as importedKeyNoAction
3401  (for ODBC 2.x compatibility)
3402  </UL>
3403  <LI><B>DELETE_RULE</B> short => What happens to
3404  the foreign key when primary is deleted.
3405  <UL>
3406  <LI> importedKeyNoAction - do not allow delete of primary
3407  key if it has been imported
3408  <LI> importedKeyCascade - delete rows that import a deleted key
3409  <LI> importedKeySetNull - change imported key to NULL if
3410  its primary key has been deleted
3411  <LI> importedKeyRestrict - same as importedKeyNoAction
3412  (for ODBC 2.x compatibility)
3413  <LI> importedKeySetDefault - change imported key to default if
3414  its primary key has been deleted
3415  </UL>
3416  <LI><B>FK_NAME</B> String => foreign key name (may be null)
3417  <LI><B>PK_NAME</B> String => primary key name (may be null)
3418  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
3419  constraints be deferred until commit
3420  <UL>
3421  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
3422  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
3423  <LI> importedKeyNotDeferrable - see SQL92 for definition
3424  </UL>
3425  </OL>
3426 
3427  @param catalog a catalog name; "" retrieves those without a
3428  catalog; null means drop catalog name from the selection criteria
3429  @param schema a schema name; "" retrieves those
3430  without a schema
3431  @param table a table name
3432  @return <code>ResultSet</code> - each row is a primary key column description
3433  @see #getExportedKeys
3434 }
3435 function TZAbstractDatabaseMetadata.GetImportedKeys(const Catalog: string;
3436  const Schema: string; const Table: string): IZResultSet;
3437 var
3438  Key: string;
3439 begin
3440  if not GetConnection.UseMetadata then
3441  begin
3442  Result := ConstructVirtualResultSet(ImportedKeyColumnsDynArray);
3443  exit;
3444  end;
3445 
3446  Key := GetImportedKeysCacheKey(Catalog, Schema, Table);
3447  Result := GetResultSetFromCache(Key);
3448  if Result = nil then
3449  begin
3450  Result := UncachedGetImportedKeys(Catalog, Schema, Table);
3451  AddResultSetToCache(Key, Result);
3452  end;
3453 end;
3454 
3455 {**
3456  Gets a description of the primary key columns that are
3457  referenced by a table's foreign key columns (the primary keys
3458  imported by a table). They are ordered by PKTABLE_CAT,
3459  PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
3460 
3461  <P>Each primary key column description has the following columns:
3462  <OL>
3463  <LI><B>PKTABLE_CAT</B> String => primary key table catalog
3464  being imported (may be null)
3465  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema
3466  being imported (may be null)
3467  <LI><B>PKTABLE_NAME</B> String => primary key table name
3468  being imported
3469  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
3470  being imported
3471  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
3472  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
3473  <LI><B>FKTABLE_NAME</B> String => foreign key table name
3474  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
3475  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
3476  <LI><B>UPDATE_RULE</B> short => What happens to
3477  foreign key when primary is updated:
3478  <UL>
3479  <LI> importedNoAction - do not allow update of primary
3480  key if it has been imported
3481  <LI> importedKeyCascade - change imported key to agree
3482  with primary key update
3483  <LI> importedKeySetNull - change imported key to NULL if
3484  its primary key has been updated
3485  <LI> importedKeySetDefault - change imported key to default values
3486  if its primary key has been updated
3487  <LI> importedKeyRestrict - same as importedKeyNoAction
3488  (for ODBC 2.x compatibility)
3489  </UL>
3490  <LI><B>DELETE_RULE</B> short => What happens to
3491  the foreign key when primary is deleted.
3492  <UL>
3493  <LI> importedKeyNoAction - do not allow delete of primary
3494  key if it has been imported
3495  <LI> importedKeyCascade - delete rows that import a deleted key
3496  <LI> importedKeySetNull - change imported key to NULL if
3497  its primary key has been deleted
3498  <LI> importedKeyRestrict - same as importedKeyNoAction
3499  (for ODBC 2.x compatibility)
3500  <LI> importedKeySetDefault - change imported key to default if
3501  its primary key has been deleted
3502  </UL>
3503  <LI><B>FK_NAME</B> String => foreign key name (may be null)
3504  <LI><B>PK_NAME</B> String => primary key name (may be null)
3505  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
3506  constraints be deferred until commit
3507  <UL>
3508  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
3509  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
3510  <LI> importedKeyNotDeferrable - see SQL92 for definition
3511  </UL>
3512  </OL>
3513 
3514  @param catalog a catalog name; "" retrieves those without a
3515  catalog; null means drop catalog name from the selection criteria
3516  @param schema a schema name; "" retrieves those
3517  without a schema
3518  @param table a table name
3519  @return <code>ResultSet</code> - each row is a primary key column description
3520  @see #getExportedKeys
3521 }
3522 function TZAbstractDatabaseMetadata.UncachedGetImportedKeys(const Catalog: string;
3523  const Schema: string; const Table: string): IZResultSet;
3524 begin
3525  Result := ConstructVirtualResultSet(ImportedKeyColumnsDynArray);
3526 end;
3527 
3528 {**
3529  Gets a description of the foreign key columns that reference a
3530  table's primary key columns (the foreign keys exported by a
3531  table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
3532  FKTABLE_NAME, and KEY_SEQ.
3533 
3534  <P>Each foreign key column description has the following columns:
3535  <OL>
3536  <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
3537  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
3538  <LI><B>PKTABLE_NAME</B> String => primary key table name
3539  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
3540  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
3541  being exported (may be null)
3542  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
3543  being exported (may be null)
3544  <LI><B>FKTABLE_NAME</B> String => foreign key table name
3545  being exported
3546  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
3547  being exported
3548  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
3549  <LI><B>UPDATE_RULE</B> short => What happens to
3550  foreign key when primary is updated:
3551  <UL>
3552  <LI> importedNoAction - do not allow update of primary
3553  key if it has been imported
3554  <LI> importedKeyCascade - change imported key to agree
3555  with primary key update
3556  <LI> importedKeySetNull - change imported key to NULL if
3557  its primary key has been updated
3558  <LI> importedKeySetDefault - change imported key to default values
3559  if its primary key has been updated
3560  <LI> importedKeyRestrict - same as importedKeyNoAction
3561  (for ODBC 2.x compatibility)
3562  </UL>
3563  <LI><B>DELETE_RULE</B> short => What happens to
3564  the foreign key when primary is deleted.
3565  <UL>
3566  <LI> importedKeyNoAction - do not allow delete of primary
3567  key if it has been imported
3568  <LI> importedKeyCascade - delete rows that import a deleted key
3569  <LI> importedKeySetNull - change imported key to NULL if
3570  its primary key has been deleted
3571  <LI> importedKeyRestrict - same as importedKeyNoAction
3572  (for ODBC 2.x compatibility)
3573  <LI> importedKeySetDefault - change imported key to default if
3574  its primary key has been deleted
3575  </UL>
3576  <LI><B>FK_NAME</B> String => foreign key name (may be null)
3577  <LI><B>PK_NAME</B> String => primary key name (may be null)
3578  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
3579  constraints be deferred until commit
3580  <UL>
3581  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
3582  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
3583  <LI> importedKeyNotDeferrable - see SQL92 for definition
3584  </UL>
3585  </OL>
3586 
3587  @param catalog a catalog name; "" retrieves those without a
3588  catalog; null means drop catalog name from the selection criteria
3589  @param schema a schema name; "" retrieves those
3590  without a schema
3591  @param table a table name
3592  @return <code>ResultSet</code> - each row is a foreign key column description
3593  @see #getImportedKeys
3594 }
3595 function TZAbstractDatabaseMetadata.GetExportedKeys(const Catalog: string;
3596  const Schema: string; const Table: string): IZResultSet;
3597 var
3598  Key: string;
3599 begin
3600  if not GetConnection.UseMetadata then
3601  begin
3602  Result := ConstructVirtualResultSet(ExportedKeyColumnsDynArray);
3603  exit;
3604  end;
3605 
3606  Key := GetExportedKeysCacheKey(Catalog, Schema, Table);
3607  Result := GetResultSetFromCache(Key);
3608  if Result = nil then
3609  begin
3610  Result := UncachedGetExportedKeys(Catalog, Schema, Table);
3611  AddResultSetToCache(Key, Result);
3612  end;
3613 end;
3614 
3615 {**
3616  Gets a description of the foreign key columns that reference a
3617  table's primary key columns (the foreign keys exported by a
3618  table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
3619  FKTABLE_NAME, and KEY_SEQ.
3620 
3621  <P>Each foreign key column description has the following columns:
3622  <OL>
3623  <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
3624  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
3625  <LI><B>PKTABLE_NAME</B> String => primary key table name
3626  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
3627  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
3628  being exported (may be null)
3629  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
3630  being exported (may be null)
3631  <LI><B>FKTABLE_NAME</B> String => foreign key table name
3632  being exported
3633  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
3634  being exported
3635  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
3636  <LI><B>UPDATE_RULE</B> short => What happens to
3637  foreign key when primary is updated:
3638  <UL>
3639  <LI> importedNoAction - do not allow update of primary
3640  key if it has been imported
3641  <LI> importedKeyCascade - change imported key to agree
3642  with primary key update
3643  <LI> importedKeySetNull - change imported key to NULL if
3644  its primary key has been updated
3645  <LI> importedKeySetDefault - change imported key to default values
3646  if its primary key has been updated
3647  <LI> importedKeyRestrict - same as importedKeyNoAction
3648  (for ODBC 2.x compatibility)
3649  </UL>
3650  <LI><B>DELETE_RULE</B> short => What happens to
3651  the foreign key when primary is deleted.
3652  <UL>
3653  <LI> importedKeyNoAction - do not allow delete of primary
3654  key if it has been imported
3655  <LI> importedKeyCascade - delete rows that import a deleted key
3656  <LI> importedKeySetNull - change imported key to NULL if
3657  its primary key has been deleted
3658  <LI> importedKeyRestrict - same as importedKeyNoAction
3659  (for ODBC 2.x compatibility)
3660  <LI> importedKeySetDefault - change imported key to default if
3661  its primary key has been deleted
3662  </UL>
3663  <LI><B>FK_NAME</B> String => foreign key name (may be null)
3664  <LI><B>PK_NAME</B> String => primary key name (may be null)
3665  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
3666  constraints be deferred until commit
3667  <UL>
3668  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
3669  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
3670  <LI> importedKeyNotDeferrable - see SQL92 for definition
3671  </UL>
3672  </OL>
3673 
3674  @param catalog a catalog name; "" retrieves those without a
3675  catalog; null means drop catalog name from the selection criteria
3676  @param schema a schema name; "" retrieves those
3677  without a schema
3678  @param table a table name
3679  @return <code>ResultSet</code> - each row is a foreign key column description
3680  @see #getImportedKeys
3681 }
3682 function TZAbstractDatabaseMetadata.UncachedGetExportedKeys(const Catalog: string;
3683  const Schema: string; const Table: string): IZResultSet;
3684 begin
3685  Result := ConstructVirtualResultSet(ExportedKeyColumnsDynArray);
3686 end;
3687 
3688 {**
3689  Gets a description of the foreign key columns in the foreign key
3690  table that reference the primary key columns of the primary key
3691  table (describe how one table imports another's key.) This
3692  should normally return a single foreign key/primary key pair
3693  (most tables only import a foreign key from a table once.) They
3694  are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
3695  KEY_SEQ.
3696 
3697  <P>Each foreign key column description has the following columns:
3698  <OL>
3699  <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
3700  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
3701  <LI><B>PKTABLE_NAME</B> String => primary key table name
3702  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
3703  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
3704  being exported (may be null)
3705  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
3706  being exported (may be null)
3707  <LI><B>FKTABLE_NAME</B> String => foreign key table name
3708  being exported
3709  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
3710  being exported
3711  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
3712  <LI><B>UPDATE_RULE</B> short => What happens to
3713  foreign key when primary is updated:
3714  <UL>
3715  <LI> importedNoAction - do not allow update of primary
3716  key if it has been imported
3717  <LI> importedKeyCascade - change imported key to agree
3718  with primary key update
3719  <LI> importedKeySetNull - change imported key to NULL if
3720  its primary key has been updated
3721  <LI> importedKeySetDefault - change imported key to default values
3722  if its primary key has been updated
3723  <LI> importedKeyRestrict - same as importedKeyNoAction
3724  (for ODBC 2.x compatibility)
3725  </UL>
3726  <LI><B>DELETE_RULE</B> short => What happens to
3727  the foreign key when primary is deleted.
3728  <UL>
3729  <LI> importedKeyNoAction - do not allow delete of primary
3730  key if it has been imported
3731  <LI> importedKeyCascade - delete rows that import a deleted key
3732  <LI> importedKeySetNull - change imported key to NULL if
3733  its primary key has been deleted
3734  <LI> importedKeyRestrict - same as importedKeyNoAction
3735  (for ODBC 2.x compatibility)
3736  <LI> importedKeySetDefault - change imported key to default if
3737  its primary key has been deleted
3738  </UL>
3739  <LI><B>FK_NAME</B> String => foreign key name (may be null)
3740  <LI><B>PK_NAME</B> String => primary key name (may be null)
3741  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
3742  constraints be deferred until commit
3743  <UL>
3744  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
3745  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
3746  <LI> importedKeyNotDeferrable - see SQL92 for definition
3747  </UL>
3748  </OL>
3749 
3750  @param primaryCatalog a catalog name; "" retrieves those without a
3751  catalog; null means drop catalog name from the selection criteria
3752  @param primarySchema a schema name; "" retrieves those
3753  without a schema
3754  @param primaryTable the table name that exports the key
3755  @param foreignCatalog a catalog name; "" retrieves those without a
3756  catalog; null means drop catalog name from the selection criteria
3757  @param foreignSchema a schema name; "" retrieves those
3758  without a schema
3759  @param foreignTable the table name that imports the key
3760  @return <code>ResultSet</code> - each row is a foreign key column description
3761  @see #getImportedKeys
3762 }
3763 function TZAbstractDatabaseMetadata.GetCrossReference(const PrimaryCatalog: string;
3764  const PrimarySchema: string; const PrimaryTable: string; const ForeignCatalog: string;
3765  const ForeignSchema: string; const ForeignTable: string): IZResultSet;
3766 var
3767  Key: string;
3768 begin
3769  if not GetConnection.UseMetadata then
3770  begin
3771  Result := ConstructVirtualResultSet(CrossRefColumnsDynArray);
3772  exit;
3773  end;
3774 
3775  Key := GetCrossReferenceCacheKey(PrimaryCatalog, PrimarySchema, PrimaryTable,
3776  ForeignCatalog, ForeignSchema, ForeignTable);
3777 
3778  Result := GetResultSetFromCache(Key);
3779  if Result = nil then
3780  begin
3781  Result := UncachedGetCrossReference(PrimaryCatalog, PrimarySchema, PrimaryTable,
3782  ForeignCatalog, ForeignSchema, ForeignTable);
3783  AddResultSetToCache(Key, Result);
3784  end;
3785 end;
3786 
3787 {**
3788  Gets a description of the foreign key columns in the foreign key
3789  table that reference the primary key columns of the primary key
3790  table (describe how one table imports another's key.) This
3791  should normally return a single foreign key/primary key pair
3792  (most tables only import a foreign key from a table once.) They
3793  are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
3794  KEY_SEQ.
3795 
3796  <P>Each foreign key column description has the following columns:
3797  <OL>
3798  <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
3799  <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
3800  <LI><B>PKTABLE_NAME</B> String => primary key table name
3801  <LI><B>PKCOLUMN_NAME</B> String => primary key column name
3802  <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
3803  being exported (may be null)
3804  <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
3805  being exported (may be null)
3806  <LI><B>FKTABLE_NAME</B> String => foreign key table name
3807  being exported
3808  <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
3809  being exported
3810  <LI><B>KEY_SEQ</B> short => sequence number within foreign key
3811  <LI><B>UPDATE_RULE</B> short => What happens to
3812  foreign key when primary is updated:
3813  <UL>
3814  <LI> importedNoAction - do not allow update of primary
3815  key if it has been imported
3816  <LI> importedKeyCascade - change imported key to agree
3817  with primary key update
3818  <LI> importedKeySetNull - change imported key to NULL if
3819  its primary key has been updated
3820  <LI> importedKeySetDefault - change imported key to default values
3821  if its primary key has been updated
3822  <LI> importedKeyRestrict - same as importedKeyNoAction
3823  (for ODBC 2.x compatibility)
3824  </UL>
3825  <LI><B>DELETE_RULE</B> short => What happens to
3826  the foreign key when primary is deleted.
3827  <UL>
3828  <LI> importedKeyNoAction - do not allow delete of primary
3829  key if it has been imported
3830  <LI> importedKeyCascade - delete rows that import a deleted key
3831  <LI> importedKeySetNull - change imported key to NULL if
3832  its primary key has been deleted
3833  <LI> importedKeyRestrict - same as importedKeyNoAction
3834  (for ODBC 2.x compatibility)
3835  <LI> importedKeySetDefault - change imported key to default if
3836  its primary key has been deleted
3837  </UL>
3838  <LI><B>FK_NAME</B> String => foreign key name (may be null)
3839  <LI><B>PK_NAME</B> String => primary key name (may be null)
3840  <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
3841  constraints be deferred until commit
3842  <UL>
3843  <LI> importedKeyInitiallyDeferred - see SQL92 for definition
3844  <LI> importedKeyInitiallyImmediate - see SQL92 for definition
3845  <LI> importedKeyNotDeferrable - see SQL92 for definition
3846  </UL>
3847  </OL>
3848 
3849  @param primaryCatalog a catalog name; "" retrieves those without a
3850  catalog; null means drop catalog name from the selection criteria
3851  @param primarySchema a schema name; "" retrieves those
3852  without a schema
3853  @param primaryTable the table name that exports the key
3854  @param foreignCatalog a catalog name; "" retrieves those without a
3855  catalog; null means drop catalog name from the selection criteria
3856  @param foreignSchema a schema name; "" retrieves those
3857  without a schema
3858  @param foreignTable the table name that imports the key
3859  @return <code>ResultSet</code> - each row is a foreign key column description
3860  @see #getImportedKeys
3861 }
3862 function TZAbstractDatabaseMetadata.UncachedGetCrossReference(const PrimaryCatalog: string;
3863  const PrimarySchema: string; const PrimaryTable: string; const ForeignCatalog: string;
3864  const ForeignSchema: string; const ForeignTable: string): IZResultSet;
3865 begin
3866  Result := ConstructVirtualResultSet(CrossRefColumnsDynArray);
3867 end;
3868 
3869 {**
3870  Gets a description of all the standard SQL types supported by
3871  this database. They are ordered by DATA_TYPE and then by how
3872  closely the data type maps to the corresponding JDBC SQL type.
3873 
3874  <P>Each type description has the following columns:
3875  <OL>
3876  <LI><B>TYPE_NAME</B> String => Type name
3877  <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
3878  <LI><B>PRECISION</B> int => maximum precision
3879  <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
3880  (may be null)
3881  <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
3882  (may be null)
3883  <LI><B>CREATE_PARAMS</B> String => parameters used in creating
3884  the type (may be null)
3885  <LI><B>NULLABLE</B> short => can you use NULL for this type?
3886  <UL>
3887  <LI> typeNoNulls - does not allow NULL values
3888  <LI> typeNullable - allows NULL values
3889  <LI> typeNullableUnknown - nullability unknown
3890  </UL>
3891  <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
3892  <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
3893  <UL>
3894  <LI> typePredNone - No support
3895  <LI> typePredChar - Only supported with WHERE .. LIKE
3896  <LI> typePredBasic - Supported except for WHERE .. LIKE
3897  <LI> typeSearchable - Supported for all WHERE ..
3898  </UL>
3899  <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
3900  <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
3901  <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
3902  auto-increment value?
3903  <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
3904  (may be null)
3905  <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
3906  <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
3907  <LI><B>SQL_DATA_TYPE</B> int => unused
3908  <LI><B>SQL_DATETIME_SUB</B> int => unused
3909  <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
3910  </OL>
3911 
3912  @return <code>ResultSet</code> - each row is an SQL type description
3913 }
3914 function TZAbstractDatabaseMetadata.GetTypeInfo: IZResultSet;
3915 var
3916  Key: string;
3917 begin
3918  if not GetConnection.UseMetadata then
3919  begin
3920  Result := ConstructVirtualResultSet(TypeInfoColumnsDynArray);
3921  exit;
3922  end;
3923 
3924  Key := GetTypeInfoCacheKey;
3925  Result := GetResultSetFromCache(Key);
3926  if Result = nil then
3927  begin
3928  Result := UncachedGetTypeInfo;
3929  AddResultSetToCache(Key, Result);
3930  end;
3931 end;
3932 
3933 {**
3934  Gets a description of all the standard SQL types supported by
3935  this database. They are ordered by DATA_TYPE and then by how
3936  closely the data type maps to the corresponding JDBC SQL type.
3937 
3938  <P>Each type description has the following columns:
3939  <OL>
3940  <LI><B>TYPE_NAME</B> String => Type name
3941  <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
3942  <LI><B>PRECISION</B> int => maximum precision
3943  <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
3944  (may be null)
3945  <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
3946  (may be null)
3947  <LI><B>CREATE_PARAMS</B> String => parameters used in creating
3948  the type (may be null)
3949  <LI><B>NULLABLE</B> short => can you use NULL for this type?
3950  <UL>
3951  <LI> typeNoNulls - does not allow NULL values
3952  <LI> typeNullable - allows NULL values
3953  <LI> typeNullableUnknown - nullability unknown
3954  </UL>
3955  <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
3956  <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
3957  <UL>
3958  <LI> typePredNone - No support
3959  <LI> typePredChar - Only supported with WHERE .. LIKE
3960  <LI> typePredBasic - Supported except for WHERE .. LIKE
3961  <LI> typeSearchable - Supported for all WHERE ..
3962  </UL>
3963  <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
3964  <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
3965  <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
3966  auto-increment value?
3967  <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
3968  (may be null)
3969  <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
3970  <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
3971  <LI><B>SQL_DATA_TYPE</B> int => unused
3972  <LI><B>SQL_DATETIME_SUB</B> int => unused
3973  <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
3974  </OL>
3975 
3976  @return <code>ResultSet</code> - each row is an SQL type description
3977 }
3978 function TZAbstractDatabaseMetadata.UncachedGetTypeInfo: IZResultSet;
3979 begin
3980  Result := ConstructVirtualResultSet(TypeInfoColumnsDynArray);
3981 end;
3982 
3983 {**
3984  Gets a description of a table's indices and statistics. They are
3985  ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
3986 
3987  <P>Each index column description has the following columns:
3988  <OL>
3989  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
3990  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
3991  <LI><B>TABLE_NAME</B> String => table name
3992  <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
3993  false when TYPE is tableIndexStatistic
3994  <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
3995  null when TYPE is tableIndexStatistic
3996  <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
3997  tableIndexStatistic
3998  <LI><B>TYPE</B> short => index type:
3999  <UL>
4000  <LI> tableIndexStatistic - this identifies table statistics that are
4001  returned in conjuction with a table's index descriptions
4002  <LI> tableIndexClustered - this is a clustered index
4003  <LI> tableIndexHashed - this is a hashed index
4004  <LI> tableIndexOther - this is some other style of index
4005  </UL>
4006  <LI><B>ORDINAL_POSITION</B> short => column sequence number
4007  within index; zero when TYPE is tableIndexStatistic
4008  <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
4009  tableIndexStatistic
4010  <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
4011  "D" => descending, may be null if sort sequence is not supported;
4012  null when TYPE is tableIndexStatistic
4013  <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatistic, then
4014  this is the number of rows in the table; otherwise, it is the
4015  number of unique values in the index.
4016  <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
4017  this is the number of pages used for the table, otherwise it
4018  is the number of pages used for the current index.
4019  <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
4020  (may be null)
4021  </OL>
4022 
4023  @param catalog a catalog name; "" retrieves those without a
4024  catalog; null means drop catalog name from the selection criteria
4025  @param schema a schema name; "" retrieves those without a schema
4026  @param table a table name
4027  @param unique when true, return only indices for unique values;
4028  when false, return indices regardless of whether unique or not
4029  @param approximate when true, result is allowed to reflect approximate
4030  or out of data values; when false, results are requested to be
4031  accurate
4032  @return <code>ResultSet</code> - each row is an index column description
4033 }
4034 function TZAbstractDatabaseMetadata.GetIndexInfo(const Catalog: string;
4035  const Schema: string; const Table: string; Unique: Boolean;
4036  Approximate: Boolean): IZResultSet;
4037 var
4038  Key: string;
4039 begin
4040  if not GetConnection.UseMetadata then
4041  begin
4042  Result := ConstructVirtualResultSet(IndexInfoColumnsDynArray);
4043  exit;
4044  end;
4045 
4046  Key := GetIndexInfoCacheKey(Catalog, Schema, Table, Unique, Approximate);
4047 
4048  Result := GetResultSetFromCache(Key);
4049  if Result = nil then
4050  begin
4051  Result := UncachedGetIndexInfo(Catalog, Schema, Table, Unique, Approximate);
4052  AddResultSetToCache(Key, Result);
4053  end;
4054 end;
4055 
4056 {**
4057  Gets a description of a table's indices and statistics. They are
4058  ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
4059 
4060  <P>Each index column description has the following columns:
4061  <OL>
4062  <LI><B>TABLE_CAT</B> String => table catalog (may be null)
4063  <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
4064  <LI><B>TABLE_NAME</B> String => table name
4065  <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
4066  false when TYPE is tableIndexStatistic
4067  <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
4068  null when TYPE is tableIndexStatistic
4069  <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
4070  tableIndexStatistic
4071  <LI><B>TYPE</B> short => index type:
4072  <UL>
4073  <LI> tableIndexStatistic - this identifies table statistics that are
4074  returned in conjuction with a table's index descriptions
4075  <LI> tableIndexClustered - this is a clustered index
4076  <LI> tableIndexHashed - this is a hashed index
4077  <LI> tableIndexOther - this is some other style of index
4078  </UL>
4079  <LI><B>ORDINAL_POSITION</B> short => column sequence number
4080  within index; zero when TYPE is tableIndexStatistic
4081  <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
4082  tableIndexStatistic
4083  <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
4084  "D" => descending, may be null if sort sequence is not supported;
4085  null when TYPE is tableIndexStatistic
4086  <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatistic, then
4087  this is the number of rows in the table; otherwise, it is the
4088  number of unique values in the index.
4089  <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
4090  this is the number of pages used for the table, otherwise it
4091  is the number of pages used for the current index.
4092  <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
4093  (may be null)
4094  </OL>
4095 
4096  @param catalog a catalog name; "" retrieves those without a
4097  catalog; null means drop catalog name from the selection criteria
4098  @param schema a schema name; "" retrieves those without a schema
4099  @param table a table name
4100  @param unique when true, return only indices for unique values;
4101  when false, return indices regardless of whether unique or not
4102  @param approximate when true, result is allowed to reflect approximate
4103  or out of data values; when false, results are requested to be
4104  accurate
4105  @return <code>ResultSet</code> - each row is an index column description
4106 }
4107 function TZAbstractDatabaseMetadata.UncachedGetIndexInfo(const Catalog: string;
4108  const Schema: string; const Table: string; Unique: Boolean;
4109  Approximate: Boolean): IZResultSet;
4110 begin
4111  Result := ConstructVirtualResultSet(IndexInfoColumnsDynArray);
4112 end;
4113 
4114 function TZAbstractDatabaseMetadata.GetSequences(const Catalog: string;
4115  const SchemaPattern: string; const SequenceNamePattern: string): IZResultSet;
4116 var
4117  Key: string;
4118 begin
4119  if not GetConnection.UseMetadata then
4120  begin
4121  Result := ConstructVirtualResultSet(SequenceColumnsDynArray);
4122  exit;
4123  end;
4124 
4125  Key := GetSequencesCacheKey(Catalog, SchemaPattern, SequenceNamePattern);
4126  Result := GetResultSetFromCache(Key);
4127  if Result = nil then
4128  begin
4129  Result := UncachedGetSequences(Catalog, SchemaPattern, SequenceNamePattern);
4130  AddResultSetToCache(Key, Result);
4131  end;
4132 end;
4133 
4134 function TZAbstractDatabaseMetadata.UncachedGetSequences(const Catalog: string;
4135  const SchemaPattern: string; const SequenceNamePattern: string): IZResultSet;
4136 begin
4137  Result := ConstructVirtualResultSet(SequenceColumnsDynArray);
4138 end;
4139 
4140 {**
4141 
4142  Gets a description of the user-defined types defined in a particular
4143  schema. Schema-specific UDTs may have type JAVA_OBJECT, STRUCT,
4144  or DISTINCT.
4145 
4146  <P>Only types matching the catalog, schema, type name and type
4147  criteria are returned. They are ordered by DATA_TYPE, TYPE_SCHEM
4148  and TYPE_NAME. The type name parameter may be a fully-qualified
4149  name. In this case, the catalog and schemaPattern parameters are
4150  ignored.
4151 
4152  <P>Each type description has the following columns:
4153  <OL>
4154  <LI><B>TYPE_CAT</B> String => the type's catalog (may be null)
4155  <LI><B>TYPE_SCHEM</B> String => type's schema (may be null)
4156  <LI><B>TYPE_NAME</B> String => type name
4157  <LI><B>CLASS_NAME</B> String => Java class name
4158  <LI><B>DATA_TYPE</B> String => type value defined in java.sql.Types.
4159  One of JAVA_OBJECT, STRUCT, or DISTINCT
4160  <LI><B>REMARKS</B> String => explanatory comment on the type
4161  </OL>
4162 
4163  <P><B>Note:</B> If the driver does not support UDTs, an empty
4164  result set is returned.
4165 
4166  @param catalog a catalog name; "" retrieves those without a
4167  catalog; null means drop catalog name from the selection criteria
4168  @param schemaPattern a schema name pattern; "" retrieves those
4169  without a schema
4170  @param typeNamePattern a type name pattern; may be a fully-qualified name
4171  @param types a list of user-named types to include (JAVA_OBJECT,
4172  STRUCT, or DISTINCT); null returns all types
4173  @return <code>ResultSet</code> - each row is a type description
4174 }
4175 function TZAbstractDatabaseMetadata.GetUDTs(const Catalog: string;
4176  const SchemaPattern: string; const TypeNamePattern: string;
4177  const Types: TIntegerDynArray): IZResultSet;
4178 var
4179  Key: string;
4180 begin
4181  if not GetConnection.UseMetadata then
4182  begin
4183  Result := ConstructVirtualResultSet(UDTColumnsDynArray);
4184  exit;
4185  end;
4186 
4187  Key := GetUDTsCacheKey(Catalog, SchemaPattern, TypeNamePattern,
4188  Types);
4189 
4190  Result := GetResultSetFromCache(Key);
4191  if Result = nil then
4192  begin
4193  Result := UncachedGetUDTs(Catalog, SchemaPattern, TypeNamePattern, Types);
4194  AddResultSetToCache(Key, Result);
4195  end;
4196 end;
4197 
4198 {**
4199 
4200  Gets a description of the user-defined types defined in a particular
4201  schema. Schema-specific UDTs may have type JAVA_OBJECT, STRUCT,
4202  or DISTINCT.
4203 
4204  <P>Only types matching the catalog, schema, type name and type
4205  criteria are returned. They are ordered by DATA_TYPE, TYPE_SCHEM
4206  and TYPE_NAME. The type name parameter may be a fully-qualified
4207  name. In this case, the catalog and schemaPattern parameters are
4208  ignored.
4209 
4210  <P>Each type description has the following columns:
4211  <OL>
4212  <LI><B>TYPE_CAT</B> String => the type's catalog (may be null)
4213  <LI><B>TYPE_SCHEM</B> String => type's schema (may be null)
4214  <LI><B>TYPE_NAME</B> String => type name
4215  <LI><B>CLASS_NAME</B> String => Java class name
4216  <LI><B>DATA_TYPE</B> String => type value defined in java.sql.Types.
4217  One of JAVA_OBJECT, STRUCT, or DISTINCT
4218  <LI><B>REMARKS</B> String => explanatory comment on the type
4219  </OL>
4220 
4221  <P><B>Note:</B> If the driver does not support UDTs, an empty
4222  result set is returned.
4223 
4224  @param catalog a catalog name; "" retrieves those without a
4225  catalog; null means drop catalog name from the selection criteria
4226  @param schemaPattern a schema name pattern; "" retrieves those
4227  without a schema
4228  @param typeNamePattern a type name pattern; may be a fully-qualified name
4229  @param types a list of user-named types to include (JAVA_OBJECT,
4230  STRUCT, or DISTINCT); null returns all types
4231  @return <code>ResultSet</code> - each row is a type description
4232 }
4233 function TZAbstractDatabaseMetadata.UncachedGetUDTs(const Catalog: string;
4234  const SchemaPattern: string; const TypeNamePattern: string;
4235  const Types: TIntegerDynArray): IZResultSet;
4236 begin
4237  Result := ConstructVirtualResultSet(UDTColumnsDynArray);
4238 end;
4239 
4240 {**
4241  Creates ab identifier convertor object.
4242  @returns an identifier convertor object.
4243 }
4244 function TZAbstractDatabaseMetadata.GetIdentifierConvertor:
4245  IZIdentifierConvertor;
4246 begin
4247  Result := TZDefaultIdentifierConvertor.Create(Self);
4248 end;
4249 
4250 {**
4251  Add escape character in the pattern that has wildcards character
4252  @param Pattern The pattern that would be escaped
4253  @return Escaped Pattern
4254 }
4255 function TZAbstractDatabaseMetadata.AddEscapeCharToWildcards(
4256  const Pattern: string): string;
4257 var
4258  i:Integer;
4259  EscapeChar : string;
4260 begin
4261  if GetDatabaseInfo.SupportsNonEscapedSearchStrings then
4262  Result := Pattern
4263  else
4264  begin
4265  EscapeChar := GetDatabaseInfo.GetSearchStringEscape;
4266  if WildcardsArray<>nil then
4267  begin
4268  Result:=StringReplace(Pattern,EscapeChar,EscapeChar+EscapeChar,[rfReplaceAll]);
4269  for i:=0 to High(WildcardsArray) do
4270  Result:=StringReplace(Result,WildcardsArray[i],EscapeChar+WildcardsArray[i],[rfReplaceAll]);
4271  end;
4272  end;
4273 end;
4274 
4275 {**
4276  Set the Wildcards character for WildcardsArray variable.
4277  Overrride this method if the wildcards character is different in other database
4278 }
4279 procedure TZAbstractDatabaseMetadata.FillWildcards;
4280 begin
4281  SetLength(WildcardsArray,1);
4282  WildcardsArray[0]:='%';
4283  {SetLength(WildcardsArray,2);
4284  WildcardsArray[0]:='_'; <---- seems to be a trublemaker, no idea how to test it with our tests. See http://zeoslib.sourceforge.net/viewtopic.php?f=40&t=13184
4285  WildcardsArray[1]:='%';}
4286 end;
4287 
4288 function TZAbstractDatabaseMetadata.NormalizePatternCase(Pattern:String): string;
4289 begin
4290  if not GetIdentifierConvertor.IsQuoted(Pattern) then
4291  if FDatabaseInfo.StoresUpperCaseIdentifiers then
4292  Result := UpperCase(Pattern)
4293  else if FDatabaseInfo.StoresLowerCaseIdentifiers then
4294  Result := LowerCase(Pattern)
4295  else Result := Pattern
4296  else
4297  Result := GetIdentifierConvertor.ExtractQuote(Pattern);
4298 end;
4299 
4300 {**
4301  Get the Wildscards in set of char type
4302  @return TZWildcardsSet type
4303 }
4304 function TZAbstractDatabaseMetadata.GetWildcardsSet:TZWildcardsSet;
4305 var i:Integer;
4306 begin
4307  Result:=[];
4308  for i:=0 to High(WildcardsArray) do
4309  Result:=Result+[WildcardsArray[i]];
4310 end;
4311 
4312 //----------------------------------------------------------------------
4313 // Metadata cache key retrieval API (technobot 2008-06-14):
4314 
4315 {**
4316  returns cache key for GetProcedures metadata entry
4317  @param Catalog a catalog name
4318  @param SchemaPattern a schema name pattern
4319  @param ProcedureNamePattern a procedure name pattern
4320  @return the cache key string
4321 }
4322 function TZAbstractDatabaseMetadata.GetProceduresCacheKey(const Catalog: string;
4323  const SchemaPattern: string; const ProcedureNamePattern: string): string;
4324 begin
4325  Result := Format('get-procedures:%s:%s:%s',
4326  [Catalog, SchemaPattern, ProcedureNamePattern]);
4327 end;
4328 
4329 {**
4330  returns cache key for GetProcedureColumns metadata entry
4331  @param Catalog a catalog name
4332  @param SchemaPattern a schema name pattern
4333  @param ProcedureNamePattern a procedure name pattern
4334  @param ColumnNamePattern a column name pattern
4335  @return the cache key string
4336 }
4337 function TZAbstractDatabaseMetadata.GetProcedureColumnsCacheKey(const Catalog: string;
4338  const SchemaPattern: string; const ProcedureNamePattern: string;
4339  const ColumnNamePattern: string): string;
4340 begin
4341  Result := Format('get-procedure-columns:%s:%s:%s:%s',
4342  [Catalog, SchemaPattern, ProcedureNamePattern, ColumnNamePattern]);
4343 end;
4344 
4345 {**
4346  returns cache key for GetTables metadata entry
4347  @param Catalog a catalog name
4348  @param SchemaPattern a schema name pattern
4349  @param TableNamePattern a table name pattern
4350  @param Types table types list
4351  @return the cache key string
4352 }
4353 function TZAbstractDatabaseMetadata.GetTablesCacheKey(const Catalog: string;
4354  const SchemaPattern: string; const TableNamePattern: string;
4355  const Types: TStringDynArray): string;
4356 var
4357  I: Integer;
4358  Key: string;
4359 begin
4360  Key := '';
4361  for I := Low(Types) to High(Types) do
4362  Key := Key + ':' + Types[I];
4363 
4364  Result := Format('get-tables:%s:%s:%s:%s',
4365  [Catalog, SchemaPattern, TableNamePattern, Key]);
4366 end;
4367 
4368 {**
4369  returns cache key for GetSchemas metadata entry
4370  @return the cache key string
4371 }
4372 function TZAbstractDatabaseMetadata.GetSchemasCacheKey: string;
4373 begin
4374  Result := 'get-schemas';
4375 end;
4376 
4377 {**
4378  returns cache key for GetCatalogs metadata entry
4379  @return the cache key string
4380 }
4381 function TZAbstractDatabaseMetadata.GetCatalogsCacheKey: string;
4382 begin
4383  Result := 'get-catalogs';
4384 end;
4385 
4386 {**
4387  returns cache key for GetTableTypes metadata entry
4388  @return the cache key string
4389 }
4390 function TZAbstractDatabaseMetadata.GetTableTypesCacheKey: string;
4391 begin
4392  Result := 'get-table-types';
4393 end;
4394 
4395 {**
4396  returns cache key for GetColumns metadata entry
4397  @param Catalog a catalog name
4398  @param SchemaPattern a schema name pattern
4399  @param TableNamePattern a table name pattern
4400  @param ColumnNamePattern a column name pattern
4401  @return the cache key string
4402 }
4403 function TZAbstractDatabaseMetadata.GetColumnsCacheKey(const Catalog: string;
4404  const SchemaPattern: string; const TableNamePattern: string;
4405  const ColumnNamePattern: string): string;
4406 begin
4407  Result := Format('get-columns:%s:%s:%s:%s',
4408  [Catalog, SchemaPattern, TableNamePattern, ColumnNamePattern]);
4409 end;
4410 
4411 {**
4412  returns cache key for GetColumnPrivileges metadata entry
4413  @param Catalog a catalog name
4414  @param Schema a schema name
4415  @param Table a table name
4416  @param ColumnNamePattern a column name pattern
4417  @return the cache key string
4418 }
4419 function TZAbstractDatabaseMetadata.GetColumnPrivilegesCacheKey(
4420  const Catalog: string; const Schema: string; const Table: string;
4421  const ColumnNamePattern: string): string;
4422 begin
4423  Result := Format('get-column-privileges:%s:%s:%s:%s',
4424  [Catalog, Schema, Table, ColumnNamePattern]);
4425 end;
4426 
4427 {**
4428  returns cache key for GetTablePrivileges metadata entry
4429  @param Catalog a catalog name
4430  @param SchemaPattern a schema name pattern
4431  @param TableNamePattern a table name pattern
4432  @return the cache key string
4433 }
4434 function TZAbstractDatabaseMetadata.GetTablePrivilegesCacheKey(
4435  const Catalog: string; const SchemaPattern: string;
4436  const TableNamePattern: string): string;
4437 begin
4438  Result := Format('get-table-privileges:%s:%s:%s',
4439  [Catalog, SchemaPattern, TableNamePattern]);
4440 end;
4441 
4442 {**
4443  returns cache key for GetBestRowIdentifier metadata entry
4444  @param Catalog a catalog name
4445  @param Schema a schema name
4446  @param Table a table name
4447  @param Scope the scope of interest
4448  @param Nullable include columns that are nullable?
4449  @return the cache key string
4450 }
4451 function TZAbstractDatabaseMetadata.GetBestRowIdentifierCacheKey(
4452  const Catalog: string; const Schema: string; const Table: string;
4453  const Scope: Integer; const Nullable: Boolean): string;
4454 begin
4455  Result := Format('get-best-row-identifier:%s:%s:%s:%d:%s',
4456  [Catalog, Schema, Table, Scope, BoolToStr(Nullable)]);
4457 end;
4458 
4459 {**
4460  returns cache key for GetVersionColumns metadata entry
4461  @param Catalog a catalog name
4462  @param Schema a schema name
4463  @param Table a table name
4464  @return the cache key string
4465 }
4466 function TZAbstractDatabaseMetadata.GetVersionColumnsCacheKey(
4467  const Catalog: string; const Schema: string; const Table: string): string;
4468 begin
4469  Result := Format('get-version-columns:%s:%s:%s', [Catalog, Schema, Table]);
4470 end;
4471 
4472 {**
4473  returns cache key for GetPrimaryKeys metadata entry
4474  @param Catalog a catalog name
4475  @param Schema a schema name
4476  @param Table a table name
4477  @return the cache key string
4478 }
4479 function TZAbstractDatabaseMetadata.GetPrimaryKeysCacheKey(const Catalog: string;
4480  const Schema: string; const Table: string): string;
4481 begin
4482  Result := Format('get-primary-keys:%s:%s:%s', [Catalog, Schema, Table]);
4483 end;
4484 
4485 {**
4486  returns cache key for GetImportedKeys metadata entry
4487  @param Catalog a catalog name
4488  @param Schema a schema name
4489  @param Table a table name
4490  @return the cache key string
4491 }
4492 function TZAbstractDatabaseMetadata.GetImportedKeysCacheKey(const Catalog: string;
4493  const Schema: string; const Table: string): string;
4494 begin
4495  Result := Format('get-imported-keys:%s:%s:%s', [Catalog, Schema, Table]);
4496 end;
4497 
4498 {**
4499  returns cache key for GetExportedKeys metadata entry
4500  @param Catalog a catalog name
4501  @param Schema a schema name
4502  @param Table a table name
4503  @return the cache key string
4504 }
4505 function TZAbstractDatabaseMetadata.GetExportedKeysCacheKey(const Catalog: string;
4506  const Schema: string; const Table: string): string;
4507 begin
4508  Result := Format('get-exported-keys:%s:%s:%s', [Catalog, Schema, Table]);
4509 end;
4510 
4511 {**
4512  returns cache key for GetCrossReference metadata entry
4513  @param PrimaryCatalog a catalog name for the primary table
4514  @param PrimarySchema a schema name for the primary table
4515  @param PrimaryTable the table name that exports the key
4516  @param ForeignCatalog a catalog name for the foreign table
4517  @param ForeignSchema a schema name for the foreign table
4518  @param ForeignTable the table name that imports the key
4519  @return the cache key string
4520 }
4521 function TZAbstractDatabaseMetadata.GetCrossReferenceCacheKey(
4522  const PrimaryCatalog: string; const PrimarySchema: string;
4523  const PrimaryTable: string; const ForeignCatalog: string;
4524  const ForeignSchema: string; const ForeignTable: string): string;
4525 begin
4526  Result := Format('get-cross-reference:%s:%s:%s:%s:%s:%s',
4527  [PrimaryCatalog, PrimarySchema, PrimaryTable, ForeignCatalog,
4528  ForeignSchema, ForeignTable]);
4529 end;
4530 
4531 {**
4532  returns cache key for GetTypeInfo metadata entry
4533  @return the cache key string
4534 }
4535 function TZAbstractDatabaseMetadata.GetTypeInfoCacheKey: string;
4536 begin
4537  Result := 'get-type-info';
4538 end;
4539 
4540 {**
4541  returns cache key for GetIndexInfo metadata entry
4542  @param Catalog a catalog name
4543  @param Schema a schema name
4544  @param Table a table name
4545  @param Unique when true, return key for a metadata entry that should contain
4546  only indices for unique values; when false, return key for a metadata
4547  entry that may contain indices to non-unique values
4548  @param Approximate when true, return key for a metadata entry that may include
4549  approximate or out of data values; when false, return key for a metadata
4550  entry that should contain only accurate results
4551  @return the cache key string
4552 }
4553 function TZAbstractDatabaseMetadata.GetIndexInfoCacheKey(const Catalog: string;
4554  const Schema: string; const Table: string; const Unique: Boolean;
4555  const Approximate: Boolean): string;
4556 begin
4557  Result := Format('get-index-info:%s:%s:%s:%s:%s',
4558  [Catalog, Schema, Table, BoolToStr(Unique), BoolToStr(Approximate)]);
4559 end;
4560 
4561 {**
4562  returns cache key for GetSequences metadata entry
4563  @param Catalog a catalog name
4564  @param SchemaPattern a schema name pattern
4565  @param SequenceNamePattern a sequence name pattern
4566  @return the cache key string
4567 }
4568 function TZAbstractDatabaseMetadata.GetSequencesCacheKey(const Catalog: string;
4569  const SchemaPattern: string; const SequenceNamePattern: string): string;
4570 begin
4571  Result := Format('get-sequences:%s:%s:%s',
4572  [Catalog, SchemaPattern, SequenceNamePattern]);
4573 end;
4574 
4575 {**
4576  returns cache key for GetUDTs metadata entry
4577  @param Catalog a catalog name
4578  @param SchemaPattern a schema name pattern
4579  @param TypeNamePattern a type name pattern
4580  @param Types a list of user-named types to include
4581  @return the cache key string
4582 }
4583 function TZAbstractDatabaseMetadata.GetUDTsCacheKey(const Catalog: string;
4584  const SchemaPattern: string; const TypeNamePattern: string;
4585  const Types: TIntegerDynArray): string;
4586 var
4587  I: Integer;
4588 begin
4589  Result := '';
4590  for I := Low(Types) to High(Types) do
4591  Result := Result + ':' + IntToStr(Types[I]);
4592  Result := Format('get-udts:%s:%s:%s%s',
4593  [Catalog, SchemaPattern, TypeNamePattern, Result]);
4594 end;
4595 
4596 {**
4597  fills string list with the keys for the currently cached metadata entries
4598  @param List a string list to fill out
4599 }
4600 procedure TZAbstractDatabaseMetadata.GetCacheKeys(List: TStrings);
4601 var
4602  I: Integer;
4603 begin
4604  List.Clear;
4605  with CachedResultSets.Keys do
4606  for I := 0 to Count-1 do
4607  List.Add((Items[I] as IZAnyValue).GetString);
4608 end;
4609 
4610 // End of metadata cache key retrieval API (technobot 2008-06-14)
4611 //----------------------------------------------------------------------
4612 
4613 
4614 { TZVirtualResultSet }
4615 
4616 {**
4617  Creates this object and assignes the main properties.
4618  @param Statement an SQL statement object.
4619  @param SQL an SQL query string.
4620 }
4621 constructor TZVirtualResultSet.CreateWithStatement(const SQL: string;
4622  Statement: IZStatement; ConSettings: PZConSettings);
4623 begin
4624  inherited CreateWithStatement(SQL, Statement, ConSettings);
4625 end;
4626 
4627 {**
4628  Creates this object and assignes the main properties.
4629  @param ColumnsInfo a columns info for cached rows.
4630  @param SQL an SQL query string.
4631 }
4632 constructor TZVirtualResultSet.CreateWithColumns(ColumnsInfo: TObjectList;
4633  const SQL: string; ConSettings: PZConSettings);
4634 begin
4635  inherited CreateWithColumns(ColumnsInfo, SQL, ConSettings);
4636 end;
4637 
4638 {**
4639  Destroys this object and cleanups the memory.
4640 }
4641 destructor TZVirtualResultSet.Destroy;
4642 begin
4643  inherited Destroy;
4644 end;
4645 
4646 {**
4647  Calculates column default values..
4648  @param RowAccessor a row accessor which contains new column values.
4649 }
4650 procedure TZVirtualResultSet.CalculateRowDefaults(RowAccessor: TZRowAccessor);
4651 begin
4652 end;
4653 
4654 {**
4655  Post changes to database server.
4656  @param OldRowAccessor a row accessor which contains old column values.
4657  @param NewRowAccessor a row accessor which contains new or updated
4658  column values.
4659 }
4660 procedure TZVirtualResultSet.PostRowUpdates(OldRowAccessor,
4661  NewRowAccessor: TZRowAccessor);
4662 begin
4663 end;
4664 
4665 { TZDefaultIdentifierConvertor }
4666 
4667 {**
4668  Constructs this default identifier convertor object.
4669  @param Metadata a database metadata interface.
4670 }
4671 constructor TZDefaultIdentifierConvertor.Create(
4672  Metadata: IZDatabaseMetadata);
4673 begin
4674  inherited Create;
4675  FMetadata := Pointer(Metadata);
4676 end;
4677 
4678 function TZDefaultIdentifierConvertor.GetMetaData;
4679 begin
4680  if Assigned(FMetadata) then
4681  Result := IZDatabaseMetadata(FMetadata)
4682  else
4683  Result := nil;
4684 end;
4685 
4686 {**
4687  Checks is the specified string in lower case.
4688  @param an identifier string.
4689  @return <code>True</code> is the identifier string in lower case.
4690 }
4691 function TZDefaultIdentifierConvertor.IsLowerCase(const Value: string): Boolean;
4692 var
4693  I: Integer;
4694 begin
4695  Result := True;
4696  for I := 1 to Length(Value) do
4697  begin
4698  if not CharInSet(Value[I], ['a'..'z','0'..'9','_']) then
4699  begin
4700  Result := False;
4701  Break;
4702  end;
4703  end;
4704 end;
4705 
4706 {**
4707  Checks is the specified string in upper case.
4708  @param an identifier string.
4709  @return <code>True</code> is the identifier string in upper case.
4710 }
4711 function TZDefaultIdentifierConvertor.IsUpperCase(const Value: string): Boolean;
4712 var
4713  I: Integer;
4714 begin
4715  Result := True;
4716  for I := 1 to Length(Value) do
4717  begin
4718  if not CharInSet(Value[I], ['A'..'Z','0'..'9','_']) then
4719  begin
4720  Result := False;
4721  Break;
4722  end;
4723  end;
4724 end;
4725 
4726 {**
4727  Checks is the specified string in special case.
4728  @param an identifier string.
4729  @return <code>True</code> is the identifier string in mixed case.
4730 }
4731 function TZDefaultIdentifierConvertor.IsSpecialCase(const Value: string): Boolean;
4732 var
4733  I: Integer;
4734 begin
4735  Result := False;
4736  if CharInSet(Value[1], ['0'..'9']) then
4737  begin
4738  Result := True;
4739  exit;
4740  end;
4741  for I := 1 to Length(Value) do
4742  begin
4743  if not CharInSet(Value[I], ['A'..'Z','a'..'z','0'..'9','_']) then
4744  begin
4745  Result := True;
4746  Break;
4747  end;
4748  end;
4749 end;
4750 
4751 {**
4752  Checks is the string case sensitive.
4753  @return <code>True</code> if the string case sensitive.
4754 }
4755 function TZDefaultIdentifierConvertor.IsCaseSensitive(const Value: string): Boolean;
4756 const
4757  AnsiSQLKeywords = 'insert,update,delete,select,drop,create,from,set,values,'
4758  + 'where,order,group,by,having,into,as,table,index,primary,key,on,is,null,'
4759  + 'char,varchar,integer,number,alter,column,value,'
4760  + 'current,top,login,status,version';
4761 var
4762  Keywords: string;
4763 begin
4764  if Value = '' then
4765  Result := False
4766  else if IsSpecialCase(Value) then
4767  Result := True
4768  else if IsLowerCase(Value) then
4769  Result := Metadata.GetDatabaseInfo.StoresUpperCaseIdentifiers
4770  else if IsUpperCase(Value) then
4771  Result := Metadata.GetDatabaseInfo.StoresLowerCaseIdentifiers
4772  else
4773  Result := not Metadata.GetDatabaseInfo.StoresMixedCaseIdentifiers;
4774 
4775  { Checks for reserved keywords. }
4776  if not Result then
4777  begin
4778  Keywords := ',' + AnsiSQLKeywords + ','
4779  + LowerCase(Metadata.GetDatabaseInfo.GetSQLKeywords) + ',';
4780  Result := Pos(',' + LowerCase(Value) + ',', Keywords) > 0;
4781  end;
4782 end;
4783 
4784 {**
4785  Checks is the string quoted.
4786  @return <code>True</code> is the string quoted.
4787 }
4788 function TZDefaultIdentifierConvertor.IsQuoted(const Value: string): Boolean;
4789 var
4790  QuoteDelim: string;
4791 begin
4792  QuoteDelim := Metadata.GetDatabaseInfo.GetIdentifierQuoteString;
4793  Result := (QuoteDelim <> '') and (Value <> '') and (QuoteDelim[1] = Value[1]);
4794 end;
4795 
4796 {**
4797  Extracts the quote from the idenfitier string.
4798  @param an identifier string.
4799  @return a extracted and processed string.
4800 }
4801 function TZDefaultIdentifierConvertor.ExtractQuote(const Value: string): string;
4802 begin
4803  if IsQuoted(Value) then
4804  begin
4805  Result := Copy(Value, 2, Length(Value) - 2);
4806  if not Metadata.GetDatabaseInfo.StoresMixedCaseQuotedIdentifiers then
4807  begin
4808  if Metadata.GetDatabaseInfo.StoresLowerCaseQuotedIdentifiers then
4809  Result := LowerCase(Result)
4810  else if Metadata.GetDatabaseInfo.StoresUpperCaseQuotedIdentifiers then
4811  Result := UpperCase(Result);
4812  end;
4813  end
4814  else
4815  begin
4816  Result := Value;
4817  if not Metadata.GetDatabaseInfo.StoresMixedCaseIdentifiers then
4818  begin
4819  if Metadata.GetDatabaseInfo.StoresLowerCaseIdentifiers then
4820  Result := LowerCase(Result)
4821  else if Metadata.GetDatabaseInfo.StoresUpperCaseIdentifiers then
4822  Result := UpperCase(Result);
4823  end;
4824  end;
4825 end;
4826 
4827 {**
4828  Quotes the identifier string.
4829  @param an identifier string.
4830  @return a quoted string.
4831 }
4832 function TZDefaultIdentifierConvertor.Quote(const Value: string): string;
4833 var
4834  QuoteDelim: string;
4835 begin
4836  Result := Value;
4837  if IsCaseSensitive(Value) then
4838  begin
4839  QuoteDelim := Metadata.GetDatabaseInfo.GetIdentifierQuoteString;
4840  if Length(QuoteDelim) > 1 then
4841  Result := QuoteDelim[1] + Result + QuoteDelim[2]
4842  else if Length(QuoteDelim) = 1 then
4843  Result := QuoteDelim[1] + Result + QuoteDelim[1];
4844  end;
4845 end;
4846 
4847 {**
4848  rerurns cache key for get tables metadata entry
4849  @param Catalog catalog name
4850  @param SchemaPattern schema pattern
4851  @param TableNamePattern table name pattern
4852  @param Types table types
4853  @return the cache key string
4854  @deprecated use TZAbstractDatabaseMetadata.GetTablesCacheKey instead
4855 }
4856 function GetTablesMetaDataCacheKey(Const Catalog:String;
4857  Const SchemaPattern:String; Const TableNamePattern:String;const Types: TStringDynArray):String;
4858 Var I : Integer;
4859  Key : String;
4860 begin
4861  Key := '';
4862  for I := Low(Types) to High(Types) do
4863  Key := Key + ':' + Types[I];
4864 
4865  Result:= Format('get-tables:%s:%s:%s:%s',
4866  [Catalog, SchemaPattern, TableNamePattern, Key]);
4867 end;
4868 
4869 
4870 const
4871  CharacterSetsColumnsCount = 2;
4872  CharacterSetsColumns: array[1..CharacterSetsColumnsCount]
4873  of TZMetadataColumnDef =(
4874  (Name: 'CHARACTER_SET_NAME'; SQLType: stString; Length: 35),
4875  (Name: 'CHARACTER_SET_ID'; SQLType: stShort; Length: 0)
4876  );
4877 
4878  CollationCharSetColumnsCount = 8; //EgonHugeist
4879  CollationCharSetColumns: array[1..CollationCharSetColumnsCount]
4880  of TZMetadataColumnDef =(
4881  (Name: 'COLLATION_CATALOG'; SQLType: stString; Length: 35),
4882  (Name: 'COLLATION_SCHEMA'; SQLType: stString; Length: 35),
4883  (Name: 'COLLATION_TABLE'; SQLType: stString; Length: 35),
4884  (Name: 'COLLATION_COLUMN'; SQLType: stString; Length: 35),
4885  (Name: 'COLLATION_NAME'; SQLType: stString; Length: 35),
4886  (Name: 'CHARACTER_SET_NAME'; SQLType: stString; Length: 35),
4887  (Name: 'CHARACTER_SET_ID'; SQLType: stShort; Length: 0),
4888  (Name: 'CHARACTER_SET_SIZE'; SQLType: stShort; Length: 0)
4889  );
4890 
4891  TriggersColumnCount = 8; //EgonHugeist
4892  TriggersColumns: array[1..TriggersColumnCount]
4893  of TZMetadataColumnDef =(
4894  (Name: 'TRIGGER_CAT'; SQLType: stString; Length: 255),
4895  (Name: 'TRIGGER_SCHEM'; SQLType: stString; Length: 255),
4896  (Name: 'TRIGGER_NAME'; SQLType: stString; Length: 255), //RDB$TRIGGER_NAME
4897  (Name: 'TRIGGER_RELATION'; SQLType: stString; Length: 255), //RDB$RELATION_NAME
4898  (Name: 'TRIGGER_TYPE'; SQLType: stShort; Length: 0), //RDB$TRIGGER_TYPE
4899  (Name: 'TRIGGER_INACTIVE'; SQLType: stShort; Length: 0), //RDB$TRIGGER_INACTIVE
4900  (Name: 'TRIGGER_SOURCE'; SQLType: stString; Length: 3000), //RDB$TRIGGER_SOURCE
4901  (Name: 'TRIGGER_DESCRIPTION'; SQLType: stString; Length: 255) //RDB$DESCRIPTION
4902  );
4903 
4904  ProceduresColumnCount = 8;
4905  ProceduresColumns: array[1..ProceduresColumnCount]
4906  of TZMetadataColumnDef =(
4907  (Name: 'PROCEDURE_CAT'; SQLType: stString; Length: 255),
4908  (Name: 'PROCEDURE_SCHEM'; SQLType: stString; Length: 255),
4909  (Name: 'PROCEDURE_NAME'; SQLType: stString; Length: 255),
4910  (Name: 'PROCEDURE_OVERLOAD'; SQLType: stString; Length: 255),
4911  (Name: 'RESERVED1'; SQLType: stString; Length: 255),
4912  (Name: 'RESERVED2'; SQLType: stString; Length: 255),
4913  (Name: 'REMARKS'; SQLType: stString; Length: 255),
4914  (Name: 'PROCEDURE_TYPE'; SQLType: stShort; Length: 0)
4915  );
4916 
4917  ProceduresColColumnCount = 13;
4918  ProceduresColColumns: array[1..ProceduresColColumnCount]
4919  of TZMetadataColumnDef =(
4920  (Name: 'PROCEDURE_CAT'; SQLType: stString; Length: 255),
4921  (Name: 'PROCEDURE_SCHEM'; SQLType: stString; Length: 255),
4922  (Name: 'PROCEDURE_NAME'; SQLType: stString; Length: 255),
4923  (Name: 'COLUMN_NAME'; SQLType: stString; Length: 255),
4924  (Name: 'COLUMN_TYPE'; SQLType: stShort; Length: 0),
4925  (Name: 'DATA_TYPE'; SQLType: stShort; Length: 0),
4926  (Name: 'TYPE_NAME'; SQLType: stString; Length: 255),
4927  (Name: 'PRECISION'; SQLType: stInteger; Length: 0),
4928  (Name: 'LENGTH'; SQLType: stInteger; Length: 0),
4929  (Name: 'SCALE'; SQLType: stShort; Length: 0),
4930  (Name: 'RADIX'; SQLType: stShort; Length: 0),
4931  (Name: 'NULLABLE'; SQLType: stShort; Length: 0),
4932  (Name: 'REMARKS'; SQLType: stString; Length: 255)
4933  );
4934 
4935  TableColumnCount = 5;
4936  TableColumns: array[1..TableColumnCount]
4937  of TZMetadataColumnDef =(
4938  (Name: 'TABLE_CAT'; SQLType: stString; Length: 255),
4939  (Name: 'TABLE_SCHEM'; SQLType: stString; Length: 255),
4940  (Name: 'TABLE_NAME'; SQLType: stString; Length: 255),
4941  (Name: 'TABLE_TYPE'; SQLType: stString; Length: 255),
4942  (Name: 'REMARKS'; SQLType: stString; Length: 255)
4943  );
4944 
4945  SchemaColumnCount = 1;
4946  SchemaColumns: array[1..SchemaColumnCount]
4947  of TZMetadataColumnDef =(
4948  (Name: 'TABLE_SCHEM'; SQLType: stString; Length: 255)
4949  );
4950 
4951  CatalogColumnCount = 1;
4952  CatalogColumns: array[1..CatalogColumnCount]
4953  of TZMetadataColumnDef =(
4954  (Name: 'TABLE_CAT'; SQLType: stString; Length: 255)
4955  );
4956 
4957  TableTypeColumnCount = 1;
4958  TableTypeColumns: array[1..TableTypeColumnCount]
4959  of TZMetadataColumnDef =(
4960  (Name: 'TABLE_TYPE'; SQLType: stString; Length: 255)
4961  );
4962 
4963  TableColColumnCount = 24;
4964  TableColColumns: array[1..TableColColumnCount]
4965  of TZMetadataColumnDef =(
4966  (Name: 'TABLE_CAT'; SQLType: stString; Length: 255),
4967  (Name: 'TABLE_SCHEM'; SQLType: stString; Length: 255),
4968  (Name: 'TABLE_NAME'; SQLType: stString; Length: 255),
4969  (Name: 'COLUMN_NAME'; SQLType: stString; Length: 255),
4970  (Name: 'DATA_TYPE'; SQLType: stShort; Length: 0),
4971  (Name: 'TYPE_NAME'; SQLType: stString; Length: 255),
4972  (Name: 'COLUMN_SIZE'; SQLType: stInteger; Length: 0),
4973  (Name: 'BUFFER_LENGTH'; SQLType: stInteger; Length: 0),
4974  (Name: 'DECIMAL_DIGITS'; SQLType: stInteger; Length: 0),
4975  (Name: 'NUM_PREC_RADIX'; SQLType: stInteger; Length: 0),
4976  (Name: 'NULLABLE'; SQLType: stInteger; Length: 0),
4977  (Name: 'REMARKS'; SQLType: stString; Length: 255),
4978  (Name: 'COLUMN_DEF'; SQLType: stString; Length: 255),
4979  (Name: 'SQL_DATA_TYPE'; SQLType: stInteger; Length: 0),
4980  (Name: 'SQL_DATETIME_SUB'; SQLType: stInteger; Length: 0),
4981  (Name: 'CHAR_OCTET_LENGTH'; SQLType: stInteger; Length: 0),
4982  (Name: 'ORDINAL_POSITION'; SQLType: stInteger; Length: 0),
4983  (Name: 'IS_NULLABLE'; SQLType: stString; Length: 255),
4984  (Name: 'AUTO_INCREMENT'; SQLType: stBoolean; Length: 0),
4985  (Name: 'CASE_SENSITIVE'; SQLType: stBoolean; Length: 0),
4986  (Name: 'SEARCHABLE'; SQLType: stBoolean; Length: 0),
4987  (Name: 'WRITABLE'; SQLType: stBoolean; Length: 0),
4988  (Name: 'DEFINITELYWRITABLE'; SQLType: stBoolean; Length: 0),
4989  (Name: 'READONLY'; SQLType: stBoolean; Length: 0)
4990  );
4991 
4992  TableColPrivColumnCount = 8;
4993  TableColPrivColumns: array[1..TableColPrivColumnCount]
4994  of TZMetadataColumnDef =(
4995  (Name: 'TABLE_CAT'; SQLType: stString; Length: 255),
4996  (Name: 'TABLE_SCHEM'; SQLType: stString; Length: 255),
4997  (Name: 'TABLE_NAME'; SQLType: stString; Length: 255),
4998  (Name: 'COLUMN_NAME'; SQLType: stString; Length: 255),
4999  (Name: 'GRANTOR'; SQLType: stString; Length: 255),
5000  (Name: 'GRANTEE'; SQLType: stString; Length: 255),
5001  (Name: 'PRIVILEGE'; SQLType: stString; Length: 255),
5002  (Name: 'IS_GRANTABLE'; SQLType: stString; Length: 255)
5003  );
5004 
5005  TablePrivColumnCount = 7;
5006  TablePrivColumns: array[1..TablePrivColumnCount]
5007  of TZMetadataColumnDef =(
5008  (Name: 'TABLE_CAT'; SQLType: stString; Length: 255),
5009  (Name: 'TABLE_SCHEM'; SQLType: stString; Length: 255),
5010  (Name: 'TABLE_NAME'; SQLType: stString; Length: 255),
5011  (Name: 'GRANTOR'; SQLType: stString; Length: 255),
5012  (Name: 'GRANTEE'; SQLType: stString; Length: 255),
5013  (Name: 'PRIVILEGE'; SQLType: stString; Length: 255),
5014  (Name: 'IS_GRANTABLE'; SQLType: stString; Length: 255)
5015  );
5016 
5017  BestRowIdentColumnCount = 8;
5018  BestRowIdentColumns: array[1..BestRowIdentColumnCount]
5019  of TZMetadataColumnDef =(
5020  (Name: 'SCOPE'; SQLType: stShort; Length: 0),
5021  (Name: 'COLUMN_NAME'; SQLType: stString; Length: 255),
5022  (Name: 'DATA_TYPE'; SQLType: stShort; Length: 0),
5023  (Name: 'TYPE_NAME'; SQLType: stString; Length: 255),
5024  (Name: 'COLUMN_SIZE'; SQLType: stInteger; Length: 0),
5025  (Name: 'BUFFER_LENGTH'; SQLType: stInteger; Length: 0),
5026  (Name: 'DECIMAL_DIGITS'; SQLType: stShort; Length: 0),
5027  (Name: 'PSEUDO_COLUMN'; SQLType: stShort; Length: 0)
5028  );
5029 
5030  TableColVerColumnCount = 8;
5031  TableColVerColumns: array[1..TableColVerColumnCount]
5032  of TZMetadataColumnDef =(
5033  (Name: 'SCOPE'; SQLType: stShort; Length: 0),
5034  (Name: 'COLUMN_NAME'; SQLType: stString; Length: 255),
5035  (Name: 'DATA_TYPE'; SQLType: stShort; Length: 0),
5036  (Name: 'TYPE_NAME'; SQLType: stString; Length: 255),
5037  (Name: 'COLUMN_SIZE'; SQLType: stInteger; Length: 0),
5038  (Name: 'BUFFER_LENGTH'; SQLType: stInteger; Length: 0),
5039  (Name: 'DECIMAL_DIGITS'; SQLType: stShort; Length: 0),
5040  (Name: 'PSEUDO_COLUMN'; SQLType: stShort; Length: 0)
5041  );
5042 
5043  PrimaryKeyColumnCount = 6;
5044  PrimaryKeyColumns: array[1..PrimaryKeyColumnCount]
5045  of TZMetadataColumnDef =(
5046  (Name: 'TABLE_CAT'; SQLType: stString; Length: 255),
5047  (Name: 'TABLE_SCHEM'; SQLType: stString; Length: 255),
5048  (Name: 'TABLE_NAME'; SQLType: stString; Length: 255),
5049  (Name: 'COLUMN_NAME'; SQLType: stString; Length: 255),
5050  (Name: 'KEY_SEQ'; SQLType: stShort; Length: 0),
5051  (Name: 'PK_NAME'; SQLType: stString; Length: 255)
5052  );
5053 
5054  ImportedKeyColumnCount = 14;
5055  ImportedKeyColumns: array[1..ImportedKeyColumnCount]
5056  of TZMetadataColumnDef =(
5057  (Name: 'PKTABLE_CAT'; SQLType: stString; Length: 255),
5058  (Name: 'PKTABLE_SCHEM'; SQLType: stString; Length: 255),
5059  (Name: 'PKTABLE_NAME'; SQLType: stString; Length: 255),
5060  (Name: 'PKCOLUMN_NAME'; SQLType: stString; Length: 255),
5061  (Name: 'FKTABLE_CAT'; SQLType: stString; Length: 255),
5062  (Name: 'FKTABLE_SCHEM'; SQLType: stString; Length: 255),
5063  (Name: 'FKTABLE_NAME'; SQLType: stString; Length: 255),
5064  (Name: 'FKCOLUMN_NAME'; SQLType: stString; Length: 255),
5065  (Name: 'KEY_SEQ'; SQLType: stShort; Length: 0),
5066  (Name: 'UPDATE_RULE'; SQLType: stShort; Length: 0),
5067  (Name: 'DELETE_RULE'; SQLType: stShort; Length: 0),
5068  (Name: 'FK_NAME'; SQLType: stString; Length: 255),
5069  (Name: 'PK_NAME'; SQLType: stString; Length: 255),
5070  (Name: 'DEFERRABILITY'; SQLType: stShort; Length: 0)
5071  );
5072 
5073  ExportedKeyColumnCount = 14;
5074  ExportedKeyColumns: array[1..ExportedKeyColumnCount]
5075  of TZMetadataColumnDef =(
5076  (Name: 'PKTABLE_CAT'; SQLType: stString; Length: 255),
5077  (Name: 'PKTABLE_SCHEM'; SQLType: stString; Length: 255),
5078  (Name: 'PKTABLE_NAME'; SQLType: stString; Length: 255),
5079  (Name: 'PKCOLUMN_NAME'; SQLType: stString; Length: 255),
5080  (Name: 'FKTABLE_CAT'; SQLType: stString; Length: 255),
5081  (Name: 'FKTABLE_SCHEM'; SQLType: stString; Length: 255),
5082  (Name: 'FKTABLE_NAME'; SQLType: stString; Length: 255),
5083  (Name: 'FKCOLUMN_NAME'; SQLType: stString; Length: 255),
5084  (Name: 'KEY_SEQ'; SQLType: stShort; Length: 0),
5085  (Name: 'UPDATE_RULE'; SQLType: stShort; Length: 0),
5086  (Name: 'DELETE_RULE'; SQLType: stShort; Length: 0),
5087  (Name: 'FK_NAME'; SQLType: stString; Length: 255),
5088  (Name: 'PK_NAME'; SQLType: stString; Length: 255),
5089  (Name: 'DEFERRABILITY'; SQLType: stShort; Length: 0)
5090  );
5091 
5092  CrossRefColumnCount = 14;
5093  CrossRefColumns: array[1..CrossRefColumnCount]
5094  of TZMetadataColumnDef =(
5095  (Name: 'PKTABLE_CAT'; SQLType: stString; Length: 255),
5096  (Name: 'PKTABLE_SCHEM'; SQLType: stString; Length: 255),
5097  (Name: 'PKTABLE_NAME'; SQLType: stString; Length: 255),
5098  (Name: 'PKCOLUMN_NAME'; SQLType: stString; Length: 255),
5099  (Name: 'FKTABLE_CAT'; SQLType: stString; Length: 255),
5100  (Name: 'FKTABLE_SCHEM'; SQLType: stString; Length: 255),
5101  (Name: 'FKTABLE_NAME'; SQLType: stString; Length: 255),
5102  (Name: 'FKCOLUMN_NAME'; SQLType: stString; Length: 255),
5103  (Name: 'KEY_SEQ'; SQLType: stShort; Length: 0),
5104  (Name: 'UPDATE_RULE'; SQLType: stShort; Length: 0),
5105  (Name: 'DELETE_RULE'; SQLType: stShort; Length: 0),
5106  (Name: 'FK_NAME'; SQLType: stString; Length: 255),
5107  (Name: 'PK_NAME'; SQLType: stString; Length: 255),
5108  (Name: 'DEFERRABILITY'; SQLType: stShort; Length: 0)
5109  );
5110 
5111  TypeInfoColumnCount = 18;
5112  TypeInfoColumns: array[1..TypeInfoColumnCount]
5113  of TZMetadataColumnDef =(
5114  (Name: 'TYPE_NAME'; SQLType: stString; Length: 255),
5115  (Name: 'DATA_TYPE'; SQLType: stShort; Length: 0),
5116  (Name: 'PRECISION'; SQLType: stInteger; Length: 0),
5117  (Name: 'LITERAL_PREFIX'; SQLType: stString; Length: 255),
5118  (Name: 'LITERAL_SUFFIX'; SQLType: stString; Length: 255),
5119  (Name: 'CREATE_PARAMS'; SQLType: stString; Length: 255),
5120  (Name: 'NULLABLE'; SQLType: stShort; Length: 0),
5121  (Name: 'CASE_SENSITIVE'; SQLType: stBoolean; Length: 0),
5122  (Name: 'SEARCHABLE'; SQLType: stShort; Length: 0),
5123  (Name: 'UNSIGNED_ATTRIBUTE'; SQLType: stBoolean; Length: 0),
5124  (Name: 'FIXED_PREC_SCALE'; SQLType: stBoolean; Length: 0),
5125  (Name: 'AUTO_INCREMENT'; SQLType: stBoolean; Length: 0),
5126  (Name: 'LOCAL_TYPE_NAME'; SQLType: stString; Length: 255),
5127  (Name: 'MINIMUM_SCALE'; SQLType: stShort; Length: 0),
5128  (Name: 'MAXIMUM_SCALE'; SQLType: stShort; Length: 0),
5129  (Name: 'SQL_DATA_TYPE'; SQLType: stInteger; Length: 0),
5130  (Name: 'SQL_DATETIME_SUB'; SQLType: stInteger; Length: 0),
5131  (Name: 'NUM_PREC_RADIX'; SQLType: stInteger; Length: 0)
5132  );
5133 
5134  IndexInfoColumnCount = 13;
5135  IndexInfoColumns: array[1..IndexInfoColumnCount]
5136  of TZMetadataColumnDef =(
5137  (Name: 'TABLE_CAT'; SQLType: stString; Length: 255),
5138  (Name: 'TABLE_SCHEM'; SQLType: stString; Length: 255),
5139  (Name: 'TABLE_NAME'; SQLType: stString; Length: 255),
5140  (Name: 'NON_UNIQUE'; SQLType: stBoolean; Length: 0),
5141  (Name: 'INDEX_QUALIFIER'; SQLType: stString; Length: 255),
5142  (Name: 'INDEX_NAME'; SQLType: stString; Length: 255),
5143  (Name: 'TYPE'; SQLType: stShort; Length: 0),
5144  (Name: 'ORDINAL_POSITION'; SQLType: stShort; Length: 0),
5145  (Name: 'COLUMN_NAME'; SQLType: stString; Length: 255),
5146  (Name: 'ASC_OR_DESC'; SQLType: stString; Length: 255),
5147  (Name: 'CARDINALITY'; SQLType: stInteger; Length: 0),
5148  (Name: 'PAGES'; SQLType: stInteger; Length: 0),
5149  (Name: 'FILTER_CONDITION'; SQLType: stString; Length: 255)
5150  );
5151 
5152  SequenceColumnCount = 3;
5153  SequenceColumns: array[1..SequenceColumnCount]
5154  of TZMetadataColumnDef = (
5155  (Name: 'SEQUENCE_CAT'; SQLType: stString; Length: 255),
5156  (Name: 'SEQUENCE_SCHEM'; SQLType: stString; Length: 255),
5157  (Name: 'SEQUENCE_NAME'; SQLType: stString; Length: 255)
5158  );
5159 
5160  UDTColumnCount = 6;
5161  UDTColumns: array[1..UDTColumnCount]
5162  of TZMetadataColumnDef =(
5163  (Name: 'TYPE_CAT'; SQLType: stString; Length: 255),
5164  (Name: 'TYPE_SCHEM'; SQLType: stString; Length: 255),
5165  (Name: 'TYPE_NAME'; SQLType: stString; Length: 255),
5166  (Name: 'CLASS_NAME'; SQLType: stString; Length: 255),
5167  (Name: 'DATA_TYPE'; SQLType: stShort; Length: 0),
5168  (Name: 'REMARKS'; SQLType: stString; Length: 255)
5169  );
5170 
5171 var
5172  I: Integer;
5173 
5174 initialization
5175  SetLength(CharacterSetsColumnsDynArray, CharacterSetsColumnsCount);
5176  for I := 1 to CharacterSetsColumnsCount do
5177  CharacterSetsColumnsDynArray[I - 1] := CharacterSetsColumns[I];
5178 
5179  SetLength(CollationCharSetColumnsDynArray, CollationCharSetColumnsCount);
5180  for I := 1 to CollationCharSetColumnsCount do
5181  CollationCharSetColumnsDynArray[I - 1] := CollationCharSetColumns[I];
5182 
5183  SetLength(TriggersColumnsDynArray, TriggersColumnCount);
5184  for I := 1 to TriggersColumnCount do
5185  TriggersColumnsDynArray[I - 1] := TriggersColumns[I];
5186 
5187  SetLength(ProceduresColumnsDynArray, ProceduresColumnCount);
5188  for I := 1 to ProceduresColumnCount do
5189  ProceduresColumnsDynArray[I - 1] := ProceduresColumns[I];
5190 
5191  SetLength(ProceduresColColumnsDynArray, ProceduresColColumnCount);
5192  for I := 1 to ProceduresColColumnCount do
5193  ProceduresColColumnsDynArray[I - 1] := ProceduresColColumns[I];
5194 
5195  SetLength(TableColumnsDynArray, TableColumnCount);
5196  for I := 1 to TableColumnCount do
5197  TableColumnsDynArray[I - 1] := TableColumns[I];
5198 
5199  SetLength(SchemaColumnsDynArray, SchemaColumnCount);
5200  for I := 1 to SchemaColumnCount do
5201  SchemaColumnsDynArray[I - 1] := SchemaColumns[I];
5202 
5203  SetLength(CatalogColumnsDynArray, CatalogColumnCount);
5204  for I := 1 to CatalogColumnCount do
5205  CatalogColumnsDynArray[I - 1] := CatalogColumns[I];
5206 
5207  SetLength(TableTypeColumnsDynArray, TableTypeColumnCount);
5208  for I := 1 to TableTypeColumnCount do
5209  TableTypeColumnsDynArray[I - 1] := TableTypeColumns[I];
5210 
5211  SetLength(TableColColumnsDynArray, TableColColumnCount);
5212  for I := 1 to TableColColumnCount do
5213  TableColColumnsDynArray[I - 1] := TableColColumns[I];
5214 
5215  SetLength(TableColPrivColumnsDynArray, TableColPrivColumnCount);
5216  for I := 1 to TableColPrivColumnCount do
5217  TableColPrivColumnsDynArray[I - 1] := TableColPrivColumns[I];
5218 
5219  SetLength(TablePrivColumnsDynArray, TablePrivColumnCount);
5220  for I := 1 to TablePrivColumnCount do
5221  TablePrivColumnsDynArray[I - 1] := TablePrivColumns[I];
5222 
5223  SetLength(BestRowIdentColumnsDynArray, BestRowIdentColumnCount);
5224  for I := 1 to BestRowIdentColumnCount do
5225  BestRowIdentColumnsDynArray[I - 1] := BestRowIdentColumns[I];
5226 
5227  SetLength(TableColVerColumnsDynArray, TableColVerColumnCount);
5228  for I := 1 to TableColVerColumnCount do
5229  TableColVerColumnsDynArray[I - 1] := TableColVerColumns[I];
5230 
5231  SetLength(PrimaryKeyColumnsDynArray, PrimaryKeyColumnCount);
5232  for I := 1 to PrimaryKeyColumnCount do
5233  PrimaryKeyColumnsDynArray[I - 1] := PrimaryKeyColumns[I];
5234 
5235  SetLength(ImportedKeyColumnsDynArray, ImportedKeyColumnCount);
5236  for I := 1 to ImportedKeyColumnCount do
5237  ImportedKeyColumnsDynArray[I - 1] := ImportedKeyColumns[I];
5238 
5239  SetLength(ExportedKeyColumnsDynArray, ExportedKeyColumnCount);
5240  for I := 1 to ExportedKeyColumnCount do
5241  ExportedKeyColumnsDynArray[I - 1] := ExportedKeyColumns[I];
5242 
5243  SetLength(CrossRefColumnsDynArray, CrossRefColumnCount);
5244  for I := 1 to CrossRefColumnCount do
5245  CrossRefColumnsDynArray[I - 1] := CrossRefColumns[I];
5246 
5247  SetLength(TypeInfoColumnsDynArray, TypeInfoColumnCount);
5248  for I := 1 to TypeInfoColumnCount do
5249  TypeInfoColumnsDynArray[I - 1] := TypeInfoColumns[I];
5250 
5251  SetLength(IndexInfoColumnsDynArray, IndexInfoColumnCount);
5252  for I := 1 to IndexInfoColumnCount do
5253  IndexInfoColumnsDynArray[I - 1] := IndexInfoColumns[I];
5254 
5255  SetLength(SequenceColumnsDynArray, SequenceColumnCount);
5256  for I := 1 to SequenceColumnCount do
5257  SequenceColumnsDynArray[I - 1] := SequenceColumns[I];
5258 
5259  SetLength(UDTColumnsDynArray, UDTColumnCount);
5260  for I := 1 to UDTColumnCount do
5261  UDTColumnsDynArray[I - 1] := UDTColumns[I];
5262 end.