00001 {*********************************************************}
00002 { }
00003 { Zeos Database Objects }
00004 { Ado metadata information }
00005 { }
00006 { Originally written by Janos Fegyverneki }
00007 { }
00008 {*********************************************************}
00009
00010 {@********************************************************}
00011 { Copyright (c) 1999-2006 Zeos Development Group }
00012 { }
00013 { License Agreement: }
00014 { }
00015 { This library is distributed in the hope that it will be }
00016 { useful, but WITHOUT ANY WARRANTY; without even the }
00017 { implied warranty of MERCHANTABILITY or FITNESS FOR }
00018 { A PARTICULAR PURPOSE. See the GNU Lesser General }
00019 { Public License for more details. }
00020 { }
00021 { The source code of the ZEOS Libraries and packages are }
00022 { distributed under the Library GNU General Public }
00023 { License (see the file COPYING / COPYING.ZEOS) }
00024 { with the following modification: }
00025 { As a special exception, the copyright holders of this }
00026 { library give you permission to link this library with }
00027 { independent modules to produce an executable, }
00028 { regardless of the license terms of these independent }
00029 { modules, and to copy and distribute the resulting }
00030 { executable under terms of your choice, provided that }
00031 { you also meet, for each linked independent module, }
00032 { the terms and conditions of the license of that module. }
00033 { An independent module is a module which is not derived }
00034 { from or based on this library. If you modify this }
00035 { library, you may extend this exception to your version }
00036 { of the library, but you are not obligated to do so. }
00037 { If you do not wish to do so, delete this exception }
00038 { statement from your version. }
00039 { }
00040 { }
00041 { The project web site is located on: }
00042 { http:
00043 { http:
00044 { svn:
00045 { }
00046 { http:
00047 { http:
00048 { }
00049 { }
00050 { }
00051 { Zeos Development Group. }
00052 {********************************************************@}
00053
00054 unit ZDbcAdoMetadata;
00055
00056 interface
00057
00058 {$I ZDbc.inc}
00059
00060 uses
00061 {$IFNDEF UNIX}
00062 {$IFNDEF VER130BELOW}
00063 Types,
00064 {$ENDIF}
00065 {$ENDIF}
00066 Classes, SysUtils, ZSysUtils, ZClasses, ZDbcIntfs, ZDbcMetadata,
00067 ZDbcResultSet, ZDbcCachedResultSet, ZDbcResultsetMetadata,
00068 ZCompatibility, ZGenericSqlAnalyser, ZPlainAdo, ZDbcConnection;
00069
00070 type
00071 {** Implements Ado Metadata. }
00072 TZAdoDatabaseMetadata = class(TZAbstractDatabaseMetadata)
00073 private
00074 FAdoConnection: ZPlainAdo.Connection;
00075 FSupportedSchemasInitialized: Boolean;
00076 function AdoOpenSchema(Schema: Integer; const Args: array of const): ZPlainAdo.RecordSet;
00077 procedure InitializeSchemas;
00078 function SchemaSupported(SchemaId: Integer): Boolean;
00079 function FindSchema(SchemaId: Integer): Integer;
00080 function BuildRestrictions(SchemaId: Integer; const Args: array of const): Variant;
00081 protected
00082 function GetStatement: IZSTatement;
00083 function UncachedGetTables(const Catalog: string; const SchemaPattern: string;
00084 const TableNamePattern: string; const Types: TStringDynArray): IZResultSet; override;
00085 function UncachedGetSchemas: IZResultSet; override;
00086 function UncachedGetCatalogs: IZResultSet; override;
00087 function UncachedGetTableTypes: IZResultSet; override;
00088 function UncachedGetColumns(const Catalog: string; const SchemaPattern: string;
00089 const TableNamePattern: string; const ColumnNamePattern: string): IZResultSet; override;
00090 function UncachedGetTablePrivileges(const Catalog: string; const SchemaPattern: string;
00091 const TableNamePattern: string): IZResultSet; override;
00092 function UncachedGetColumnPrivileges(const Catalog: string; const Schema: string;
00093 const Table: string; const ColumnNamePattern: string): IZResultSet; override;
00094 function UncachedGetPrimaryKeys(const Catalog: string; const Schema: string;
00095 const Table: string): IZResultSet; override;
00096 function UncachedGetImportedKeys(const Catalog: string; const Schema: string;
00097 const Table: string): IZResultSet; override;
00098 function UncachedGetExportedKeys(const Catalog: string; const Schema: string;
00099 const Table: string): IZResultSet; override;
00100 function UncachedGetCrossReference(const PrimaryCatalog: string; const PrimarySchema: string;
00101 const PrimaryTable: string; const ForeignCatalog: string; const ForeignSchema: string;
00102 const ForeignTable: string): IZResultSet; override;
00103 function UncachedGetIndexInfo(const Catalog: string; const Schema: string; const Table: string;
00104 Unique: Boolean; Approximate: Boolean): IZResultSet; override;
00105
00106
00107 function UncachedGetProcedures(const Catalog: string; const SchemaPattern: string;
00108 const ProcedureNamePattern: string): IZResultSet; override;
00109 function UncachedGetProcedureColumns(const Catalog: string; const SchemaPattern: string;
00110 const ProcedureNamePattern: string; const ColumnNamePattern: string):
00111 IZResultSet; override;
00112 function UncachedGetVersionColumns(const Catalog: string; const Schema: string;
00113 const Table: string): IZResultSet; override;
00114 function UncachedGetTypeInfo: IZResultSet; override;
00115 function UncachedGetUDTs(const Catalog: string; const SchemaPattern: string;
00116 const TypeNamePattern: string; const Types: TIntegerDynArray): IZResultSet; override;
00117 public
00118 constructor Create(Connection: TZAbstractConnection; Url: string;
00119 Info: TStrings);
00120 destructor Destroy; override;
00121
00122 function GetDatabaseProductName: string; override;
00123 function GetDatabaseProductVersion: string; override;
00124 function GetDriverName: string; override;
00125 function GetDriverMajorVersion: Integer; override;
00126 function GetDriverMinorVersion: Integer; override;
00127 function UsesLocalFilePerTable: Boolean; override;
00128 function SupportsMixedCaseIdentifiers: Boolean; override;
00129 function StoresUpperCaseIdentifiers: Boolean; override;
00130 function StoresLowerCaseIdentifiers: Boolean; override;
00131 function StoresMixedCaseIdentifiers: Boolean; override;
00132 function SupportsMixedCaseQuotedIdentifiers: Boolean; override;
00133 function StoresUpperCaseQuotedIdentifiers: Boolean; override;
00134 function StoresLowerCaseQuotedIdentifiers: Boolean; override;
00135 function StoresMixedCaseQuotedIdentifiers: Boolean; override;
00136 function GetIdentifierQuoteString: string; override;
00137 function GetSQLKeywords: string; override;
00138 function GetNumericFunctions: string; override;
00139 function GetStringFunctions: string; override;
00140 function GetSystemFunctions: string; override;
00141 function GetTimeDateFunctions: string; override;
00142 function GetSearchStringEscape: string; override;
00143 function GetExtraNameCharacters: string; override;
00144
00145 function SupportsExpressionsInOrderBy: Boolean; override;
00146 function SupportsOrderByUnrelated: Boolean; override;
00147 function SupportsGroupBy: Boolean; override;
00148 function SupportsGroupByUnrelated: Boolean; override;
00149 function SupportsGroupByBeyondSelect: Boolean; override;
00150 function SupportsIntegrityEnhancementFacility: Boolean; override;
00151 function GetSchemaTerm: string; override;
00152 function GetProcedureTerm: string; override;
00153 function GetCatalogTerm: string; override;
00154 function GetCatalogSeparator: string; override;
00155 function SupportsSchemasInDataManipulation: Boolean; override;
00156 function SupportsSchemasInProcedureCalls: Boolean; override;
00157 function SupportsSchemasInTableDefinitions: Boolean; override;
00158 function SupportsSchemasInIndexDefinitions: Boolean; override;
00159 function SupportsSchemasInPrivilegeDefinitions: Boolean; override;
00160 function SupportsCatalogsInDataManipulation: Boolean; override;
00161 function SupportsCatalogsInProcedureCalls: Boolean; override;
00162 function SupportsCatalogsInTableDefinitions: Boolean; override;
00163 function SupportsCatalogsInIndexDefinitions: Boolean; override;
00164 function SupportsCatalogsInPrivilegeDefinitions: Boolean; override;
00165 function SupportsPositionedDelete: Boolean; override;
00166 function SupportsPositionedUpdate: Boolean; override;
00167 function SupportsSelectForUpdate: Boolean; override;
00168 function SupportsStoredProcedures: Boolean; override;
00169 function SupportsSubqueriesInComparisons: Boolean; override;
00170 function SupportsSubqueriesInExists: Boolean; override;
00171 function SupportsSubqueriesInIns: Boolean; override;
00172 function SupportsSubqueriesInQuantifieds: Boolean; override;
00173 function SupportsCorrelatedSubqueries: Boolean; override;
00174 function SupportsUnion: Boolean; override;
00175 function SupportsUnionAll: Boolean; override;
00176 function SupportsOpenCursorsAcrossCommit: Boolean; override;
00177 function SupportsOpenCursorsAcrossRollback: Boolean; override;
00178 function SupportsOpenStatementsAcrossCommit: Boolean; override;
00179 function SupportsOpenStatementsAcrossRollback: Boolean; override;
00180
00181 function GetMaxBinaryLiteralLength: Integer; override;
00182 function GetMaxCharLiteralLength: Integer; override;
00183 function GetMaxColumnNameLength: Integer; override;
00184 function GetMaxColumnsInGroupBy: Integer; override;
00185 function GetMaxColumnsInIndex: Integer; override;
00186 function GetMaxColumnsInOrderBy: Integer; override;
00187 function GetMaxColumnsInSelect: Integer; override;
00188 function GetMaxColumnsInTable: Integer; override;
00189 function GetMaxConnections: Integer; override;
00190 function GetMaxCursorNameLength: Integer; override;
00191 function GetMaxIndexLength: Integer; override;
00192 function GetMaxSchemaNameLength: Integer; override;
00193 function GetMaxProcedureNameLength: Integer; override;
00194 function GetMaxCatalogNameLength: Integer; override;
00195 function GetMaxRowSize: Integer; override;
00196 function DoesMaxRowSizeIncludeBlobs: Boolean; override;
00197 function GetMaxStatementLength: Integer; override;
00198 function GetMaxStatements: Integer; override;
00199 function GetMaxTableNameLength: Integer; override;
00200 function GetMaxTablesInSelect: Integer; override;
00201 function GetMaxUserNameLength: Integer; override;
00202
00203 function GetDefaultTransactionIsolation: TZTransactIsolationLevel; override;
00204 function SupportsTransactions: Boolean; override;
00205 function SupportsTransactionIsolationLevel(Level: TZTransactIsolationLevel):
00206 Boolean; override;
00207 function SupportsDataDefinitionAndDataManipulationTransactions: Boolean; override;
00208 function SupportsDataManipulationTransactionsOnly: Boolean; override;
00209 function DataDefinitionCausesTransactionCommit: Boolean; override;
00210 function DataDefinitionIgnoredInTransactions: Boolean; override;
00211
00212 function SupportsResultSetType(_Type: TZResultSetType): Boolean; override;
00213 function SupportsResultSetConcurrency(_Type: TZResultSetType;
00214 Concurrency: TZResultSetConcurrency): Boolean; override;
00215
00216
00217 end;
00218
00219 implementation
00220
00221 uses
00222 {$IFNDEF VER130BELOW}
00223 Variants,
00224 {$ENDIF}
00225 Math, ZDbcUtils, ZCollections, ZGenericSqlToken, ZDbcAdoUtils, ZDbcAdo,
00226 OleDB, ZDbcAdoResultSet;
00227
00228 type
00229 TSuppSchemaRec = record
00230 SchemaGuid: TGuid;
00231 SupportedRestrictions: Integer;
00232 AdoSchemaId: Integer;
00233 end;
00234
00235 IDBSchemaRowset = interface(IUnknown)
00236 ['{0c733a7b-2a1c-11ce-ade5-00aa0044773d}']
00237 function GetRowset(
00238 pUnkOuter : IUnknown;
00239 const rguidSchema : TGUID;
00240 cRestrictions : Integer;
00241 var rgRestrictions : PVariant;{!!was: const VARIANT __RPC_FAR rgRestrictions[ ],}
00242 const riid : IUnknown;
00243 cPropertySets : Integer;
00244 var rgPropertySets : TDBPROPSET;
00245 var ppRowset : IUnknown) : HResult; stdcall;
00246 function GetSchemas(
00247 var pcSchemas : Integer;
00248 var prgSchemas : PGUID;
00249 var prgRestrictionSupport : PInteger) : HResult; stdcall;
00250 end;
00251
00252 var
00253 SupportedSchemas: array of TSuppSchemaRec;
00254
00255 { TZAdoDatabaseMetadata }
00256
00257 {**
00258 Constructs this object and assignes the main properties.
00259 @param Connection a database connection object.
00260 @param Url a database connection url string.
00261 @param Info an extra connection properties.
00262 }
00263 constructor TZAdoDatabaseMetadata.Create(Connection: TZAbstractConnection;
00264 Url: string; Info: TStrings);
00265 begin
00266 inherited Create(Connection, Url, Info);
00267 FAdoConnection := nil;
00268 end;
00269
00270 {**
00271 Destroys this object and cleanups the memory.
00272 }
00273 destructor TZAdoDatabaseMetadata.Destroy;
00274 begin
00275 inherited Destroy;
00276 end;
00277
00278
00279
00280
00281 {**
00282 What's the name of this database product?
00283 @return database product name
00284 }
00285 function TZAdoDatabaseMetadata.GetDatabaseProductName: string;
00286 begin
00287 Result := 'ado';
00288 end;
00289
00290 {**
00291 What's the version of this database product?
00292 @return database version
00293 }
00294 function TZAdoDatabaseMetadata.GetDatabaseProductVersion: string;
00295 begin
00296 Result := (GetConnection as IZAdoConnection).GetAdoConnection.Version;
00297 end;
00298
00299 {**
00300 What's the name of this JDBC driver?
00301 @return JDBC driver name
00302 }
00303 function TZAdoDatabaseMetadata.GetDriverName: string;
00304 begin
00305 Result := 'Zeos Database Connectivity Driver for Microsoft ADO';
00306 end;
00307
00308 {**
00309 What's this JDBC driver's major version number?
00310 @return JDBC driver major version
00311 }
00312 function TZAdoDatabaseMetadata.GetDriverMajorVersion: Integer;
00313 begin
00314 Result := 1;
00315 end;
00316
00317 {**
00318 What's this JDBC driver's minor version number?
00319 @return JDBC driver minor version number
00320 }
00321 function TZAdoDatabaseMetadata.GetDriverMinorVersion: Integer;
00322 begin
00323 Result := 0;
00324 end;
00325
00326 {**
00327 Does the database use a file for each table?
00328 @return true if the database uses a local file for each table
00329 }
00330 function TZAdoDatabaseMetadata.UsesLocalFilePerTable: Boolean;
00331 begin
00332 Result := False;
00333 end;
00334
00335 {**
00336 Does the database treat mixed case unquoted SQL identifiers as
00337 case sensitive and as a result store them in mixed case?
00338 A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will
00339 always return false.
00340 @return <code>true</code> if so; <code>false</code> otherwise
00341 }
00342 function TZAdoDatabaseMetadata.SupportsMixedCaseIdentifiers: Boolean;
00343 begin
00344 Result := False;
00345 end;
00346
00347 {**
00348 Does the database treat mixed case unquoted SQL identifiers as
00349 case insensitive and store them in upper case?
00350 @return <code>true</code> if so; <code>false</code> otherwise
00351 }
00352 function TZAdoDatabaseMetadata.StoresUpperCaseIdentifiers: Boolean;
00353 begin
00354 Result := True;
00355 end;
00356
00357 {**
00358 Does the database treat mixed case unquoted SQL identifiers as
00359 case insensitive and store them in lower case?
00360 @return <code>true</code> if so; <code>false</code> otherwise
00361 }
00362 function TZAdoDatabaseMetadata.StoresLowerCaseIdentifiers: Boolean;
00363 begin
00364 Result := True;
00365 end;
00366
00367 {**
00368 Does the database treat mixed case unquoted SQL identifiers as
00369 case insensitive and store them in mixed case?
00370 @return <code>true</code> if so; <code>false</code> otherwise
00371 }
00372 function TZAdoDatabaseMetadata.StoresMixedCaseIdentifiers: Boolean;
00373 begin
00374 Result := True;
00375 end;
00376
00377 {**
00378 Does the database treat mixed case quoted SQL identifiers as
00379 case sensitive and as a result store them in mixed case?
00380 A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will always return true.
00381 @return <code>true</code> if so; <code>false</code> otherwise
00382 }
00383 function TZAdoDatabaseMetadata.SupportsMixedCaseQuotedIdentifiers: Boolean;
00384 begin
00385 Result := True;
00386 end;
00387
00388 {**
00389 Does the database treat mixed case quoted SQL identifiers as
00390 case insensitive and store them in upper case?
00391 @return <code>true</code> if so; <code>false</code> otherwise
00392 }
00393 function TZAdoDatabaseMetadata.StoresUpperCaseQuotedIdentifiers: Boolean;
00394 begin
00395 Result := True;
00396 end;
00397
00398 {**
00399 Does the database treat mixed case quoted SQL identifiers as
00400 case insensitive and store them in lower case?
00401 @return <code>true</code> if so; <code>false</code> otherwise
00402 }
00403 function TZAdoDatabaseMetadata.StoresLowerCaseQuotedIdentifiers: Boolean;
00404 begin
00405 Result := True;
00406 end;
00407
00408 {**
00409 Does the database treat mixed case quoted SQL identifiers as
00410 case insensitive and store them in mixed case?
00411 @return <code>true</code> if so; <code>false</code> otherwise
00412 }
00413 function TZAdoDatabaseMetadata.StoresMixedCaseQuotedIdentifiers: Boolean;
00414 begin
00415 Result := True;
00416 end;
00417
00418 {**
00419 What's the string used to quote SQL identifiers?
00420 This returns a space " " if identifier quoting isn't supported.
00421 A JDBC Compliant<sup><font size=-2>TM</font></sup>
00422 driver always uses a double quote character.
00423 @return the quoting string
00424 }
00425 function TZAdoDatabaseMetadata.GetIdentifierQuoteString: string;
00426 begin
00427 Result := '[]';
00428 end;
00429
00430 {**
00431 Gets a comma-separated list of all a database's SQL keywords
00432 that are NOT also SQL92 keywords.
00433 @return the list
00434 }
00435 function TZAdoDatabaseMetadata.GetSQLKeywords: string;
00436 begin
00437 { TODO -ofjanos -cAPI : SQL Keywords that are not SQL92 compliant }
00438 Result := '';
00439 end;
00440
00441 {**
00442 Gets a comma-separated list of math functions. These are the
00443 X/Open CLI math function names used in the JDBC function escape
00444 clause.
00445 @return the list
00446 }
00447 function TZAdoDatabaseMetadata.GetNumericFunctions: string;
00448 begin
00449 Result := 'ABS,ACOS,ASIN,ATAN,ATN2,CEILING,COS,COT,DEGREES,EXP,FLOOR,LOG,LOG10,'+
00450 'PI,POWER,RADIANS,RAND,ROUND,SIGN,SIN,SQUARE,SQRT,TAN';
00451 end;
00452
00453 {**
00454 Gets a comma-separated list of string functions. These are the
00455 X/Open CLI string function names used in the JDBC function escape
00456 clause.
00457 @return the list
00458 }
00459 function TZAdoDatabaseMetadata.GetStringFunctions: string;
00460 begin
00461 Result := 'ASCII,CHAR,CHARINDEX,DIFFERENCE,LEFT,LEN,LOWER,LTRIM,NCHAR,PATINDEX,'+
00462 'REPLACE,QUOTENAME,REPLICATE,REVERSE,RIGHT,RTRIM,SOUNDEX,SPACE,STR,'+
00463 'STUFF,SUBSTRING,UNICODE,UPPER';
00464 end;
00465
00466 {**
00467 Gets a comma-separated list of system functions. These are the
00468 X/Open CLI system function names used in the JDBC function escape
00469 clause.
00470 @return the list
00471 }
00472 function TZAdoDatabaseMetadata.GetSystemFunctions: string;
00473 begin
00474 Result := 'APP_NAME,CASE,CAST,CONVERT,COALESCE,CURRENT_TIMESTAMP,CURRENT_USER,'+
00475 'DATALENGTH,@@ERROR,FORMATMESSAGE,GETANSINULL,HOST_ID,HOST_NAME,'+
00476 'IDENT_INCR,IDENT_SEED,@@IDENTITY,IDENTITY,ISDATE,ISNULL,ISNUMERIC,'+
00477 'NEWID,NULLIF,PARSENAME,PERMISSIONS,@@ROWCOUNT,SESSION_USER,STATS_DATE,'+
00478 'SYSTEM_USER,@@TRANCOUNT,USER_NAME';
00479 end;
00480
00481 {**
00482 Gets a comma-separated list of time and date functions.
00483 @return the list
00484 }
00485 function TZAdoDatabaseMetadata.GetTimeDateFunctions: string;
00486 begin
00487 Result := 'DATEADD,DATEDIFF,DATENAME,DATEPART,DAY,GETDATE,MONTH,YEAR';
00488 end;
00489
00490 {**
00491 Gets the string that can be used to escape wildcard characters.
00492 This is the string that can be used to escape '_' or '%' in
00493 the string pattern style catalog search parameters.
00494
00495 <P>The '_' character represents any single character.
00496 <P>The '%' character represents any sequence of zero or
00497 more characters.
00498
00499 @return the string used to escape wildcard characters
00500 }
00501 function TZAdoDatabaseMetadata.GetSearchStringEscape: string;
00502 begin
00503 { TODO -ofjanos -cgeneral :
00504 In sql server this must be specified as the parameter of like.
00505 example: WHERE ColumnA LIKE '%5/%%' ESCAPE '/' }
00506 Result := '/';
00507 end;
00508
00509 {**
00510 Gets all the "extra" characters that can be used in unquoted
00511 identifier names (those beyond a-z, A-Z, 0-9 and _).
00512 @return the string containing the extra characters
00513 }
00514 function TZAdoDatabaseMetadata.GetExtraNameCharacters: string;
00515 begin
00516 Result := '@$#';
00517 end;
00518
00519
00520
00521
00522 {**
00523 Are expressions in "ORDER BY" lists supported?
00524 @return <code>true</code> if so; <code>false</code> otherwise
00525 }
00526 function TZAdoDatabaseMetadata.SupportsExpressionsInOrderBy: Boolean;
00527 begin
00528 Result := True;
00529 end;
00530
00531 {**
00532 Can an "ORDER BY" clause use columns not in the SELECT statement?
00533 @return <code>true</code> if so; <code>false</code> otherwise
00534 }
00535 function TZAdoDatabaseMetadata.SupportsOrderByUnrelated: Boolean;
00536 begin
00537 Result := True;
00538 end;
00539
00540 {**
00541 Is some form of "GROUP BY" clause supported?
00542 @return <code>true</code> if so; <code>false</code> otherwise
00543 }
00544 function TZAdoDatabaseMetadata.SupportsGroupBy: Boolean;
00545 begin
00546 Result := True;
00547 end;
00548
00549 {**
00550 Can a "GROUP BY" clause use columns not in the SELECT?
00551 @return <code>true</code> if so; <code>false</code> otherwise
00552 }
00553 function TZAdoDatabaseMetadata.SupportsGroupByUnrelated: Boolean;
00554 begin
00555 Result := True;
00556 end;
00557
00558 {**
00559 Can a "GROUP BY" clause add columns not in the SELECT
00560 provided it specifies all the columns in the SELECT?
00561 @return <code>true</code> if so; <code>false</code> otherwise
00562 }
00563 function TZAdoDatabaseMetadata.SupportsGroupByBeyondSelect: Boolean;
00564 begin
00565 Result := True;
00566 end;
00567
00568 {**
00569 Is the SQL Integrity Enhancement Facility supported?
00570 @return <code>true</code> if so; <code>false</code> otherwise
00571 }
00572 function TZAdoDatabaseMetadata.SupportsIntegrityEnhancementFacility: Boolean;
00573 begin
00574 Result := False;
00575 end;
00576
00577 {**
00578 What's the database vendor's preferred term for "schema"?
00579 @return the vendor term
00580 }
00581 function TZAdoDatabaseMetadata.GetSchemaTerm: string;
00582 begin
00583 Result := 'owner';
00584 end;
00585
00586 {**
00587 What's the database vendor's preferred term for "procedure"?
00588 @return the vendor term
00589 }
00590 function TZAdoDatabaseMetadata.GetProcedureTerm: string;
00591 begin
00592 Result := 'procedure';
00593 end;
00594
00595 {**
00596 What's the database vendor's preferred term for "catalog"?
00597 @return the vendor term
00598 }
00599 function TZAdoDatabaseMetadata.GetCatalogTerm: string;
00600 begin
00601 Result := 'database';
00602 end;
00603
00604 {**
00605 What's the separator between catalog and table name?
00606 @return the separator string
00607 }
00608 function TZAdoDatabaseMetadata.GetCatalogSeparator: string;
00609 begin
00610 Result := '.';
00611 end;
00612
00613 {**
00614 Can a schema name be used in a data manipulation statement?
00615 @return <code>true</code> if so; <code>false</code> otherwise
00616 }
00617 function TZAdoDatabaseMetadata.SupportsSchemasInDataManipulation: Boolean;
00618 begin
00619 Result := True;
00620 end;
00621
00622 {**
00623 Can a schema name be used in a procedure call statement?
00624 @return <code>true</code> if so; <code>false</code> otherwise
00625 }
00626 function TZAdoDatabaseMetadata.SupportsSchemasInProcedureCalls: Boolean;
00627 begin
00628 Result := True;
00629 end;
00630
00631 {**
00632 Can a schema name be used in a table definition statement?
00633 @return <code>true</code> if so; <code>false</code> otherwise
00634 }
00635 function TZAdoDatabaseMetadata.SupportsSchemasInTableDefinitions: Boolean;
00636 begin
00637 Result := True;
00638 end;
00639
00640 {**
00641 Can a schema name be used in an index definition statement?
00642 @return <code>true</code> if so; <code>false</code> otherwise
00643 }
00644 function TZAdoDatabaseMetadata.SupportsSchemasInIndexDefinitions: Boolean;
00645 begin
00646 Result := True;
00647 end;
00648
00649 {**
00650 Can a schema name be used in a privilege definition statement?
00651 @return <code>true</code> if so; <code>false</code> otherwise
00652 }
00653 function TZAdoDatabaseMetadata.SupportsSchemasInPrivilegeDefinitions: Boolean;
00654 begin
00655 Result := True;
00656 end;
00657
00658 {**
00659 Can a catalog name be used in a data manipulation statement?
00660 @return <code>true</code> if so; <code>false</code> otherwise
00661 }
00662 function TZAdoDatabaseMetadata.SupportsCatalogsInDataManipulation: Boolean;
00663 begin
00664 Result := True;
00665 end;
00666
00667 {**
00668 Can a catalog name be used in a procedure call statement?
00669 @return <code>true</code> if so; <code>false</code> otherwise
00670 }
00671 function TZAdoDatabaseMetadata.SupportsCatalogsInProcedureCalls: Boolean;
00672 begin
00673 Result := True;
00674 end;
00675
00676 {**
00677 Can a catalog name be used in a table definition statement?
00678 @return <code>true</code> if so; <code>false</code> otherwise
00679 }
00680 function TZAdoDatabaseMetadata.SupportsCatalogsInTableDefinitions: Boolean;
00681 begin
00682 Result := True;
00683 end;
00684
00685 {**
00686 Can a catalog name be used in an index definition statement?
00687 @return <code>true</code> if so; <code>false</code> otherwise
00688 }
00689 function TZAdoDatabaseMetadata.SupportsCatalogsInIndexDefinitions: Boolean;
00690 begin
00691 Result := True;
00692 end;
00693
00694 {**
00695 Can a catalog name be used in a privilege definition statement?
00696 @return <code>true</code> if so; <code>false</code> otherwise
00697 }
00698 function TZAdoDatabaseMetadata.SupportsCatalogsInPrivilegeDefinitions: Boolean;
00699 begin
00700 Result := True;
00701 end;
00702
00703 {**
00704 Is positioned DELETE supported?
00705 @return <code>true</code> if so; <code>false</code> otherwise
00706 }
00707 function TZAdoDatabaseMetadata.SupportsPositionedDelete: Boolean;
00708 begin
00709 //CURRENT OF
00710 //Specifies that the DELETE is done at the current position of the specified cursor.
00711 Result := True;
00712 end;
00713
00714 {**
00715 Is positioned UPDATE supported?
00716 @return <code>true</code> if so; <code>false</code> otherwise
00717 }
00718 function TZAdoDatabaseMetadata.SupportsPositionedUpdate: Boolean;
00719 begin
00720 Result := True;
00721 end;
00722
00723 {**
00724 Is SELECT for UPDATE supported?
00725 @return <code>true</code> if so; <code>false</code> otherwise
00726 }
00727 function TZAdoDatabaseMetadata.SupportsSelectForUpdate: Boolean;
00728 begin
00729 Result := True;
00730 end;
00731
00732 {**
00733 Are stored procedure calls using the stored procedure escape
00734 syntax supported?
00735 @return <code>true</code> if so; <code>false</code> otherwise
00736 }
00737 function TZAdoDatabaseMetadata.SupportsStoredProcedures: Boolean;
00738 begin
00739 Result := True;
00740 end;
00741
00742 {**
00743 Are subqueries in comparison expressions supported?
00744 A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
00745 @return <code>true</code> if so; <code>false</code> otherwise
00746 }
00747 function TZAdoDatabaseMetadata.SupportsSubqueriesInComparisons: Boolean;
00748 begin
00749 Result := True;
00750 end;
00751
00752 {**
00753 Are subqueries in 'exists' expressions supported?
00754 A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
00755 @return <code>true</code> if so; <code>false</code> otherwise
00756 }
00757 function TZAdoDatabaseMetadata.SupportsSubqueriesInExists: Boolean;
00758 begin
00759 Result := True;
00760 end;
00761
00762 {**
00763 Are subqueries in 'in' statements supported?
00764 A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
00765 @return <code>true</code> if so; <code>false</code> otherwise
00766 }
00767 function TZAdoDatabaseMetadata.SupportsSubqueriesInIns: Boolean;
00768 begin
00769 Result := True;
00770 end;
00771
00772 {**
00773 Are subqueries in quantified expressions supported?
00774 A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
00775 @return <code>true</code> if so; <code>false</code> otherwise
00776 }
00777 function TZAdoDatabaseMetadata.SupportsSubqueriesInQuantifieds: Boolean;
00778 begin
00779 Result := True;
00780 end;
00781
00782 {**
00783 Are correlated subqueries supported?
00784 A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
00785 @return <code>true</code> if so; <code>false</code> otherwise
00786 }
00787 function TZAdoDatabaseMetadata.SupportsCorrelatedSubqueries: Boolean;
00788 begin
00789 Result := True;
00790 end;
00791
00792 {**
00793 Is SQL UNION supported?
00794 @return <code>true</code> if so; <code>false</code> otherwise
00795 }
00796 function TZAdoDatabaseMetadata.SupportsUnion: Boolean;
00797 begin
00798 Result := True;
00799 end;
00800
00801 {**
00802 Is SQL UNION ALL supported?
00803 @return <code>true</code> if so; <code>false</code> otherwise
00804 }
00805 function TZAdoDatabaseMetadata.SupportsUnionAll: Boolean;
00806 begin
00807 Result := True;
00808 end;
00809
00810 {**
00811 Can cursors remain open across commits?
00812 @return <code>true</code> if cursors always remain open;
00813 <code>false</code> if they might not remain open
00814 }
00815 function TZAdoDatabaseMetadata.SupportsOpenCursorsAcrossCommit: Boolean;
00816 begin
00817 Result := True;
00818 end;
00819
00820 {**
00821 Can cursors remain open across rollbacks?
00822 @return <code>true</code> if cursors always remain open;
00823 <code>false</code> if they might not remain open
00824 }
00825 function TZAdoDatabaseMetadata.SupportsOpenCursorsAcrossRollback: Boolean;
00826 begin
00827 Result := True;
00828 end;
00829
00830 {**
00831 Can statements remain open across commits?
00832 @return <code>true</code> if statements always remain open;
00833 <code>false</code> if they might not remain open
00834 }
00835 function TZAdoDatabaseMetadata.SupportsOpenStatementsAcrossCommit: Boolean;
00836 begin
00837 Result := False;
00838 end;
00839
00840 {**
00841 Can statements remain open across rollbacks?
00842 @return <code>true</code> if statements always remain open;
00843 <code>false</code> if they might not remain open
00844 }
00845 function TZAdoDatabaseMetadata.SupportsOpenStatementsAcrossRollback: Boolean;
00846 begin
00847 Result := False;
00848 end;
00849
00850 //----------------------------------------------------------------------
00851 // The following group of methods exposes various limitations
00852 // based on the target database with the current driver.
00853 // Unless otherwise specified, a result of zero means there is no
00854 // limit, or the limit is not known.
00855
00856 {**
00857 How many hex characters can you have in an inline binary literal?
00858 @return max binary literal length in hex characters;
00859 a result of zero means that there is no limit or the limit is not known
00860 }
00861 function TZAdoDatabaseMetadata.GetMaxBinaryLiteralLength: Integer;
00862 begin
00863 Result := 16000;
00864 end;
00865
00866 {**
00867 What's the max length for a character literal?
00868 @return max literal length;
00869 a result of zero means that there is no limit or the limit is not known
00870 }
00871 function TZAdoDatabaseMetadata.GetMaxCharLiteralLength: Integer;
00872 begin
00873 Result := 8000;
00874 end;
00875
00876 {**
00877 What's the limit on column name length?
00878 @return max column name length;
00879 a result of zero means that there is no limit or the limit is not known
00880 }
00881 function TZAdoDatabaseMetadata.GetMaxColumnNameLength: Integer;
00882 begin
00883 Result := 128;
00884 end;
00885
00886 {**
00887 What's the maximum number of columns in a "GROUP BY" clause?
00888 @return max number of columns;
00889 a result of zero means that there is no limit or the limit is not known
00890 }
00891 function TZAdoDatabaseMetadata.GetMaxColumnsInGroupBy: Integer;
00892 begin
00893 Result := 0;
00894 end;
00895
00896 {**
00897 What's the maximum number of columns allowed in an index?
00898 @return max number of columns;
00899 a result of zero means that there is no limit or the limit is not known
00900 }
00901 function TZAdoDatabaseMetadata.GetMaxColumnsInIndex: Integer;
00902 begin
00903 Result := 16;
00904 end;
00905
00906 {**
00907 What's the maximum number of columns in an "ORDER BY" clause?
00908 @return max number of columns;
00909 a result of zero means that there is no limit or the limit is not known
00910 }
00911 function TZAdoDatabaseMetadata.GetMaxColumnsInOrderBy: Integer;
00912 begin
00913 Result := 0;
00914 end;
00915
00916 {**
00917 What's the maximum number of columns in a "SELECT" list?
00918 @return max number of columns;
00919 a result of zero means that there is no limit or the limit is not known
00920 }
00921 function TZAdoDatabaseMetadata.GetMaxColumnsInSelect: Integer;
00922 begin
00923 Result := 4096;
00924 end;
00925
00926 {**
00927 What's the maximum number of columns in a table?
00928 @return max number of columns;
00929 a result of zero means that there is no limit or the limit is not known
00930 }
00931 function TZAdoDatabaseMetadata.GetMaxColumnsInTable: Integer;
00932 begin
00933 Result := 1024;
00934 end;
00935
00936 {**
00937 How many active connections can we have at a time to this database?
00938 @return max number of active connections;
00939 a result of zero means that there is no limit or the limit is not known
00940 }
00941 function TZAdoDatabaseMetadata.GetMaxConnections: Integer;
00942 begin
00943 Result := 0;
00944 end;
00945
00946 {**
00947 What's the maximum cursor name length?
00948 @return max cursor name length in bytes;
00949 a result of zero means that there is no limit or the limit is not known
00950 }
00951 function TZAdoDatabaseMetadata.GetMaxCursorNameLength: Integer;
00952 begin
00953 Result := 128;
00954 end;
00955
00956 {**
00957 Retrieves the maximum number of bytes for an index, including all
00958 of the parts of the index.
00959 @return max index length in bytes, which includes the composite of all
00960 the constituent parts of the index;
00961 a result of zero means that there is no limit or the limit is not known
00962 }
00963 function TZAdoDatabaseMetadata.GetMaxIndexLength: Integer;
00964 begin
00965 Result := 900;
00966 end;
00967
00968 {**
00969 What's the maximum length allowed for a schema name?
00970 @return max name length in bytes;
00971 a result of zero means that there is no limit or the limit is not known
00972 }
00973 function TZAdoDatabaseMetadata.GetMaxSchemaNameLength: Integer;
00974 begin
00975 Result := 128;
00976 end;
00977
00978 {**
00979 What's the maximum length of a procedure name?
00980 @return max name length in bytes;
00981 a result of zero means that there is no limit or the limit is not known
00982 }
00983 function TZAdoDatabaseMetadata.GetMaxProcedureNameLength: Integer;
00984 begin
00985 Result := 128;
00986 end;
00987
00988 {**
00989 What's the maximum length of a catalog name?
00990 @return max name length in bytes;
00991 a result of zero means that there is no limit or the limit is not known
00992 }
00993 function TZAdoDatabaseMetadata.GetMaxCatalogNameLength: Integer;
00994 begin
00995 Result := 128;
00996 end;
00997
00998 {**
00999 What's the maximum length of a single row?
01000 @return max row size in bytes;
01001 a result of zero means that there is no limit or the limit is not known
01002 }
01003 function TZAdoDatabaseMetadata.GetMaxRowSize: Integer;
01004 begin
01005 Result := 8060;
01006 end;
01007
01008 {**
01009 Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
01010 blobs?
01011 @return <code>true</code> if so; <code>false</code> otherwise
01012 }
01013 function TZAdoDatabaseMetadata.DoesMaxRowSizeIncludeBlobs: Boolean;
01014 begin
01015 Result := False;
01016 end;
01017
01018 {**
01019 What's the maximum length of an SQL statement?
01020 @return max length in bytes;
01021 a result of zero means that there is no limit or the limit is not known
01022 }
01023 function TZAdoDatabaseMetadata.GetMaxStatementLength: Integer;
01024 begin
01025 Result := 0;
01026 end;
01027
01028 {**
01029 How many active statements can we have open at one time to this
01030 database?
01031 @return the maximum number of statements that can be open at one time;
01032 a result of zero means that there is no limit or the limit is not known
01033 }
01034 function TZAdoDatabaseMetadata.GetMaxStatements: Integer;
01035 begin
01036 Result := 0;
01037 end;
01038
01039 {**
01040 What's the maximum length of a table name?
01041 @return max name length in bytes;
01042 a result of zero means that there is no limit or the limit is not known
01043 }
01044 function TZAdoDatabaseMetadata.GetMaxTableNameLength: Integer;
01045 begin
01046 Result := 128;
01047 end;
01048
01049 {**
01050 What's the maximum number of tables in a SELECT statement?
01051 @return the maximum number of tables allowed in a SELECT statement;
01052 a result of zero means that there is no limit or the limit is not known
01053 }
01054 function TZAdoDatabaseMetadata.GetMaxTablesInSelect: Integer;
01055 begin
01056 Result := 256;
01057 end;
01058
01059 {**
01060 What's the maximum length of a user name?
01061 @return max user name length in bytes;
01062 a result of zero means that there is no limit or the limit is not known
01063 }
01064 function TZAdoDatabaseMetadata.GetMaxUserNameLength: Integer;
01065 begin
01066 Result := 128;
01067 end;
01068
01069 //----------------------------------------------------------------------
01070
01071 {**
01072 What's the database's default transaction isolation level? The
01073 values are defined in <code>java.sql.Connection</code>.
01074 @return the default isolation level
01075 @see Connection
01076 }
01077 function TZAdoDatabaseMetadata.GetDefaultTransactionIsolation:
01078 TZTransactIsolationLevel;
01079 begin
01080 Result := tiReadCommitted;
01081 end;
01082
01083 {**
01084 Are transactions supported? If not, invoking the method
01085 <code>commit</code> is a noop and the isolation level is TRANSACTION_NONE.
01086 @return <code>true</code> if transactions are supported; <code>false</code> otherwise
01087 }
01088 function TZAdoDatabaseMetadata.SupportsTransactions: Boolean;
01089 begin
01090 Result := True;
01091 end;
01092
01093 {**
01094 Does this database support the given transaction isolation level?
01095 @param level the values are defined in <code>java.sql.Connection</code>
01096 @return <code>true</code> if so; <code>false</code> otherwise
01097 @see Connection
01098 }
01099 function TZAdoDatabaseMetadata.SupportsTransactionIsolationLevel(
01100 Level: TZTransactIsolationLevel): Boolean;
01101 begin
01102 Result := True;
01103 end;
01104
01105 {**
01106 Are both data definition and data manipulation statements
01107 within a transaction supported?
01108 @return <code>true</code> if so; <code>false</code> otherwise
01109 }
01110 function TZAdoDatabaseMetadata.
01111 SupportsDataDefinitionAndDataManipulationTransactions: Boolean;
01112 begin
01113 Result := True;
01114 end;
01115
01116 {**
01117 Are only data manipulation statements within a transaction
01118 supported?
01119 @return <code>true</code> if so; <code>false</code> otherwise
01120 }
01121 function TZAdoDatabaseMetadata.
01122 SupportsDataManipulationTransactionsOnly: Boolean;
01123 begin
01124 Result := False;
01125 end;
01126
01127 {**
01128 Does a data definition statement within a transaction force the
01129 transaction to commit?
01130 @return <code>true</code> if so; <code>false</code> otherwise
01131 }
01132 function TZAdoDatabaseMetadata.DataDefinitionCausesTransactionCommit: Boolean;
01133 begin
01134 Result := False;
01135 end;
01136
01137 {**
01138 Is a data definition statement within a transaction ignored?
01139 @return <code>true</code> if so; <code>false</code> otherwise
01140 }
01141 function TZAdoDatabaseMetadata.DataDefinitionIgnoredInTransactions: Boolean;
01142 begin
01143 Result := False;
01144 end;
01145
01146 {**
01147 Gets a description of the stored procedures available in a
01148 catalog.
01149
01150 <P>Only procedure descriptions matching the schema and
01151 procedure name criteria are returned. They are ordered by
01152 PROCEDURE_SCHEM, and PROCEDURE_NAME.
01153
01154 <P>Each procedure description has the the following columns:
01155 <OL>
01156 <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
01157 <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
01158 <LI><B>PROCEDURE_NAME</B> String => procedure name
01159 <LI> reserved for future use
01160 <LI> reserved for future use
01161 <LI> reserved for future use
01162 <LI><B>REMARKS</B> String => explanatory comment on the procedure
01163 <LI><B>PROCEDURE_TYPE</B> short => kind of procedure:
01164 <UL>
01165 <LI> procedureResultUnknown - May return a result
01166 <LI> procedureNoResult - Does not return a result
01167 <LI> procedureReturnsResult - Returns a result
01168 </UL>
01169 </OL>
01170
01171 @param catalog a catalog name; "" retrieves those without a
01172 catalog; null means drop catalog name from the selection criteria
01173 @param schemaPattern a schema name pattern; "" retrieves those
01174 without a schema
01175 @param procedureNamePattern a procedure name pattern
01176 @return <code>ResultSet</code> - each row is a procedure description
01177 @see #getSearchStringEscape
01178 }
01179 function TZAdoDatabaseMetadata.UncachedGetProcedures(const Catalog: string;
01180 const SchemaPattern: string; const ProcedureNamePattern: string): IZResultSet;
01181 var
01182 AdoRecordSet: ZPlainAdo.RecordSet;
01183 begin
01184 Result := ConstructVirtualResultSet(ProceduresColumnsDynArray);
01185
01186 AdoRecordSet := AdoOpenSchema(adSchemaProcedures,
01187 [Catalog, SchemaPattern, ProcedureNamePattern, '']);
01188 if Assigned(AdoRecordSet) then
01189 begin
01190 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
01191 begin
01192 while Next do
01193 begin
01194 Result.MoveToInsertRow;
01195 Result.UpdateStringByName('PROCEDURE_CAT',
01196 GetStringByName('PROCEDURE_CATALOG'));
01197 Result.UpdateStringByName('PROCEDURE_SCHEM',
01198 GetStringByName('PROCEDURE_SCHEMA'));
01199 Result.UpdateStringByName('PROCEDURE_NAME',
01200 GetStringByName('PROCEDURE_NAME'));
01201 Result.UpdateStringByName('REMARKS',
01202 GetStringByName('DESCRIPTION'));
01203 Result.UpdateShortByName('PROCEDURE_TYPE',
01204 GetShortByName('PROCEDURE_TYPE') - 1);
01205 Result.InsertRow;
01206 end;
01207 Close;
01208 Free;
01209 end;
01210 end;
01211 end;
01212
01213 {**
01214 Gets a description of a catalog's stored procedure parameters
01215 and result columns.
01216
01217 <P>Only descriptions matching the schema, procedure and
01218 parameter name criteria are returned. They are ordered by
01219 PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value,
01220 if any, is first. Next are the parameter descriptions in call
01221 order. The column descriptions follow in column number order.
01222
01223 <P>Each row in the <code>ResultSet</code> is a parameter description or
01224 column description with the following fields:
01225 <OL>
01226 <LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
01227 <LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
01228 <LI><B>PROCEDURE_NAME</B> String => procedure name
01229 <LI><B>COLUMN_NAME</B> String => column/parameter name
01230 <LI><B>COLUMN_TYPE</B> Short => kind of column/parameter:
01231 <UL>
01232 <LI> procedureColumnUnknown - nobody knows
01233 <LI> procedureColumnIn - IN parameter
01234 <LI> procedureColumnInOut - INOUT parameter
01235 <LI> procedureColumnOut - OUT parameter
01236 <LI> procedureColumnReturn - procedure return value
01237 <LI> procedureColumnResult - result column in <code>ResultSet</code>
01238 </UL>
01239 <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
01240 <LI><B>TYPE_NAME</B> String => SQL type name, for a UDT type the
01241 type name is fully qualified
01242 <LI><B>PRECISION</B> int => precision
01243 <LI><B>LENGTH</B> int => length in bytes of data
01244 <LI><B>SCALE</B> short => scale
01245 <LI><B>RADIX</B> short => radix
01246 <LI><B>NULLABLE</B> short => can it contain NULL?
01247 <UL>
01248 <LI> procedureNoNulls - does not allow NULL values
01249 <LI> procedureNullable - allows NULL values
01250 <LI> procedureNullableUnknown - nullability unknown
01251 </UL>
01252 <LI><B>REMARKS</B> String => comment describing parameter/column
01253 </OL>
01254
01255 <P><B>Note:</B> Some databases may not return the column
01256 descriptions for a procedure. Additional columns beyond
01257 REMARKS can be defined by the database.
01258
01259 @param catalog a catalog name; "" retrieves those without a
01260 catalog; null means drop catalog name from the selection criteria
01261 @param schemaPattern a schema name pattern; "" retrieves those
01262 without a schema
01263 @param procedureNamePattern a procedure name pattern
01264 @param columnNamePattern a column name pattern
01265 @return <code>ResultSet</code> - each row describes a stored procedure parameter or
01266 column
01267 @see #getSearchStringEscape
01268 }
01269 function TZAdoDatabaseMetadata.UncachedGetProcedureColumns(const Catalog: string;
01270 const SchemaPattern: string; const ProcedureNamePattern: string;
01271 const ColumnNamePattern: string): IZResultSet;
01272 var
01273 AdoRecordSet: ZPlainAdo.RecordSet;
01274 begin
01275 Result := ConstructVirtualResultSet(ProceduresColColumnsDynArray);
01276
01277 AdoRecordSet := AdoOpenSchema(adSchemaProcedureParameters,
01278 [Catalog, SchemaPattern, ProcedureNamePattern]);
01279 if Assigned(AdoRecordSet) then
01280 begin
01281 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
01282 begin
01283 while Next do
01284 begin
01285 Result.MoveToInsertRow;
01286 Result.UpdateStringByName('PROCEDURE_CAT',
01287 GetStringByName('PROCEDURE_CATALOG'));
01288 Result.UpdateStringByName('PROCEDURE_SCHEM',
01289 GetStringByName('PROCEDURE_SCHEMA'));
01290 Result.UpdateStringByName('PROCEDURE_NAME',
01291 GetStringByName('PROCEDURE_NAME'));
01292 Result.UpdateStringByName('COLUMN_NAME',
01293 GetStringByName('PARAMETER_NAME'));
01294 case GetShortByName('PARAMETER_TYPE') of
01295 1: Result.UpdateShortByName('COLUMN_TYPE', 1);
01296 2: Result.UpdateShortByName('COLUMN_TYPE', 3);
01297 3: Result.UpdateShortByName('COLUMN_TYPE', 2);
01298 4: Result.UpdateShortByName('COLUMN_TYPE', 4);
01299 else
01300 Result.UpdateShortByName('COLUMN_TYPE', 0);
01301 end;
01302 Result.UpdateShortByName('DATA_TYPE',
01303 Ord(ConvertAdoToSqlType(GetShortByName('DATA_TYPE'))));
01304 Result.UpdateStringByName('TYPE_NAME',
01305 GetStringByName('TYPE_NAME'));
01306 Result.UpdateIntByName('PRECISION',
01307 GetIntByName('NUMERIC_PRECISION'));
01308 Result.UpdateIntByName('LENGTH',
01309 GetIntByName('CHARACTER_OCTET_LENGTH'));
01310 Result.UpdateShortByName('SCALE',
01311 GetShortByName('NUMERIC_SCALE'));
01312
01313 Result.UpdateShortByName('NULLABLE', 2);
01314 if GetStringByName('IS_NULLABLE') = 'NO' then
01315 Result.UpdateShortByName('NULLABLE', 0);
01316 if GetStringByName('IS_NULLABLE') = 'YES' then
01317 Result.UpdateShortByName('NULLABLE', 1);
01318 Result.UpdateStringByName('REMARKS',
01319 GetStringByName('DESCRIPTION'));
01320 Result.InsertRow;
01321 end;
01322 Close;
01323 Free;
01324 end;
01325 end;
01326 end;
01327
01328 {**
01329 Gets a description of tables available in a catalog.
01330
01331 <P>Only table descriptions matching the catalog, schema, table
01332 name and type criteria are returned. They are ordered by
01333 TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
01334
01335 <P>Each table description has the following columns:
01336 <OL>
01337 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
01338 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
01339 <LI><B>TABLE_NAME</B> String => table name
01340 <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
01341 "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
01342 "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
01343 <LI><B>REMARKS</B> String => explanatory comment on the table
01344 </OL>
01345
01346 <P><B>Note:</B> Some databases may not return information for
01347 all tables.
01348
01349 @param catalog a catalog name; "" retrieves those without a
01350 catalog; null means drop catalog name from the selection criteria
01351 @param schemaPattern a schema name pattern; "" retrieves those
01352 without a schema
01353 @param tableNamePattern a table name pattern
01354 @param types a list of table types to include; null returns all types
01355 @return <code>ResultSet</code> - each row is a table description
01356 @see #getSearchStringEscape
01357 }
01358 function TZAdoDatabaseMetadata.UncachedGetTables(const Catalog: string;
01359 const SchemaPattern: string; const TableNamePattern: string;
01360 const Types: TStringDynArray): IZResultSet;
01361 var
01362 I: Integer;
01363 TableTypes: string;
01364 AdoRecordSet: ZPlainAdo.RecordSet;
01365 begin
01366 Result := ConstructVirtualResultSet(TableColumnsDynArray);
01367
01368 for I := Low(Types) to High(Types) do
01369 begin
01370 if Length(TableTypes) > 0 then
01371 TableTypes := TableTypes + ',';
01372 TableTypes := TableTypes + Types[I];
01373 end;
01374
01375 AdoRecordSet := AdoOpenSchema(adSchemaTables,
01376 [Catalog, SchemaPattern, TableNamePattern, TableTypes]);
01377 if Assigned(AdoRecordSet) then
01378 begin
01379 with TZAdoResultSet.Create(GetStatement, '', AdoRecordset) do
01380 begin
01381 while Next do
01382 begin
01383 Result.MoveToInsertRow;
01384 Result.UpdateStringByName('TABLE_CAT',
01385 GetStringByName('TABLE_CATALOG'));
01386 Result.UpdateStringByName('TABLE_SCHEM',
01387 GetStringByName('TABLE_SCHEMA'));
01388 Result.UpdateStringByName('TABLE_NAME',
01389 GetStringByName('TABLE_NAME'));
01390 Result.UpdateStringByName('TABLE_TYPE',
01391 GetStringByName('TABLE_TYPE'));
01392 Result.UpdateStringByName('REMARKS',
01393 GetStringByName('DESCRIPTION'));
01394 Result.InsertRow;
01395 end;
01396 Close;
01397 Free;
01398 end;
01399 end;
01400 end;
01401
01402 {**
01403 Gets the schema names available in this database. The results
01404 are ordered by schema name.
01405
01406 <P>The schema column is:
01407 <OL>
01408 <LI><B>TABLE_SCHEM</B> String => schema name
01409 </OL>
01410
01411 @return <code>ResultSet</code> - each row has a single String column that is a
01412 schema name
01413 }
01414 function TZAdoDatabaseMetadata.UncachedGetSchemas: IZResultSet;
01415 var
01416 AdoRecordSet: ZPlainAdo.RecordSet;
01417 begin
01418 Result := ConstructVirtualResultSet(SchemaColumnsDynArray);
01419
01420 AdoRecordSet := AdoOpenSchema(adSchemaSchemata, []);
01421 if Assigned(AdoRecordSet) then
01422 begin
01423 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
01424 begin
01425 while Next do
01426 begin
01427 Result.MoveToInsertRow;
01428 Result.UpdateStringByName('TABLE_SCHEM',
01429 GetStringByName('SCHEMA_NAME'));
01430 Result.InsertRow;
01431 end;
01432 Close;
01433 Free;
01434 end;
01435 end;
01436 end;
01437
01438 {**
01439 Gets the catalog names available in this database. The results
01440 are ordered by catalog name.
01441
01442 <P>The catalog column is:
01443 <OL>
01444 <LI><B>TABLE_CAT</B> String => catalog name
01445 </OL>
01446
01447 @return <code>ResultSet</code> - each row has a single String column that is a
01448 catalog name
01449 }
01450 function TZAdoDatabaseMetadata.UncachedGetCatalogs: IZResultSet;
01451 var
01452 AdoRecordSet: ZPlainAdo.RecordSet;
01453 begin
01454 Result := ConstructVirtualResultSet(CatalogColumnsDynArray);
01455
01456 AdoRecordSet := AdoOpenSchema(adSchemaCatalogs, []);
01457 if Assigned(AdoRecordSet) then
01458 begin
01459 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
01460 begin
01461 while Next do
01462 begin
01463 Result.MoveToInsertRow;
01464 Result.UpdateStringByName('TABLE_CAT',
01465 GetStringByName('CATALOG_NAME'));
01466 Result.InsertRow;
01467 end;
01468 Close;
01469 Free;
01470 end;
01471 end;
01472 end;
01473
01474 {**
01475 Gets the table types available in this database. The results
01476 are ordered by table type.
01477
01478 <P>The table type is:
01479 <OL>
01480 <LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
01481 "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
01482 "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
01483 </OL>
01484
01485 @return <code>ResultSet</code> - each row has a single String column that is a
01486 table type
01487 }
01488 function TZAdoDatabaseMetadata.UncachedGetTableTypes: IZResultSet;
01489 const
01490 TableTypes: array[0..7] of string = (
01491 'ALIAS', 'TABLE', 'SYNONYM', 'SYSTEM TABLE', 'VIEW',
01492 'GLOBAL TEMPORARY', 'LOCAL TEMPORARY', 'SYSTEM VIEW'
01493 );
01494 var
01495 I: Integer;
01496 begin
01497 Result := ConstructVirtualResultSet(TableTypeColumnsDynArray);
01498 for I := 0 to 7 do
01499 begin
01500 Result.MoveToInsertRow;
01501 Result.UpdateStringByName('TABLE_TYPE', TableTypes[I]);
01502 Result.InsertRow;
01503 end;
01504 end;
01505
01506 {**
01507 Gets a description of table columns available in
01508 the specified catalog.
01509
01510 <P>Only column descriptions matching the catalog, schema, table
01511 and column name criteria are returned. They are ordered by
01512 TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
01513
01514 <P>Each column description has the following columns:
01515 <OL>
01516 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
01517 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
01518 <LI><B>TABLE_NAME</B> String => table name
01519 <LI><B>COLUMN_NAME</B> String => column name
01520 <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
01521 <LI><B>TYPE_NAME</B> String => Data source dependent type name,
01522 for a UDT the type name is fully qualified
01523 <LI><B>COLUMN_SIZE</B> int => column size. For char or date
01524 types this is the maximum number of characters, for numeric or
01525 decimal types this is precision.
01526 <LI><B>BUFFER_LENGTH</B> is not used.
01527 <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
01528 <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
01529 <LI><B>NULLABLE</B> int => is NULL allowed?
01530 <UL>
01531 <LI> columnNoNulls - might not allow NULL values
01532 <LI> columnNullable - definitely allows NULL values
01533 <LI> columnNullableUnknown - nullability unknown
01534 </UL>
01535 <LI><B>REMARKS</B> String => comment describing column (may be null)
01536 <LI><B>COLUMN_DEF</B> String => default value (may be null)
01537 <LI><B>SQL_DATA_TYPE</B> int => unused
01538 <LI><B>SQL_DATETIME_SUB</B> int => unused
01539 <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
01540 maximum number of bytes in the column
01541 <LI><B>ORDINAL_POSITION</B> int => index of column in table
01542 (starting at 1)
01543 <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
01544 does not allow NULL values; "YES" means the column might
01545 allow NULL values. An empty string means nobody knows.
01546 </OL>
01547
01548 @param catalog a catalog name; "" retrieves those without a
01549 catalog; null means drop catalog name from the selection criteria
01550 @param schemaPattern a schema name pattern; "" retrieves those
01551 without a schema
01552 @param tableNamePattern a table name pattern
01553 @param columnNamePattern a column name pattern
01554 @return <code>ResultSet</code> - each row is a column description
01555 @see #getSearchStringEscape
01556 }
01557 function TZAdoDatabaseMetadata.UncachedGetColumns(const Catalog: string;
01558 const SchemaPattern: string; const TableNamePattern: string;
01559 const ColumnNamePattern: string): IZResultSet;
01560 var
01561 AdoRecordSet: ZPlainAdo.RecordSet;
01562 Flags: Integer;
01563 begin
01564 Result := ConstructVirtualResultSet(TableColColumnsDynArray);
01565
01566 AdoRecordSet := AdoOpenSchema(adSchemaColumns,
01567 [Catalog, SchemaPattern, TableNamePattern, ColumnNamePattern]);
01568 if Assigned(AdoRecordSet) then
01569 begin
01570 AdoRecordSet.Sort := 'ORDINAL_POSITION';
01571 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
01572 begin
01573 while Next do
01574 begin
01575 Result.MoveToInsertRow;
01576 Result.UpdateStringByName('TABLE_CAT',
01577 GetStringByName('TABLE_CATALOG'));
01578 Result.UpdateStringByName('TABLE_SCHEM',
01579 GetStringByName('TABLE_SCHEMA'));
01580 Result.UpdateStringByName('TABLE_NAME',
01581 GetStringByName('TABLE_NAME'));
01582 Result.UpdateStringByName('COLUMN_NAME',
01583 GetStringByName('COLUMN_NAME'));
01584
01585
01586
01587 Flags := GetIntByName('COLUMN_FLAGS');
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597 Result.UpdateIntByName('COLUMN_SIZE',
01598 GetIntByName('CHARACTER_MAXIMUM_LENGTH'));
01599 Result.UpdateIntByName('BUFFER_LENGTH',
01600 GetIntByName('CHARACTER_MAXIMUM_LENGTH'));
01601 Result.UpdateIntByName('DECIMAL_DIGITS',
01602 GetIntByName('NUMERIC_SCALE'));
01603 Result.UpdateIntByName('NUM_PREC_RADIX',
01604 GetShortByName('NUMERIC_PRECISION'));
01605 if GetBooleanByName('IS_NULLABLE') then
01606 Result.UpdateShortByName('NULLABLE', 1)
01607 else
01608 Result.UpdateShortByName('NULLABLE', 0);
01609 Result.UpdateStringByName('REMARKS',
01610 GetStringByName('DESCRIPTION'));
01611 Result.UpdateStringByName('COLUMN_DEF',
01612 GetStringByName('COLUMN_DEFAULT'));
01613 Result.UpdateShortByName('SQL_DATETIME_SUB',
01614 GetShortByName('DATETIME_PRECISION'));
01615 Result.UpdateIntByName('CHAR_OCTET_LENGTH',
01616 GetIntByName('CHARACTER_OCTET_LENGTH'));
01617 Result.UpdateIntByName('ORDINAL_POSITION',
01618 GetIntByName('ORDINAL_POSITION'));
01619 Result.UpdateStringByName('IS_NULLABLE',
01620 GetStringByName('IS_NULLABLE'));
01621
01622 Result.UpdateBooleanByName('WRITABLE',
01623 (Flags and (DBCOLUMNFLAGS_WRITE or DBCOLUMNFLAGS_WRITEUNKNOWN) <> 0));
01624
01625 Result.UpdateBooleanByName('DEFINITELYWRITABLE',
01626 (Flags and (DBCOLUMNFLAGS_WRITE) <> 0));
01627 Result.UpdateBooleanByName('READONLY',
01628 (Flags and (DBCOLUMNFLAGS_WRITE or DBCOLUMNFLAGS_WRITEUNKNOWN) = 0));
01629 Result.UpdateBooleanByName('SEARCHABLE',
01630 (Flags and (DBCOLUMNFLAGS_ISLONG) = 0));
01631
01632 Result.InsertRow;
01633 end;
01634 Close;
01635 Free;
01636 end;
01637 end;
01638 end;
01639
01640 {**
01641 Gets a description of the access rights for a table's columns.
01642
01643 <P>Only privileges matching the column name criteria are
01644 returned. They are ordered by COLUMN_NAME and PRIVILEGE.
01645
01646 <P>Each privilige description has the following columns:
01647 <OL>
01648 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
01649 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
01650 <LI><B>TABLE_NAME</B> String => table name
01651 <LI><B>COLUMN_NAME</B> String => column name
01652 <LI><B>GRANTOR</B> => grantor of access (may be null)
01653 <LI><B>GRANTEE</B> String => grantee of access
01654 <LI><B>PRIVILEGE</B> String => name of access (SELECT,
01655 INSERT, UPDATE, REFRENCES, ...)
01656 <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
01657 to grant to others; "NO" if not; null if unknown
01658 </OL>
01659
01660 @param catalog a catalog name; "" retrieves those without a
01661 catalog; null means drop catalog name from the selection criteria
01662 @param schema a schema name; "" retrieves those without a schema
01663 @param table a table name
01664 @param columnNamePattern a column name pattern
01665 @return <code>ResultSet</code> - each row is a column privilege description
01666 @see #getSearchStringEscape
01667 }
01668 function TZAdoDatabaseMetadata.UncachedGetColumnPrivileges(const Catalog: string;
01669 const Schema: string; const Table: string; const ColumnNamePattern: string): IZResultSet;
01670 var
01671 AdoRecordSet: ZPlainAdo.RecordSet;
01672 begin
01673 Result := ConstructVirtualResultSet(TableColPrivColumnsDynArray);
01674
01675 AdoRecordSet := AdoOpenSchema(adSchemaColumnPrivileges,
01676 [Catalog, Schema, Table, ColumnNamePattern]);
01677 if Assigned(AdoRecordSet) then
01678 begin
01679 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
01680 begin
01681 while Next do
01682 begin
01683 Result.MoveToInsertRow;
01684 Result.UpdateStringByName('TABLE_CAT',
01685 GetStringByName('TABLE_CATALOG'));
01686 Result.UpdateStringByName('TABLE_SCHEM',
01687 GetStringByName('TABLE_SCHEMA'));
01688 Result.UpdateStringByName('TABLE_NAME',
01689 GetStringByName('TABLE_NAME'));
01690 Result.UpdateStringByName('COLUMN_NAME',
01691 GetStringByName('COLUMN_NAME'));
01692 Result.UpdateStringByName('GRANTOR',
01693 GetStringByName('GRANTOR'));
01694 Result.UpdateStringByName('GRANTEE',
01695 GetStringByName('GRANTEE'));
01696 Result.UpdateStringByName('PRIVILEGE',
01697 GetStringByName('PRIVILEGE_TYPE'));
01698 if GetBooleanByName('IS_GRANTABLE') then
01699 Result.UpdateStringByName('IS_GRANTABLE', 'YES')
01700 else
01701 Result.UpdateStringByName('IS_GRANTABLE', 'NO');
01702 Result.InsertRow;
01703 end;
01704 Close;
01705 Free;
01706 end;
01707 end;
01708 end;
01709
01710 {**
01711 Gets a description of the access rights for each table available
01712 in a catalog. Note that a table privilege applies to one or
01713 more columns in the table. It would be wrong to assume that
01714 this priviledge applies to all columns (this may be true for
01715 some systems but is not true for all.)
01716
01717 <P>Only privileges matching the schema and table name
01718 criteria are returned. They are ordered by TABLE_SCHEM,
01719 TABLE_NAME, and PRIVILEGE.
01720
01721 <P>Each privilige description has the following columns:
01722 <OL>
01723 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
01724 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
01725 <LI><B>TABLE_NAME</B> String => table name
01726 <LI><B>GRANTOR</B> => grantor of access (may be null)
01727 <LI><B>GRANTEE</B> String => grantee of access
01728 <LI><B>PRIVILEGE</B> String => name of access (SELECT,
01729 INSERT, UPDATE, REFRENCES, ...)
01730 <LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
01731 to grant to others; "NO" if not; null if unknown
01732 </OL>
01733
01734 @param catalog a catalog name; "" retrieves those without a
01735 catalog; null means drop catalog name from the selection criteria
01736 @param schemaPattern a schema name pattern; "" retrieves those
01737 without a schema
01738 @param tableNamePattern a table name pattern
01739 @return <code>ResultSet</code> - each row is a table privilege description
01740 @see #getSearchStringEscape
01741 }
01742 function TZAdoDatabaseMetadata.UncachedGetTablePrivileges(const Catalog: string;
01743 const SchemaPattern: string; const TableNamePattern: string): IZResultSet;
01744 var
01745 AdoRecordSet: ZPlainAdo.RecordSet;
01746 begin
01747 Result := ConstructVirtualResultSet(TablePrivColumnsDynArray);
01748
01749 AdoRecordSet := AdoOpenSchema(adSchemaTablePrivileges,
01750 [Catalog, SchemaPattern, TableNamePattern]);
01751 if Assigned(AdoRecordSet) then
01752 begin
01753 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
01754 begin
01755 while Next do
01756 begin
01757 Result.MoveToInsertRow;
01758 Result.UpdateStringByName('TABLE_CAT',
01759 GetStringByName('TABLE_CATALOG'));
01760 Result.UpdateStringByName('TABLE_SCHEM',
01761 GetStringByName('TABLE_SCHEMA'));
01762 Result.UpdateStringByName('TABLE_NAME',
01763 GetStringByName('TABLE_NAME'));
01764 Result.UpdateStringByName('GRANTOR',
01765 GetStringByName('GRANTOR'));
01766 Result.UpdateStringByName('GRANTEE',
01767 GetStringByName('GRANTEE'));
01768 Result.UpdateStringByName('PRIVILEGE',
01769 GetStringByName('PRIVILEGE_TYPE'));
01770 if GetBooleanByName('IS_GRANTABLE') then
01771 Result.UpdateStringByName('IS_GRANTABLE', 'YES')
01772 else Result.UpdateStringByName('IS_GRANTABLE', 'NO');
01773 Result.InsertRow;
01774 end;
01775 Close;
01776 Free;
01777 end;
01778 end;
01779 end;
01780
01781 {**
01782 Gets a description of a table's columns that are automatically
01783 updated when any value in a row is updated. They are
01784 unordered.
01785
01786 <P>Each column description has the following columns:
01787 <OL>
01788 <LI><B>SCOPE</B> short => is not used
01789 <LI><B>COLUMN_NAME</B> String => column name
01790 <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
01791 <LI><B>TYPE_NAME</B> String => Data source dependent type name
01792 <LI><B>COLUMN_SIZE</B> int => precision
01793 <LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
01794 <LI><B>DECIMAL_DIGITS</B> short => scale
01795 <LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
01796 like an Oracle ROWID
01797 <UL>
01798 <LI> versionColumnUnknown - may or may not be pseudo column
01799 <LI> versionColumnNotPseudo - is NOT a pseudo column
01800 <LI> versionColumnPseudo - is a pseudo column
01801 </UL>
01802 </OL>
01803
01804 @param catalog a catalog name; "" retrieves those without a
01805 catalog; null means drop catalog name from the selection criteria
01806 @param schema a schema name; "" retrieves those without a schema
01807 @param table a table name
01808 @return <code>ResultSet</code> - each row is a column description
01809 @exception SQLException if a database access error occurs
01810 }
01811 function TZAdoDatabaseMetadata.UncachedGetVersionColumns(const Catalog: string;
01812 const Schema: string; const Table: string): IZResultSet;
01813 const
01814 DBCOLUMNFLAGS_ISROWVER = $00000200;
01815 var
01816 AdoRecordSet: ZPlainAdo.RecordSet;
01817 begin
01818 Result := ConstructVirtualResultSet(TableColVerColumnsDynArray);
01819
01820 AdoRecordSet := AdoOpenSchema(adSchemaColumns, [Catalog, Schema, Table]);
01821 if Assigned(AdoRecordSet) then
01822 begin
01823 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
01824 begin
01825 while Next do
01826 begin
01827 if (GetIntByName('COLUMN_FLAGS')
01828 and DBCOLUMNFLAGS_ISROWVER) = 0 then
01829 Continue;
01830 Result.MoveToInsertRow;
01831 Result.UpdateShortByName('SCOPE', 0);
01832 Result.UpdateStringByName('COLUMN_NAME',
01833 GetStringByName('COLUMN_NAME'));
01834 Result.UpdateShortByName('DATA_TYPE',
01835 Ord(ConvertAdoToSqlType(GetShortByName('DATA_TYPE'))));
01836 Result.UpdateStringByName('TYPE_NAME',
01837 GetStringByName('TYPE_NAME'));
01838 Result.UpdateIntByName('COLUMN_SIZE',
01839 GetIntByName('CHARACTER_OCTET_LENGTH'));
01840 Result.UpdateIntByName('BUFFER_LENGTH',
01841 GetIntByName('CHARACTER_OCTET_LENGTH'));
01842 Result.UpdateIntByName('DECIMAL_DIGITS',
01843 GetIntByName('NUMERIC_SCALE'));
01844 Result.UpdateShortByName('PSEUDO_COLUMN', 0);
01845 Result.InsertRow;
01846 end;
01847 Close;
01848 Free;
01849 end;
01850 end;
01851 end;
01852
01853 {**
01854 Gets a description of a table's primary key columns. They
01855 are ordered by COLUMN_NAME.
01856
01857 <P>Each primary key column description has the following columns:
01858 <OL>
01859 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
01860 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
01861 <LI><B>TABLE_NAME</B> String => table name
01862 <LI><B>COLUMN_NAME</B> String => column name
01863 <LI><B>KEY_SEQ</B> short => sequence number within primary key
01864 <LI><B>PK_NAME</B> String => primary key name (may be null)
01865 </OL>
01866
01867 @param catalog a catalog name; "" retrieves those without a
01868 catalog; null means drop catalog name from the selection criteria
01869 @param schema a schema name; "" retrieves those
01870 without a schema
01871 @param table a table name
01872 @return <code>ResultSet</code> - each row is a primary key column description
01873 @exception SQLException if a database access error occurs
01874 }
01875 function TZAdoDatabaseMetadata.UncachedGetPrimaryKeys(const Catalog: string;
01876 const Schema: string; const Table: string): IZResultSet;
01877 var
01878 AdoRecordSet: ZPlainAdo.RecordSet;
01879 begin
01880 Result := ConstructVirtualResultSet(PrimaryKeyColumnsDynArray);
01881
01882 AdoRecordSet := AdoOpenSchema(adSchemaPrimaryKeys,
01883 [Catalog, Schema, Table]);
01884 if Assigned(AdoRecordSet) then
01885 begin
01886 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
01887 begin
01888 while Next do
01889 begin
01890 Result.MoveToInsertRow;
01891 Result.UpdateStringByName('TABLE_CAT',
01892 GetStringByName('TABLE_CATALOG'));
01893 Result.UpdateStringByName('TABLE_SCHEM',
01894 GetStringByName('TABLE_SCHEMA'));
01895 Result.UpdateStringByName('TABLE_NAME',
01896 GetStringByName('TABLE_NAME'));
01897 Result.UpdateStringByName('COLUMN_NAME',
01898 GetStringByName('COLUMN_NAME'));
01899 Result.UpdateShortByName('KEY_SEQ',
01900 GetShortByName('ORDINAL'));
01901 if FindColumn('PK_NAME') >= 1 then
01902 begin
01903 Result.UpdateStringByName('PK_NAME',
01904 GetStringByName('PK_NAME'));
01905 end;
01906 Result.InsertRow;
01907 end;
01908 Close;
01909 Free;
01910 end;
01911 end;
01912 end;
01913
01914 {**
01915 Gets a description of the primary key columns that are
01916 referenced by a table's foreign key columns (the primary keys
01917 imported by a table). They are ordered by PKTABLE_CAT,
01918 PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
01919
01920 <P>Each primary key column description has the following columns:
01921 <OL>
01922 <LI><B>PKTABLE_CAT</B> String => primary key table catalog
01923 being imported (may be null)
01924 <LI><B>PKTABLE_SCHEM</B> String => primary key table schema
01925 being imported (may be null)
01926 <LI><B>PKTABLE_NAME</B> String => primary key table name
01927 being imported
01928 <LI><B>PKCOLUMN_NAME</B> String => primary key column name
01929 being imported
01930 <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
01931 <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
01932 <LI><B>FKTABLE_NAME</B> String => foreign key table name
01933 <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
01934 <LI><B>KEY_SEQ</B> short => sequence number within foreign key
01935 <LI><B>UPDATE_RULE</B> short => What happens to
01936 foreign key when primary is updated:
01937 <UL>
01938 <LI> importedNoAction - do not allow update of primary
01939 key if it has been imported
01940 <LI> importedKeyCascade - change imported key to agree
01941 with primary key update
01942 <LI> importedKeySetNull - change imported key to NULL if
01943 its primary key has been updated
01944 <LI> importedKeySetDefault - change imported key to default values
01945 if its primary key has been updated
01946 <LI> importedKeyRestrict - same as importedKeyNoAction
01947 (for ODBC 2.x compatibility)
01948 </UL>
01949 <LI><B>DELETE_RULE</B> short => What happens to
01950 the foreign key when primary is deleted.
01951 <UL>
01952 <LI> importedKeyNoAction - do not allow delete of primary
01953 key if it has been imported
01954 <LI> importedKeyCascade - delete rows that import a deleted key
01955 <LI> importedKeySetNull - change imported key to NULL if
01956 its primary key has been deleted
01957 <LI> importedKeyRestrict - same as importedKeyNoAction
01958 (for ODBC 2.x compatibility)
01959 <LI> importedKeySetDefault - change imported key to default if
01960 its primary key has been deleted
01961 </UL>
01962 <LI><B>FK_NAME</B> String => foreign key name (may be null)
01963 <LI><B>PK_NAME</B> String => primary key name (may be null)
01964 <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
01965 constraints be deferred until commit
01966 <UL>
01967 <LI> importedKeyInitiallyDeferred - see SQL92 for definition
01968 <LI> importedKeyInitiallyImmediate - see SQL92 for definition
01969 <LI> importedKeyNotDeferrable - see SQL92 for definition
01970 </UL>
01971 </OL>
01972
01973 @param catalog a catalog name; "" retrieves those without a
01974 catalog; null means drop catalog name from the selection criteria
01975 @param schema a schema name; "" retrieves those
01976 without a schema
01977 @param table a table name
01978 @return <code>ResultSet</code> - each row is a primary key column description
01979 @see #getExportedKeys
01980 }
01981 function TZAdoDatabaseMetadata.UncachedGetImportedKeys(const Catalog: string;
01982 const Schema: string; const Table: string): IZResultSet;
01983 begin
01984 Result := UncachedGetCrossReference('', '', '', Catalog, Schema, Table);
01985 end;
01986
01987 {**
01988 Gets a description of the foreign key columns that reference a
01989 table's primary key columns (the foreign keys exported by a
01990 table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
01991 FKTABLE_NAME, and KEY_SEQ.
01992
01993 <P>Each foreign key column description has the following columns:
01994 <OL>
01995 <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
01996 <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
01997 <LI><B>PKTABLE_NAME</B> String => primary key table name
01998 <LI><B>PKCOLUMN_NAME</B> String => primary key column name
01999 <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
02000 being exported (may be null)
02001 <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
02002 being exported (may be null)
02003 <LI><B>FKTABLE_NAME</B> String => foreign key table name
02004 being exported
02005 <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
02006 being exported
02007 <LI><B>KEY_SEQ</B> short => sequence number within foreign key
02008 <LI><B>UPDATE_RULE</B> short => What happens to
02009 foreign key when primary is updated:
02010 <UL>
02011 <LI> importedNoAction - do not allow update of primary
02012 key if it has been imported
02013 <LI> importedKeyCascade - change imported key to agree
02014 with primary key update
02015 <LI> importedKeySetNull - change imported key to NULL if
02016 its primary key has been updated
02017 <LI> importedKeySetDefault - change imported key to default values
02018 if its primary key has been updated
02019 <LI> importedKeyRestrict - same as importedKeyNoAction
02020 (for ODBC 2.x compatibility)
02021 </UL>
02022 <LI><B>DELETE_RULE</B> short => What happens to
02023 the foreign key when primary is deleted.
02024 <UL>
02025 <LI> importedKeyNoAction - do not allow delete of primary
02026 key if it has been imported
02027 <LI> importedKeyCascade - delete rows that import a deleted key
02028 <LI> importedKeySetNull - change imported key to NULL if
02029 its primary key has been deleted
02030 <LI> importedKeyRestrict - same as importedKeyNoAction
02031 (for ODBC 2.x compatibility)
02032 <LI> importedKeySetDefault - change imported key to default if
02033 its primary key has been deleted
02034 </UL>
02035 <LI><B>FK_NAME</B> String => foreign key name (may be null)
02036 <LI><B>PK_NAME</B> String => primary key name (may be null)
02037 <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
02038 constraints be deferred until commit
02039 <UL>
02040 <LI> importedKeyInitiallyDeferred - see SQL92 for definition
02041 <LI> importedKeyInitiallyImmediate - see SQL92 for definition
02042 <LI> importedKeyNotDeferrable - see SQL92 for definition
02043 </UL>
02044 </OL>
02045
02046 @param catalog a catalog name; "" retrieves those without a
02047 catalog; null means drop catalog name from the selection criteria
02048 @param schema a schema name; "" retrieves those
02049 without a schema
02050 @param table a table name
02051 @return <code>ResultSet</code> - each row is a foreign key column description
02052 @see #getImportedKeys
02053 }
02054 function TZAdoDatabaseMetadata.UncachedGetExportedKeys(const Catalog: string;
02055 const Schema: string; const Table: string): IZResultSet;
02056 begin
02057 Result := UncachedGetCrossReference(Catalog, Schema, Table, '', '', '');
02058 end;
02059
02060 {**
02061 Gets a description of the foreign key columns in the foreign key
02062 table that reference the primary key columns of the primary key
02063 table (describe how one table imports another's key.) This
02064 should normally return a single foreign key/primary key pair
02065 (most tables only import a foreign key from a table once.) They
02066 are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
02067 KEY_SEQ.
02068
02069 <P>Each foreign key column description has the following columns:
02070 <OL>
02071 <LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
02072 <LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
02073 <LI><B>PKTABLE_NAME</B> String => primary key table name
02074 <LI><B>PKCOLUMN_NAME</B> String => primary key column name
02075 <LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
02076 being exported (may be null)
02077 <LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
02078 being exported (may be null)
02079 <LI><B>FKTABLE_NAME</B> String => foreign key table name
02080 being exported
02081 <LI><B>FKCOLUMN_NAME</B> String => foreign key column name
02082 being exported
02083 <LI><B>KEY_SEQ</B> short => sequence number within foreign key
02084 <LI><B>UPDATE_RULE</B> short => What happens to
02085 foreign key when primary is updated:
02086 <UL>
02087 <LI> importedNoAction - do not allow update of primary
02088 key if it has been imported
02089 <LI> importedKeyCascade - change imported key to agree
02090 with primary key update
02091 <LI> importedKeySetNull - change imported key to NULL if
02092 its primary key has been updated
02093 <LI> importedKeySetDefault - change imported key to default values
02094 if its primary key has been updated
02095 <LI> importedKeyRestrict - same as importedKeyNoAction
02096 (for ODBC 2.x compatibility)
02097 </UL>
02098 <LI><B>DELETE_RULE</B> short => What happens to
02099 the foreign key when primary is deleted.
02100 <UL>
02101 <LI> importedKeyNoAction - do not allow delete of primary
02102 key if it has been imported
02103 <LI> importedKeyCascade - delete rows that import a deleted key
02104 <LI> importedKeySetNull - change imported key to NULL if
02105 its primary key has been deleted
02106 <LI> importedKeyRestrict - same as importedKeyNoAction
02107 (for ODBC 2.x compatibility)
02108 <LI> importedKeySetDefault - change imported key to default if
02109 its primary key has been deleted
02110 </UL>
02111 <LI><B>FK_NAME</B> String => foreign key name (may be null)
02112 <LI><B>PK_NAME</B> String => primary key name (may be null)
02113 <LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
02114 constraints be deferred until commit
02115 <UL>
02116 <LI> importedKeyInitiallyDeferred - see SQL92 for definition
02117 <LI> importedKeyInitiallyImmediate - see SQL92 for definition
02118 <LI> importedKeyNotDeferrable - see SQL92 for definition
02119 </UL>
02120 </OL>
02121
02122 @param primaryCatalog a catalog name; "" retrieves those without a
02123 catalog; null means drop catalog name from the selection criteria
02124 @param primarySchema a schema name; "" retrieves those
02125 without a schema
02126 @param primaryTable the table name that exports the key
02127 @param foreignCatalog a catalog name; "" retrieves those without a
02128 catalog; null means drop catalog name from the selection criteria
02129 @param foreignSchema a schema name; "" retrieves those
02130 without a schema
02131 @param foreignTable the table name that imports the key
02132 @return <code>ResultSet</code> - each row is a foreign key column description
02133 @see #getImportedKeys
02134 }
02135 function TZAdoDatabaseMetadata.UncachedGetCrossReference(const PrimaryCatalog: string;
02136 const PrimarySchema: string; const PrimaryTable: string; const ForeignCatalog: string;
02137 const ForeignSchema: string; const ForeignTable: string): IZResultSet;
02138 var
02139 AdoRecordSet: ZPlainAdo.RecordSet;
02140 begin
02141 Result := ConstructVirtualResultSet(CrossRefColumnsDynArray);
02142
02143 AdoRecordSet := AdoOpenSchema(adSchemaForeignKeys,
02144 [PrimaryCatalog, PrimarySchema, PrimaryTable,
02145 ForeignCatalog, ForeignSchema, ForeignTable]);
02146 if Assigned(AdoRecordSet) then
02147 begin
02148 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
02149 begin
02150 while Next do
02151 begin
02152 Result.MoveToInsertRow;
02153 Result.UpdateStringByName('PKTABLE_CAT',
02154 GetStringByName('PK_TABLE_CATALOG'));
02155 Result.UpdateStringByName('PKTABLE_SCHEM',
02156 GetStringByName('PK_TABLE_SCHEMA'));
02157 Result.UpdateStringByName('PKTABLE_NAME',
02158 GetStringByName('PK_TABLE_NAME'));
02159 Result.UpdateStringByName('PKCOLUMN_NAME',
02160 GetStringByName('PK_COLUMN_NAME'));
02161 Result.UpdateStringByName('FKTABLE_CAT',
02162 GetStringByName('FK_TABLE_CATALOG'));
02163 Result.UpdateStringByName('FKTABLE_SCHEM',
02164 GetStringByName('FK_TABLE_SCHEMA'));
02165 Result.UpdateStringByName('FKTABLE_NAME',
02166 GetStringByName('FK_TABLE_NAME'));
02167 Result.UpdateStringByName('FKCOLUMN_NAME',
02168 GetStringByName('FK_COLUMN_NAME'));
02169 Result.UpdateShortByName('KEY_SEQ',
02170 GetShortByName('ORDINAL'));
02171
02172
02173
02174
02175 Result.UpdateStringByName('FK_NAME',
02176 GetStringByName('FK_NAME'));
02177 Result.UpdateStringByName('PK_NAME',
02178 GetStringByName('PK_NAME'));
02179 Result.UpdateIntByName('DEFERRABILITY',
02180 GetShortByName('DEFERRABILITY'));
02181 Result.InsertRow;
02182 end;
02183 Close;
02184 Free;
02185 end;
02186 end;
02187 end;
02188
02189 {**
02190 Gets a description of all the standard SQL types supported by
02191 this database. They are ordered by DATA_TYPE and then by how
02192 closely the data type maps to the corresponding JDBC SQL type.
02193
02194 <P>Each type description has the following columns:
02195 <OL>
02196 <LI><B>TYPE_NAME</B> String => Type name
02197 <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
02198 <LI><B>PRECISION</B> int => maximum precision
02199 <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
02200 (may be null)
02201 <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
02202 (may be null)
02203 <LI><B>CREATE_PARAMS</B> String => parameters used in creating
02204 the type (may be null)
02205 <LI><B>NULLABLE</B> short => can you use NULL for this type?
02206 <UL>
02207 <LI> typeNoNulls - does not allow NULL values
02208 <LI> typeNullable - allows NULL values
02209 <LI> typeNullableUnknown - nullability unknown
02210 </UL>
02211 <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
02212 <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
02213 <UL>
02214 <LI> typePredNone - No support
02215 <LI> typePredChar - Only supported with WHERE .. LIKE
02216 <LI> typePredBasic - Supported except for WHERE .. LIKE
02217 <LI> typeSearchable - Supported for all WHERE ..
02218 </UL>
02219 <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
02220 <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
02221 <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
02222 auto-increment value?
02223 <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
02224 (may be null)
02225 <LI><B>MINIMUM_SCALE</B> short => minimum scale supported
02226 <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
02227 <LI><B>SQL_DATA_TYPE</B> int => unused
02228 <LI><B>SQL_DATETIME_SUB</B> int => unused
02229 <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
02230 </OL>
02231
02232 @return <code>ResultSet</code> - each row is an SQL type description
02233 }
02234 function TZAdoDatabaseMetadata.UncachedGetTypeInfo: IZResultSet;
02235 var
02236 AdoRecordSet: ZPlainAdo.RecordSet;
02237 begin
02238 Result := ConstructVirtualResultSet(TypeInfoColumnsDynArray);
02239
02240 AdoRecordSet := AdoOpenSchema(adSchemaProviderTypes, []);
02241 if Assigned(AdoRecordSet) then
02242 begin
02243 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
02244 begin
02245 while Next do
02246 begin
02247 Result.MoveToInsertRow;
02248 Result.UpdateStringByName('TYPE_NAME',
02249 GetStringByName('TYPE_NAME'));
02250 Result.UpdateShortByName('DATA_TYPE',
02251 Ord(ConvertAdoToSqlType(GetShortByName('DATA_TYPE'))));
02252 Result.UpdateIntByName('PRECISION',
02253 0);
02254 Result.UpdateStringByName('LITERAL_PREFIX',
02255 GetStringByName('LITERAL_PREFIX'));
02256 Result.UpdateStringByName('LITERAL_SUFFIX',
02257 GetStringByName('LITERAL_SUFFIX'));
02258 Result.UpdateStringByName('CREATE_PARAMS',
02259 GetStringByName('CREATE_PARAMS'));
02260 if GetBooleanByName('IS_NULLABLE') then
02261 Result.UpdateShortByName('NULLABLE', 1)
02262 else
02263 Result.UpdateShortByName('NULLABLE', 0);
02264 Result.UpdateBooleanByName('CASE_SENSITIVE',
02265 GetBooleanByName('CASE_SENSITIVE'));
02266 Result.UpdateShortByName('SEARCHABLE',
02267 GetShortByName('SEARCHABLE'));
02268 Result.UpdateBooleanByName('UNSIGNED_ATTRIBUTE',
02269 GetBooleanByName('UNSIGNED_ATTRIBUTE'));
02270 Result.UpdateBooleanByName('FIXED_PREC_SCALE',
02271 GetBooleanByName('FIXED_PREC_SCALE'));
02272 Result.UpdateBooleanByName('AUTO_INCREMENT', False);
02273 Result.UpdateStringByName('LOCAL_TYPE_NAME',
02274 GetStringByName('LOCAL_TYPE_NAME'));
02275 Result.UpdateShortByName('MINIMUM_SCALE',
02276 GetShortByName('MINIMUM_SCALE'));
02277 Result.UpdateShortByName('MAXIMUM_SCALE',
02278 GetShortByName('MAXIMUM_SCALE'));
02279
02280
02281
02282
02283
02284
02285 Result.InsertRow;
02286 end;
02287 Close;
02288 Free;
02289 end;
02290 end;
02291 end;
02292
02293 {**
02294 Gets a description of a table's indices and statistics. They are
02295 ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
02296
02297 <P>Each index column description has the following columns:
02298 <OL>
02299 <LI><B>TABLE_CAT</B> String => table catalog (may be null)
02300 <LI><B>TABLE_SCHEM</B> String => table schema (may be null)
02301 <LI><B>TABLE_NAME</B> String => table name
02302 <LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
02303 false when TYPE is tableIndexStatistic
02304 <LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
02305 null when TYPE is tableIndexStatistic
02306 <LI><B>INDEX_NAME</B> String => index name; null when TYPE is
02307 tableIndexStatistic
02308 <LI><B>TYPE</B> short => index type:
02309 <UL>
02310 <LI> tableIndexStatistic - this identifies table statistics that are
02311 returned in conjuction with a table's index descriptions
02312 <LI> tableIndexClustered - this is a clustered index
02313 <LI> tableIndexHashed - this is a hashed index
02314 <LI> tableIndexOther - this is some other style of index
02315 </UL>
02316 <LI><B>ORDINAL_POSITION</B> short => column sequence number
02317 within index; zero when TYPE is tableIndexStatistic
02318 <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
02319 tableIndexStatistic
02320 <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
02321 "D" => descending, may be null if sort sequence is not supported;
02322 null when TYPE is tableIndexStatistic
02323 <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatistic, then
02324 this is the number of rows in the table; otherwise, it is the
02325 number of unique values in the index.
02326 <LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
02327 this is the number of pages used for the table, otherwise it
02328 is the number of pages used for the current index.
02329 <LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
02330 (may be null)
02331 </OL>
02332
02333 @param catalog a catalog name; "" retrieves those without a
02334 catalog; null means drop catalog name from the selection criteria
02335 @param schema a schema name; "" retrieves those without a schema
02336 @param table a table name
02337 @param unique when true, return only indices for unique values;
02338 when false, return indices regardless of whether unique or not
02339 @param approximate when true, result is allowed to reflect approximate
02340 or out of data values; when false, results are requested to be
02341 accurate
02342 @return <code>ResultSet</code> - each row is an index column description
02343 }
02344 function TZAdoDatabaseMetadata.UncachedGetIndexInfo(const Catalog: string;
02345 const Schema: string; const Table: string; Unique: Boolean;
02346 Approximate: Boolean): IZResultSet;
02347 var
02348 AdoRecordSet: ZPlainAdo.RecordSet;
02349 begin
02350 Result := ConstructVirtualResultSet(IndexInfoColumnsDynArray);
02351
02352 AdoRecordSet := AdoOpenSchema(adSchemaIndexes,
02353 [Catalog, Schema, '', '', Table]);
02354 if Assigned(AdoRecordSet) then
02355 begin
02356 with TZAdoResultSet.Create(GetStatement, '', AdoRecordSet) do
02357 begin
02358 while Next do
02359 begin
02360 Result.MoveToInsertRow;
02361 Result.UpdateStringByName('TABLE_CAT',
02362 GetStringByName('TABLE_CATALOG'));
02363 Result.UpdateStringByName('TABLE_SCHEM',
02364 GetStringByName('TABLE_SCHEMA'));
02365 Result.UpdateStringByName('TABLE_NAME',
02366 GetStringByName('TABLE_NAME'));
02367 Result.UpdateBooleanByName('NON_UNIQUE',
02368 not GetBooleanByName('UNIQUE'));
02369 Result.UpdateStringByName('INDEX_QUALIFIER',
02370 GetStringByName('INDEX_CATALOG'));
02371 Result.UpdateStringByName('INDEX_NAME',
02372 GetStringByName('INDEX_NAME'));
02373 Result.UpdateShortByName('TYPE',
02374 GetShortByName('TYPE'));
02375 Result.UpdateShortByName('ORDINAL_POSITION',
02376 GetShortByName('ORDINAL_POSITION'));
02377 Result.UpdateStringByName('COLUMN_NAME',
02378 GetStringByName('COLUMN_NAME'));
02379
02380
02381 Result.UpdateIntByName('CARDINALITY',
02382 GetIntByName('CARDINALITY'));
02383 Result.UpdateIntByName('PAGES',
02384 GetIntByName('PAGES'));
02385 Result.UpdateStringByName('FILTER_CONDITION',
02386 GetStringByName('FILTER_CONDITION'));
02387 Result.InsertRow;
02388 end;
02389 Close;
02390 Free;
02391 end;
02392 end;
02393 end;
02394
02395 {**
02396 Does the database support the given result set type?
02397 @param type defined in <code>java.sql.ResultSet</code>
02398 @return <code>true</code> if so; <code>false</code> otherwise
02399 }
02400 function TZAdoDatabaseMetadata.SupportsResultSetType(
02401 _Type: TZResultSetType): Boolean;
02402 begin
02403 Result := True;
02404 end;
02405
02406 {**
02407 Does the database support the concurrency type in combination
02408 with the given result set type?
02409
02410 @param type defined in <code>java.sql.ResultSet</code>
02411 @param concurrency type defined in <code>java.sql.ResultSet</code>
02412 @return <code>true</code> if so; <code>false</code> otherwise
02413 }
02414 function TZAdoDatabaseMetadata.SupportsResultSetConcurrency(
02415 _Type: TZResultSetType; Concurrency: TZResultSetConcurrency): Boolean;
02416 begin
02417 Result := True;
02418 end;
02419
02420 {**
02421
02422 Gets a description of the user-defined types defined in a particular
02423 schema. Schema-specific UDTs may have type JAVA_OBJECT, STRUCT,
02424 or DISTINCT.
02425
02426 <P>Only types matching the catalog, schema, type name and type
02427 criteria are returned. They are ordered by DATA_TYPE, TYPE_SCHEM
02428 and TYPE_NAME. The type name parameter may be a fully-qualified
02429 name. In this case, the catalog and schemaPattern parameters are
02430 ignored.
02431
02432 <P>Each type description has the following columns:
02433 <OL>
02434 <LI><B>TYPE_CAT</B> String => the type's catalog (may be null)
02435 <LI><B>TYPE_SCHEM</B> String => type's schema (may be null)
02436 <LI><B>TYPE_NAME</B> String => type name
02437 <LI><B>CLASS_NAME</B> String => Java class name
02438 <LI><B>DATA_TYPE</B> String => type value defined in java.sql.Types.
02439 One of JAVA_OBJECT, STRUCT, or DISTINCT
02440 <LI><B>REMARKS</B> String => explanatory comment on the type
02441 </OL>
02442
02443 <P><B>Note:</B> If the driver does not support UDTs, an empty
02444 result set is returned.
02445
02446 @param catalog a catalog name; "" retrieves those without a
02447 catalog; null means drop catalog name from the selection criteria
02448 @param schemaPattern a schema name pattern; "" retrieves those
02449 without a schema
02450 @param typeNamePattern a type name pattern; may be a fully-qualified name
02451 @param types a list of user-named types to include (JAVA_OBJECT,
02452 STRUCT, or DISTINCT); null returns all types
02453 @return <code>ResultSet</code> - each row is a type description
02454 }
02455 function TZAdoDatabaseMetadata.UncachedGetUDTs(const Catalog: string; const SchemaPattern: string;
02456 const TypeNamePattern: string; const Types: TIntegerDynArray): IZResultSet;
02457 begin
02458 Result := ConstructVirtualResultSet(UDTColumnsDynArray);
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480 end;
02481
02482 {**
02483 Create a statement for use
02484 @return TZAdoStatement
02485 }
02486 function TZAdoDatabaseMetadata.GetStatement: IZSTatement;
02487 begin
02488 Result := GetConnection.CreateStatement;
02489 end;
02490
02491 {**
02492 Open a schema rowset from ado
02493
02494 @Schema Ado identifier
02495 @Args Variant array with restrictions
02496 @return ADO recordset with the schemas; nil if the schema is not supported
02497 }
02498 function TZAdoDatabaseMetadata.AdoOpenSchema(Schema: Integer; const Args: array of const): ZPlainAdo.RecordSet;
02499 var
02500 Restrictions: Variant;
02501 begin
02502 Result := nil;
02503 if not FSupportedSchemasInitialized then
02504 InitializeSchemas;
02505 if not SchemaSupported(Schema) then
02506 Exit;
02507 try
02508 Restrictions := BuildRestrictions(Schema, Args);
02509 Result := (GetConnection as IZAdoConnection).GetAdoConnection.
02510 OpenSchema(Schema, Restrictions, EmptyParam);
02511 except
02512 Result := nil;
02513 end;
02514 end;
02515
02516 {**
02517 Initialize supported schemas and restrictions from the OleDB provider
02518 }
02519 procedure TZAdoDatabaseMetadata.InitializeSchemas;
02520 var
02521 AdoConnection: IZAdoConnection;
02522 OleDBSession: IUnknown;
02523 SchemaRS: IDBSchemaRowset;
02524 PG, OriginalPG: PGUID;
02525 IA: PIntegerArray;
02526 Nr: Integer;
02527 I: Integer;
02528 begin
02529 if not FSupportedSchemasInitialized then
02530 begin
02531 if not Assigned(FAdoConnection) then
02532 begin
02533 GetConnection.QueryInterface(IZAdoConnection, AdoConnection);
02534 FAdoConnection := AdoConnection.GetAdoConnection;
02535 end;
02536 (FAdoConnection as ADOConnectionConstruction).Get_Session(OleDBSession);
02537 OleDBSession.QueryInterface(IDBSchemaRowset, SchemaRS);
02538 if Assigned(SchemaRS) then
02539 begin
02540 SchemaRS.GetSchemas(Nr, PG, PInteger(IA));
02541 OriginalPG := PG;
02542 SetLength(SupportedSchemas, Nr);
02543 for I := 0 to Nr - 1 do
02544 begin
02545 SupportedSchemas[I].SchemaGuid := PG^;
02546 SupportedSchemas[I].SupportedRestrictions := IA^[I];
02547 SupportedSchemas[I].AdoSchemaId := ConvertOleDBToAdoSchema(PG^);
02548 Inc(Integer(PG), SizeOf(TGuid));
02549 end;
02550 FSupportedSchemasInitialized := True;
02551 if Assigned(OriginalPG) then ZAdoMalloc.Free(OriginalPG);
02552 if Assigned(IA) then ZAdoMalloc.Free(IA);
02553 end;
02554 end;
02555 end;
02556
02557 {**
02558 Find the Schema Id in the supported schemas
02559
02560 @SchemaId Ado identifier
02561 @return Index of the schema in the supported schemas array
02562 }
02563 function TZAdoDatabaseMetadata.FindSchema(SchemaId: Integer): Integer;
02564 var
02565 I: Integer;
02566 begin
02567 Result := -1;
02568 for I := 0 to Length(SupportedSchemas) - 1 do
02569 if SupportedSchemas[I].AdoSchemaId = SchemaId then
02570 begin
02571 Result := I;
02572 Break;
02573 end;
02574 end;
02575
02576 {**
02577 Is the schema supported by the OleDB provider?
02578
02579 @SchemaId Ado identifier
02580 @return True if the schema is supported
02581 }
02582 function TZAdoDatabaseMetadata.SchemaSupported(SchemaId: Integer): Boolean;
02583 begin
02584 Result := FindSchema(SchemaId) > -1;
02585 end;
02586
02587 {**
02588 Build a variant array from the provided parameters based on the supported restrictions
02589
02590 @SchemaId Ado identifier
02591 @Args Restrictions
02592 @return Variant array of restrictions
02593 }
02594 function TZAdoDatabaseMetadata.BuildRestrictions(SchemaId: Integer;
02595 const Args: array of const): Variant;
02596 var
02597 SchemaIndex: Integer;
02598 I: Integer;
02599 begin
02600 Result := Null;
02601 if High(Args) = -1 then
02602 Exit;
02603 SchemaIndex := FindSchema(SchemaId);
02604 if SchemaIndex = -1 then
02605 Exit;
02606
02607 Result := VarArrayCreate([0, High(Args)], varVariant);
02608 for I := 0 to High(Args) do
02609 begin
02610 if (SupportedSchemas[SchemaIndex].SupportedRestrictions
02611 and (1 shl I)) <> 0 then
02612 begin
02613 Result[I] := string(Args[I].VAnsiString);
02614 if (Args[I].VType = vtAnsiString) then
02615 if string(Args[I].VAnsiString) = '' then
02616 Result[I] := UnAssigned;
02617 end else
02618 Result[I] := UnAssigned;
02619 end;
02620 end;
02621
02622 end.
02623
02624