mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2026-03-13 09:24:25 +08:00
2706 lines
98 KiB
ObjectPascal
2706 lines
98 KiB
ObjectPascal
{*********************************************************}
|
|
{ }
|
|
{ Zeos Database Objects }
|
|
{ Sybase Database metadata information }
|
|
{ }
|
|
{ Originally written by Janos Fegyverneki }
|
|
{ }
|
|
{*********************************************************}
|
|
|
|
{@********************************************************}
|
|
{ Copyright (c) 1999-2006 Zeos Development Group }
|
|
{ }
|
|
{ License Agreement: }
|
|
{ }
|
|
{ This library is distributed in the hope that it will be }
|
|
{ useful, but WITHOUT ANY WARRANTY; without even the }
|
|
{ implied warranty of MERCHANTABILITY or FITNESS FOR }
|
|
{ A PARTICULAR PURPOSE. See the GNU Lesser General }
|
|
{ Public License for more details. }
|
|
{ }
|
|
{ The source code of the ZEOS Libraries and packages are }
|
|
{ distributed under the Library GNU General Public }
|
|
{ License (see the file COPYING / COPYING.ZEOS) }
|
|
{ with the following modification: }
|
|
{ As a special exception, the copyright holders of this }
|
|
{ library give you permission to link this library with }
|
|
{ independent modules to produce an executable, }
|
|
{ regardless of the license terms of these independent }
|
|
{ modules, and to copy and distribute the resulting }
|
|
{ executable under terms of your choice, provided that }
|
|
{ you also meet, for each linked independent module, }
|
|
{ the terms and conditions of the license of that module. }
|
|
{ An independent module is a module which is not derived }
|
|
{ from or based on this library. If you modify this }
|
|
{ library, you may extend this exception to your version }
|
|
{ of the library, but you are not obligated to do so. }
|
|
{ If you do not wish to do so, delete this exception }
|
|
{ statement from your version. }
|
|
{ }
|
|
{ }
|
|
{ The project web site is located on: }
|
|
{ http://zeos.firmos.at (FORUM) }
|
|
{ http://zeosbugs.firmos.at (BUGTRACKER) }
|
|
{ svn://zeos.firmos.at/zeos/trunk (SVN Repository) }
|
|
{ }
|
|
{ http://www.sourceforge.net/projects/zeoslib. }
|
|
{ http://www.zeoslib.sourceforge.net }
|
|
{ }
|
|
{ }
|
|
{ }
|
|
{ Zeos Development Group. }
|
|
{********************************************************@}
|
|
|
|
unit ZDbcDbLibSybaseMetadata;
|
|
|
|
interface
|
|
|
|
{$I ZDbc.inc}
|
|
|
|
uses
|
|
{$IFNDEF VER130BELOW}
|
|
Types,
|
|
{$ENDIF}
|
|
Classes, SysUtils, ZSysUtils, ZClasses, ZDbcIntfs, ZDbcMetadata,
|
|
ZDbcResultSet, ZTokenizer, ZDbcCachedResultSet, ZDbcResultsetMetadata,
|
|
ZCompatibility, ZGenericSqlAnalyser, ZDbcConnection;
|
|
|
|
type
|
|
|
|
{** Implements Sybase Database Metadata. }
|
|
TZSybaseDatabaseMetadata = class(TZAbstractDatabaseMetadata)
|
|
protected
|
|
function GetStatement: IZStatement;
|
|
public
|
|
constructor Create(Connection: TZAbstractConnection; Url: string;
|
|
Info: TStrings);
|
|
destructor Destroy; override;
|
|
|
|
function GetDatabaseProductName: string; override;
|
|
function GetDatabaseProductVersion: string; override;
|
|
function GetDriverName: string; override;
|
|
function GetDriverMajorVersion: Integer; override;
|
|
function GetDriverMinorVersion: Integer; override;
|
|
function UsesLocalFilePerTable: Boolean; override;
|
|
function SupportsMixedCaseIdentifiers: Boolean; override;
|
|
function StoresUpperCaseIdentifiers: Boolean; override;
|
|
function StoresLowerCaseIdentifiers: Boolean; override;
|
|
function StoresMixedCaseIdentifiers: Boolean; override;
|
|
function SupportsMixedCaseQuotedIdentifiers: Boolean; override;
|
|
function StoresUpperCaseQuotedIdentifiers: Boolean; override;
|
|
function StoresLowerCaseQuotedIdentifiers: Boolean; override;
|
|
function StoresMixedCaseQuotedIdentifiers: Boolean; override;
|
|
function GetIdentifierQuoteString: string; override;
|
|
function GetSQLKeywords: string; override;
|
|
function GetNumericFunctions: string; override;
|
|
function GetStringFunctions: string; override;
|
|
function GetSystemFunctions: string; override;
|
|
function GetTimeDateFunctions: string; override;
|
|
function GetSearchStringEscape: string; override;
|
|
function GetExtraNameCharacters: string; override;
|
|
|
|
function SupportsExpressionsInOrderBy: Boolean; override;
|
|
function SupportsOrderByUnrelated: Boolean; override;
|
|
function SupportsGroupBy: Boolean; override;
|
|
function SupportsGroupByUnrelated: Boolean; override;
|
|
function SupportsGroupByBeyondSelect: Boolean; override;
|
|
function SupportsIntegrityEnhancementFacility: Boolean; override;
|
|
function GetSchemaTerm: string; override;
|
|
function GetProcedureTerm: string; override;
|
|
function GetCatalogTerm: string; override;
|
|
function GetCatalogSeparator: string; override;
|
|
function SupportsSchemasInDataManipulation: Boolean; override;
|
|
function SupportsSchemasInProcedureCalls: Boolean; override;
|
|
function SupportsSchemasInTableDefinitions: Boolean; override;
|
|
function SupportsSchemasInIndexDefinitions: Boolean; override;
|
|
function SupportsSchemasInPrivilegeDefinitions: Boolean; override;
|
|
function SupportsCatalogsInDataManipulation: Boolean; override;
|
|
function SupportsCatalogsInProcedureCalls: Boolean; override;
|
|
function SupportsCatalogsInTableDefinitions: Boolean; override;
|
|
function SupportsCatalogsInIndexDefinitions: Boolean; override;
|
|
function SupportsCatalogsInPrivilegeDefinitions: Boolean; override;
|
|
function SupportsPositionedDelete: Boolean; override;
|
|
function SupportsPositionedUpdate: Boolean; override;
|
|
function SupportsSelectForUpdate: Boolean; override;
|
|
function SupportsStoredProcedures: Boolean; override;
|
|
function SupportsSubqueriesInComparisons: Boolean; override;
|
|
function SupportsSubqueriesInExists: Boolean; override;
|
|
function SupportsSubqueriesInIns: Boolean; override;
|
|
function SupportsSubqueriesInQuantifieds: Boolean; override;
|
|
function SupportsCorrelatedSubqueries: Boolean; override;
|
|
function SupportsUnion: Boolean; override;
|
|
function SupportsUnionAll: Boolean; override;
|
|
function SupportsOpenCursorsAcrossCommit: Boolean; override;
|
|
function SupportsOpenCursorsAcrossRollback: Boolean; override;
|
|
function SupportsOpenStatementsAcrossCommit: Boolean; override;
|
|
function SupportsOpenStatementsAcrossRollback: Boolean; override;
|
|
|
|
function GetMaxBinaryLiteralLength: Integer; override;
|
|
function GetMaxCharLiteralLength: Integer; override;
|
|
function GetMaxColumnNameLength: Integer; override;
|
|
function GetMaxColumnsInGroupBy: Integer; override;
|
|
function GetMaxColumnsInIndex: Integer; override;
|
|
function GetMaxColumnsInOrderBy: Integer; override;
|
|
function GetMaxColumnsInSelect: Integer; override;
|
|
function GetMaxColumnsInTable: Integer; override;
|
|
function GetMaxConnections: Integer; override;
|
|
function GetMaxCursorNameLength: Integer; override;
|
|
function GetMaxIndexLength: Integer; override;
|
|
function GetMaxSchemaNameLength: Integer; override;
|
|
function GetMaxProcedureNameLength: Integer; override;
|
|
function GetMaxCatalogNameLength: Integer; override;
|
|
function GetMaxRowSize: Integer; override;
|
|
function DoesMaxRowSizeIncludeBlobs: Boolean; override;
|
|
function GetMaxStatementLength: Integer; override;
|
|
function GetMaxStatements: Integer; override;
|
|
function GetMaxTableNameLength: Integer; override;
|
|
function GetMaxTablesInSelect: Integer; override;
|
|
function GetMaxUserNameLength: Integer; override;
|
|
|
|
function GetDefaultTransactionIsolation: TZTransactIsolationLevel; override;
|
|
function SupportsTransactions: Boolean; override;
|
|
function SupportsTransactionIsolationLevel(Level: TZTransactIsolationLevel):
|
|
Boolean; override;
|
|
function SupportsDataDefinitionAndDataManipulationTransactions: Boolean; override;
|
|
function SupportsDataManipulationTransactionsOnly: Boolean; override;
|
|
function DataDefinitionCausesTransactionCommit: Boolean; override;
|
|
function DataDefinitionIgnoredInTransactions: Boolean; override;
|
|
|
|
function GetProcedures(const Catalog: string; const SchemaPattern: string;
|
|
const ProcedureNamePattern: string): IZResultSet; override;
|
|
function GetProcedureColumns(const Catalog: string; const SchemaPattern: string;
|
|
const ProcedureNamePattern: string; const ColumnNamePattern: string):
|
|
IZResultSet; override;
|
|
|
|
function GetTables(const Catalog: string; const SchemaPattern: string;
|
|
const TableNamePattern: string; const Types: TStringDynArray): IZResultSet; override;
|
|
function GetSchemas: IZResultSet; override;
|
|
function GetCatalogs: IZResultSet; override;
|
|
function GetTableTypes: IZResultSet; override;
|
|
function GetColumns(const Catalog: string; const SchemaPattern: string;
|
|
const TableNamePattern: string; const ColumnNamePattern: string): IZResultSet; override;
|
|
function GetColumnPrivileges(const Catalog: string; const Schema: string;
|
|
const Table: string; const ColumnNamePattern: string): IZResultSet; override;
|
|
|
|
function GetTablePrivileges(const Catalog: string; const SchemaPattern: string;
|
|
const TableNamePattern: string): IZResultSet; override;
|
|
function GetVersionColumns(const Catalog: string; const Schema: string;
|
|
const Table: string): IZResultSet; override;
|
|
|
|
function GetPrimaryKeys(const Catalog: string; const Schema: string;
|
|
const Table: string): IZResultSet; override;
|
|
function GetImportedKeys(const Catalog: string; const Schema: string;
|
|
const Table: string): IZResultSet; override;
|
|
function GetExportedKeys(const Catalog: string; const Schema: string;
|
|
const Table: string): IZResultSet; override;
|
|
function GetCrossReference(const PrimaryCatalog: string; const PrimarySchema: string;
|
|
const PrimaryTable: string; const ForeignCatalog: string; const ForeignSchema: string;
|
|
const ForeignTable: string): IZResultSet; override;
|
|
|
|
function GetTypeInfo: IZResultSet; override;
|
|
|
|
function GetIndexInfo(const Catalog: string; const Schema: string; const Table: string;
|
|
Unique: Boolean; Approximate: Boolean): IZResultSet; override;
|
|
|
|
function SupportsResultSetType(_Type: TZResultSetType): Boolean; override;
|
|
function SupportsResultSetConcurrency(_Type: TZResultSetType;
|
|
Concurrency: TZResultSetConcurrency): Boolean; override;
|
|
|
|
function GetUDTs(const Catalog: string; const SchemaPattern: string;
|
|
const TypeNamePattern: string; const Types: TIntegerDynArray): IZResultSet; override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses Math, ZDbcUtils, ZCollections, ZSybaseToken, ZSybaseAnalyser,
|
|
ZDbcDbLibUtils;
|
|
|
|
{ TZSybaseDatabaseMetadata }
|
|
|
|
{**
|
|
Constructs this object and assignes the main properties.
|
|
@param Connection a database connection object.
|
|
@param Url a database connection url string.
|
|
@param Info an extra connection properties.
|
|
}
|
|
constructor TZSybaseDatabaseMetadata.Create(Connection: TZAbstractConnection;
|
|
Url: string; Info: TStrings);
|
|
begin
|
|
inherited Create(Connection, Url, Info);
|
|
end;
|
|
|
|
{**
|
|
Destroys this object and cleanups the memory.
|
|
}
|
|
destructor TZSybaseDatabaseMetadata.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
//----------------------------------------------------------------------
|
|
// First, a variety of minor information about the target database.
|
|
|
|
{**
|
|
What's the name of this database product?
|
|
@return database product name
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetDatabaseProductName: string;
|
|
begin
|
|
Result := 'Sybase';
|
|
end;
|
|
|
|
{**
|
|
What's the version of this database product?
|
|
@return database version
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetDatabaseProductVersion: string;
|
|
begin
|
|
Result := '12+';
|
|
end;
|
|
|
|
{**
|
|
What's the name of this JDBC driver?
|
|
@return JDBC driver name
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetDriverName: string;
|
|
begin
|
|
Result := 'Zeos Database Connectivity Driver for Sybase ASE Server';
|
|
end;
|
|
|
|
{**
|
|
What's this JDBC driver's major version number?
|
|
@return JDBC driver major version
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetDriverMajorVersion: Integer;
|
|
begin
|
|
Result := 1;
|
|
end;
|
|
|
|
{**
|
|
What's this JDBC driver's minor version number?
|
|
@return JDBC driver minor version number
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetDriverMinorVersion: Integer;
|
|
begin
|
|
Result := 0;
|
|
end;
|
|
|
|
{**
|
|
Does the database use a file for each table?
|
|
@return true if the database uses a local file for each table
|
|
}
|
|
function TZSybaseDatabaseMetadata.UsesLocalFilePerTable: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{**
|
|
Does the database treat mixed case unquoted SQL identifiers as
|
|
case sensitive and as a result store them in mixed case?
|
|
A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will always return false.
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsMixedCaseIdentifiers: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{**
|
|
Does the database treat mixed case unquoted SQL identifiers as
|
|
case insensitive and store them in upper case?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.StoresUpperCaseIdentifiers: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Does the database treat mixed case unquoted SQL identifiers as
|
|
case insensitive and store them in lower case?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.StoresLowerCaseIdentifiers: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Does the database treat mixed case unquoted SQL identifiers as
|
|
case insensitive and store them in mixed case?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.StoresMixedCaseIdentifiers: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Does the database treat mixed case quoted SQL identifiers as
|
|
case sensitive and as a result store them in mixed case?
|
|
A JDBC Compliant<sup><font size=-2>TM</font></sup> driver will always return true.
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsMixedCaseQuotedIdentifiers: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Does the database treat mixed case quoted SQL identifiers as
|
|
case insensitive and store them in upper case?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.StoresUpperCaseQuotedIdentifiers: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Does the database treat mixed case quoted SQL identifiers as
|
|
case insensitive and store them in lower case?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.StoresLowerCaseQuotedIdentifiers: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Does the database treat mixed case quoted SQL identifiers as
|
|
case insensitive and store them in mixed case?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.StoresMixedCaseQuotedIdentifiers: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
What's the string used to quote SQL identifiers?
|
|
This returns a space " " if identifier quoting isn't supported.
|
|
A JDBC Compliant<sup><font size=-2>TM</font></sup>
|
|
driver always uses a double quote character.
|
|
@return the quoting string
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetIdentifierQuoteString: string;
|
|
begin
|
|
Result := '"';
|
|
end;
|
|
|
|
{**
|
|
Gets a comma-separated list of all a database's SQL keywords
|
|
that are NOT also SQL92 keywords.
|
|
@return the list
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetSQLKeywords: string;
|
|
begin
|
|
{ TODO -ofjanos -cAPI : SQL Keywords that are not SQL92 compliant }
|
|
Result := '';
|
|
end;
|
|
|
|
{**
|
|
Gets a comma-separated list of math functions. These are the
|
|
X/Open CLI math function names used in the JDBC function escape
|
|
clause.
|
|
@return the list
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetNumericFunctions: string;
|
|
begin
|
|
Result := 'ABS,ACOS,ASIN,ATAN,ATN2,CEILING,COS,COT,DEGREES,EXP,FLOOR,LOG,LOG10,'+
|
|
'PI,POWER,RADIANS,RAND,ROUND,SIGN,SIN,SQUARE,SQRT,TAN';
|
|
end;
|
|
|
|
{**
|
|
Gets a comma-separated list of string functions. These are the
|
|
X/Open CLI string function names used in the JDBC function escape
|
|
clause.
|
|
@return the list
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetStringFunctions: string;
|
|
begin
|
|
Result := 'ASCII,CHAR,CHARINDEX,DIFFERENCE,LEFT,LEN,LOWER,LTRIM,NCHAR,PATINDEX,'+
|
|
'REPLACE,QUOTENAME,REPLICATE,REVERSE,RIGHT,RTRIM,SOUNDEX,SPACE,STR,'+
|
|
'STUFF,SUBSTRING,UNICODE,UPPER';
|
|
end;
|
|
|
|
{**
|
|
Gets a comma-separated list of system functions. These are the
|
|
X/Open CLI system function names used in the JDBC function escape
|
|
clause.
|
|
@return the list
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetSystemFunctions: string;
|
|
begin
|
|
Result := 'APP_NAME,CASE,CAST,CONVERT,COALESCE,CURRENT_TIMESTAMP,CURRENT_USER,'+
|
|
'DATALENGTH,@@ERROR,FORMATMESSAGE,GETANSINULL,HOST_ID,HOST_NAME,'+
|
|
'IDENT_INCR,IDENT_SEED,@@IDENTITY,IDENTITY,ISDATE,ISNULL,ISNUMERIC,'+
|
|
'NEWID,NULLIF,PARSENAME,PERMISSIONS,@@ROWCOUNT,SESSION_USER,STATS_DATE,'+
|
|
'SYSTEM_USER,@@TRANCOUNT,USER_NAME';
|
|
end;
|
|
|
|
{**
|
|
Gets a comma-separated list of time and date functions.
|
|
@return the list
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetTimeDateFunctions: string;
|
|
begin
|
|
Result := 'DATEADD,DATEDIFF,DATENAME,DATEPART,DAY,GETDATE,MONTH,YEAR';
|
|
end;
|
|
|
|
{**
|
|
Gets the string that can be used to escape wildcard characters.
|
|
This is the string that can be used to escape '_' or '%' in
|
|
the string pattern style catalog search parameters.
|
|
|
|
<P>The '_' character represents any single character.
|
|
<P>The '%' character represents any sequence of zero or
|
|
more characters.
|
|
|
|
@return the string used to escape wildcard characters
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetSearchStringEscape: string;
|
|
begin
|
|
{ TODO -ofjanos -cgeneral :
|
|
In sql server this must be specified as the parameter of like.
|
|
example: WHERE ColumnA LIKE '%5/%%' ESCAPE '/' }
|
|
Result := '/';
|
|
end;
|
|
|
|
{**
|
|
Gets all the "extra" characters that can be used in unquoted
|
|
identifier names (those beyond a-z, A-Z, 0-9 and _).
|
|
@return the string containing the extra characters
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetExtraNameCharacters: string;
|
|
begin
|
|
Result := '@$#';
|
|
end;
|
|
|
|
//--------------------------------------------------------------------
|
|
// Functions describing which features are supported.
|
|
|
|
{**
|
|
Are expressions in "ORDER BY" lists supported?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsExpressionsInOrderBy: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can an "ORDER BY" clause use columns not in the SELECT statement?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsOrderByUnrelated: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Is some form of "GROUP BY" clause supported?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsGroupBy: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can a "GROUP BY" clause use columns not in the SELECT?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsGroupByUnrelated: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can a "GROUP BY" clause add columns not in the SELECT
|
|
provided it specifies all the columns in the SELECT?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsGroupByBeyondSelect: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Is the SQL Integrity Enhancement Facility supported?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsIntegrityEnhancementFacility: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{**
|
|
What's the database vendor's preferred term for "schema"?
|
|
@return the vendor term
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetSchemaTerm: string;
|
|
begin
|
|
Result := 'owner';
|
|
end;
|
|
|
|
{**
|
|
What's the database vendor's preferred term for "procedure"?
|
|
@return the vendor term
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetProcedureTerm: string;
|
|
begin
|
|
Result := 'procedure';
|
|
end;
|
|
|
|
{**
|
|
What's the database vendor's preferred term for "catalog"?
|
|
@return the vendor term
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetCatalogTerm: string;
|
|
begin
|
|
Result := 'database';
|
|
end;
|
|
|
|
{**
|
|
What's the separator between catalog and table name?
|
|
@return the separator string
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetCatalogSeparator: string;
|
|
begin
|
|
Result := '.';
|
|
end;
|
|
|
|
{**
|
|
Can a schema name be used in a data manipulation statement?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsSchemasInDataManipulation: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can a schema name be used in a procedure call statement?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsSchemasInProcedureCalls: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can a schema name be used in a table definition statement?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsSchemasInTableDefinitions: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can a schema name be used in an index definition statement?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsSchemasInIndexDefinitions: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can a schema name be used in a privilege definition statement?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsSchemasInPrivilegeDefinitions: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can a catalog name be used in a data manipulation statement?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsCatalogsInDataManipulation: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can a catalog name be used in a procedure call statement?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsCatalogsInProcedureCalls: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can a catalog name be used in a table definition statement?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsCatalogsInTableDefinitions: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can a catalog name be used in an index definition statement?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsCatalogsInIndexDefinitions: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can a catalog name be used in a privilege definition statement?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsCatalogsInPrivilegeDefinitions: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Is positioned DELETE supported?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsPositionedDelete: Boolean;
|
|
begin
|
|
//CURRENT OF
|
|
//Specifies that the DELETE is done at the current position of the specified cursor.
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Is positioned UPDATE supported?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsPositionedUpdate: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Is SELECT for UPDATE supported?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsSelectForUpdate: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Are stored procedure calls using the stored procedure escape
|
|
syntax supported?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsStoredProcedures: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Are subqueries in comparison expressions supported?
|
|
A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsSubqueriesInComparisons: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Are subqueries in 'exists' expressions supported?
|
|
A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsSubqueriesInExists: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Are subqueries in 'in' statements supported?
|
|
A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsSubqueriesInIns: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Are subqueries in quantified expressions supported?
|
|
A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsSubqueriesInQuantifieds: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Are correlated subqueries supported?
|
|
A JDBC Compliant<sup><font size=-2>TM</font></sup> driver always returns true.
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsCorrelatedSubqueries: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Is SQL UNION supported?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsUnion: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Is SQL UNION ALL supported?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsUnionAll: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can cursors remain open across commits?
|
|
@return <code>true</code> if cursors always remain open;
|
|
<code>false</code> if they might not remain open
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsOpenCursorsAcrossCommit: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can cursors remain open across rollbacks?
|
|
@return <code>true</code> if cursors always remain open;
|
|
<code>false</code> if they might not remain open
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsOpenCursorsAcrossRollback: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Can statements remain open across commits?
|
|
@return <code>true</code> if statements always remain open;
|
|
<code>false</code> if they might not remain open
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsOpenStatementsAcrossCommit: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{**
|
|
Can statements remain open across rollbacks?
|
|
@return <code>true</code> if statements always remain open;
|
|
<code>false</code> if they might not remain open
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsOpenStatementsAcrossRollback: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
//----------------------------------------------------------------------
|
|
// The following group of methods exposes various limitations
|
|
// based on the target database with the current driver.
|
|
// Unless otherwise specified, a result of zero means there is no
|
|
// limit, or the limit is not known.
|
|
|
|
{**
|
|
How many hex characters can you have in an inline binary literal?
|
|
@return max binary literal length in hex characters;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxBinaryLiteralLength: Integer;
|
|
begin
|
|
Result := 16000;
|
|
end;
|
|
|
|
{**
|
|
What's the max length for a character literal?
|
|
@return max literal length;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxCharLiteralLength: Integer;
|
|
begin
|
|
Result := 8000;
|
|
end;
|
|
|
|
{**
|
|
What's the limit on column name length?
|
|
@return max column name length;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxColumnNameLength: Integer;
|
|
begin
|
|
Result := 128;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum number of columns in a "GROUP BY" clause?
|
|
@return max number of columns;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxColumnsInGroupBy: Integer;
|
|
begin
|
|
Result := 0;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum number of columns allowed in an index?
|
|
@return max number of columns;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxColumnsInIndex: Integer;
|
|
begin
|
|
Result := 16;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum number of columns in an "ORDER BY" clause?
|
|
@return max number of columns;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxColumnsInOrderBy: Integer;
|
|
begin
|
|
Result := 0;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum number of columns in a "SELECT" list?
|
|
@return max number of columns;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxColumnsInSelect: Integer;
|
|
begin
|
|
Result := 4096;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum number of columns in a table?
|
|
@return max number of columns;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxColumnsInTable: Integer;
|
|
begin
|
|
Result := 1024;
|
|
end;
|
|
|
|
{**
|
|
How many active connections can we have at a time to this database?
|
|
@return max number of active connections;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxConnections: Integer;
|
|
begin
|
|
Result := 0;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum cursor name length?
|
|
@return max cursor name length in bytes;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxCursorNameLength: Integer;
|
|
begin
|
|
Result := 128;
|
|
end;
|
|
|
|
{**
|
|
Retrieves the maximum number of bytes for an index, including all
|
|
of the parts of the index.
|
|
@return max index length in bytes, which includes the composite of all
|
|
the constituent parts of the index;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxIndexLength: Integer;
|
|
begin
|
|
Result := 900;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum length allowed for a schema name?
|
|
@return max name length in bytes;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxSchemaNameLength: Integer;
|
|
begin
|
|
Result := 128;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum length of a procedure name?
|
|
@return max name length in bytes;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxProcedureNameLength: Integer;
|
|
begin
|
|
Result := 128;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum length of a catalog name?
|
|
@return max name length in bytes;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxCatalogNameLength: Integer;
|
|
begin
|
|
Result := 128;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum length of a single row?
|
|
@return max row size in bytes;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxRowSize: Integer;
|
|
begin
|
|
Result := 8060;
|
|
end;
|
|
|
|
{**
|
|
Did getMaxRowSize() include LONGVARCHAR and LONGVARBINARY
|
|
blobs?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.DoesMaxRowSizeIncludeBlobs: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum length of an SQL statement?
|
|
@return max length in bytes;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxStatementLength: Integer;
|
|
begin
|
|
Result := 0;
|
|
end;
|
|
|
|
{**
|
|
How many active statements can we have open at one time to this
|
|
database?
|
|
@return the maximum number of statements that can be open at one time;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxStatements: Integer;
|
|
begin
|
|
Result := 0;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum length of a table name?
|
|
@return max name length in bytes;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxTableNameLength: Integer;
|
|
begin
|
|
Result := 128;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum number of tables in a SELECT statement?
|
|
@return the maximum number of tables allowed in a SELECT statement;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxTablesInSelect: Integer;
|
|
begin
|
|
Result := 256;
|
|
end;
|
|
|
|
{**
|
|
What's the maximum length of a user name?
|
|
@return max user name length in bytes;
|
|
a result of zero means that there is no limit or the limit is not known
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetMaxUserNameLength: Integer;
|
|
begin
|
|
Result := 128;
|
|
end;
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
{**
|
|
What's the database's default transaction isolation level? The
|
|
values are defined in <code>java.sql.Connection</code>.
|
|
@return the default isolation level
|
|
@see Connection
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetDefaultTransactionIsolation:
|
|
TZTransactIsolationLevel;
|
|
begin
|
|
Result := tiReadCommitted;
|
|
end;
|
|
|
|
{**
|
|
Are transactions supported? If not, invoking the method
|
|
<code>commit</code> is a noop and the isolation level is TRANSACTION_NONE.
|
|
@return <code>true</code> if transactions are supported; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsTransactions: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Does this database support the given transaction isolation level?
|
|
@param level the values are defined in <code>java.sql.Connection</code>
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
@see Connection
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsTransactionIsolationLevel(
|
|
Level: TZTransactIsolationLevel): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Are both data definition and data manipulation statements
|
|
within a transaction supported?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.
|
|
SupportsDataDefinitionAndDataManipulationTransactions: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Are only data manipulation statements within a transaction
|
|
supported?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.
|
|
SupportsDataManipulationTransactionsOnly: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{**
|
|
Does a data definition statement within a transaction force the
|
|
transaction to commit?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.DataDefinitionCausesTransactionCommit: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{**
|
|
Is a data definition statement within a transaction ignored?
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.DataDefinitionIgnoredInTransactions: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of the stored procedures available in a
|
|
catalog.
|
|
|
|
<P>Only procedure descriptions matching the schema and
|
|
procedure name criteria are returned. They are ordered by
|
|
PROCEDURE_SCHEM, and PROCEDURE_NAME.
|
|
|
|
<P>Each procedure description has the the following columns:
|
|
<OL>
|
|
<LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
|
|
<LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
|
|
<LI><B>PROCEDURE_NAME</B> String => procedure name
|
|
<LI> reserved for future use
|
|
<LI> reserved for future use
|
|
<LI> reserved for future use
|
|
<LI><B>REMARKS</B> String => explanatory comment on the procedure
|
|
<LI><B>PROCEDURE_TYPE</B> short => kind of procedure:
|
|
<UL>
|
|
<LI> procedureResultUnknown - May return a result
|
|
<LI> procedureNoResult - Does not return a result
|
|
<LI> procedureReturnsResult - Returns a result
|
|
</UL>
|
|
</OL>
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schemaPattern a schema name pattern; "" retrieves those
|
|
without a schema
|
|
@param procedureNamePattern a procedure name pattern
|
|
@return <code>ResultSet</code> - each row is a procedure description
|
|
@see #getSearchStringEscape
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetProcedures(const Catalog: string;
|
|
const SchemaPattern: string; const ProcedureNamePattern: string): IZResultSet;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := Format('get-procedures:%s:%s:%s',
|
|
[Catalog, SchemaPattern, ProcedureNamePattern]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(ProceduresColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_stored_procedures %s, %s, %s',
|
|
[AQSNull(Catalog), AQSNull(SchemaPattern), AQSNull(ProcedureNamePattern)])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('PROCEDURE_CAT',
|
|
GetStringByName('PROCEDURE_CAT'));
|
|
Result.UpdateStringByName('PROCEDURE_SCHEM',
|
|
GetStringByName('PROCEDURE_SCHEM'));
|
|
Result.UpdateStringByName('PROCEDURE_NAME',
|
|
GetStringByName('PROCEDURE_NAME'));
|
|
Result.UpdateStringByName('REMARKS',
|
|
GetStringByName('REMARKS'));
|
|
Result.UpdateShortByName('PROCEDURE_TYPE',
|
|
GetShortByName('PROCEDURE_TYPE'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of a catalog's stored procedure parameters
|
|
and result columns.
|
|
|
|
<P>Only descriptions matching the schema, procedure and
|
|
parameter name criteria are returned. They are ordered by
|
|
PROCEDURE_SCHEM and PROCEDURE_NAME. Within this, the return value,
|
|
if any, is first. Next are the parameter descriptions in call
|
|
order. The column descriptions follow in column number order.
|
|
|
|
<P>Each row in the <code>ResultSet</code> is a parameter description or
|
|
column description with the following fields:
|
|
<OL>
|
|
<LI><B>PROCEDURE_CAT</B> String => procedure catalog (may be null)
|
|
<LI><B>PROCEDURE_SCHEM</B> String => procedure schema (may be null)
|
|
<LI><B>PROCEDURE_NAME</B> String => procedure name
|
|
<LI><B>COLUMN_NAME</B> String => column/parameter name
|
|
<LI><B>COLUMN_TYPE</B> Short => kind of column/parameter:
|
|
<UL>
|
|
<LI> procedureColumnUnknown - nobody knows
|
|
<LI> procedureColumnIn - IN parameter
|
|
<LI> procedureColumnInOut - INOUT parameter
|
|
<LI> procedureColumnOut - OUT parameter
|
|
<LI> procedureColumnReturn - procedure return value
|
|
<LI> procedureColumnResult - result column in <code>ResultSet</code>
|
|
</UL>
|
|
<LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
|
|
<LI><B>TYPE_NAME</B> String => SQL type name, for a UDT type the
|
|
type name is fully qualified
|
|
<LI><B>PRECISION</B> int => precision
|
|
<LI><B>LENGTH</B> int => length in bytes of data
|
|
<LI><B>SCALE</B> short => scale
|
|
<LI><B>RADIX</B> short => radix
|
|
<LI><B>NULLABLE</B> short => can it contain NULL?
|
|
<UL>
|
|
<LI> procedureNoNulls - does not allow NULL values
|
|
<LI> procedureNullable - allows NULL values
|
|
<LI> procedureNullableUnknown - nullability unknown
|
|
</UL>
|
|
<LI><B>REMARKS</B> String => comment describing parameter/column
|
|
</OL>
|
|
|
|
<P><B>Note:</B> Some databases may not return the column
|
|
descriptions for a procedure. Additional columns beyond
|
|
REMARKS can be defined by the database.
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schemaPattern a schema name pattern; "" retrieves those
|
|
without a schema
|
|
@param procedureNamePattern a procedure name pattern
|
|
@param columnNamePattern a column name pattern
|
|
@return <code>ResultSet</code> - each row describes a stored procedure parameter or
|
|
column
|
|
@see #getSearchStringEscape
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetProcedureColumns(const Catalog: string;
|
|
const SchemaPattern: string; const ProcedureNamePattern: string;
|
|
const ColumnNamePattern: string): IZResultSet;
|
|
var
|
|
ProcNamePart: string;
|
|
NumberPart: string;
|
|
status2: Integer;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := Format('get-procedure-columns:%s:%s:%s:%s',
|
|
[Catalog, SchemaPattern, ProcedureNamePattern, ColumnNamePattern]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(ProceduresColColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_getprocedurecolumns %s, %s, %s, %s',
|
|
[AQSNull(Catalog), AQSNull(SchemaPattern), AQSNull(ProcedureNamePattern), AQSNull(ColumnNamePattern)])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('PROCEDURE_CAT',
|
|
GetStringByName('PROCEDURE_CAT'));
|
|
Result.UpdateStringByName('PROCEDURE_SCHEM',
|
|
GetStringByName('PROCEDURE_SCHEM'));
|
|
Result.UpdateStringByName('PROCEDURE_NAME',
|
|
GetStringByName('PROCEDURE_NAME'));
|
|
Result.UpdateStringByName('COLUMN_NAME',
|
|
GetStringByName('COLUMN_NAME'));
|
|
case GetShortByName('COLUMN_TYPE') of
|
|
0, 1: Result.UpdateShortByName('COLUMN_TYPE', 1); //ptInput
|
|
2: Result.UpdateShortByName('COLUMN_TYPE', 3); //ptInputOutput
|
|
3: Result.UpdateShortByName('COLUMN_TYPE', 0); //ptUnknown
|
|
4: Result.UpdateShortByName('COLUMN_TYPE', 3); //ptInputOutput
|
|
5: Result.UpdateShortByName('COLUMN_TYPE', 4); //ptResult
|
|
else
|
|
Result.UpdateShortByName('COLUMN_TYPE', 0); //ptUnknown
|
|
end;
|
|
Result.UpdateShortByName('DATA_TYPE',
|
|
Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'))));
|
|
Result.UpdateStringByName('TYPE_NAME',
|
|
GetStringByName('TYPE_NAME'));
|
|
Result.UpdateIntByName('PRECISION',
|
|
GetIntByName('PRECISION'));
|
|
Result.UpdateIntByName('LENGTH',
|
|
GetIntByName('LENGTH'));
|
|
Result.UpdateShortByName('SCALE',
|
|
GetShortByName('SCALE'));
|
|
Result.UpdateShortByName('RADIX',
|
|
GetShortByName('RADIX'));
|
|
Result.UpdateShortByName('NULLABLE',
|
|
GetShortByName('NULLABLE'));
|
|
Result.UpdateStringByName('REMARKS',
|
|
GetStringByName('REMARKS'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
Result.BeforeFirst;
|
|
|
|
NumberPart := '1';
|
|
if AnsiPos(';', ProcNamePart) > 0 then
|
|
begin
|
|
NumberPart := Copy(ProcNamePart, LastDelimiter(';', ProcNamePart) + 1,
|
|
Length(ProcNamePart));
|
|
if NumberPart = '' then
|
|
NumberPart := '1';
|
|
|
|
ProcNamePart := Copy(ProcNamePart, 1, LastDelimiter(';', ProcNamePart));
|
|
if ProcNamePart[Length(ProcNamePart)] = ';' then
|
|
Delete(ProcNamePart, Length(ProcNamePart), 1);
|
|
end;
|
|
//status2 is added in sybase ASE 12.5 to store the storedprocedure parameters
|
|
// input/output type this column does not exists in prior versions.
|
|
// In prior versions there is no way to determine between input or output type.
|
|
with GetStatement.ExecuteQuery(
|
|
Format('select c.* from syscolumns c inner join sysobjects o on'
|
|
+ ' (o.id = c.id) where o.name = %s and c.number = %s order by colid',
|
|
[AnsiQuotedStr(ProcNamePart, ''''), NumberPart])) do
|
|
begin
|
|
Result.Next;//Skip return parameter
|
|
while Next do
|
|
begin
|
|
Result.Next;
|
|
if FindColumn('status2') >= 1 then
|
|
status2 := GetShortByName('status2')
|
|
else
|
|
status2 := 0;
|
|
case status2 of
|
|
0, 1: Result.UpdateShortByName('COLUMN_TYPE', 1); //ptInput
|
|
2: Result.UpdateShortByName('COLUMN_TYPE', 3); //ptInputOutput
|
|
3: Result.UpdateShortByName('COLUMN_TYPE', 0); //ptUnknown
|
|
4: Result.UpdateShortByName('COLUMN_TYPE', 3); //ptInputOutput
|
|
5: Result.UpdateShortByName('COLUMN_TYPE', 4); //ptResult
|
|
else
|
|
Result.UpdateShortByName('COLUMN_TYPE', 0); //ptUnknown
|
|
end;
|
|
Result.UpdateRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of tables available in a catalog.
|
|
|
|
<P>Only table descriptions matching the catalog, schema, table
|
|
name and type criteria are returned. They are ordered by
|
|
TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.
|
|
|
|
<P>Each table description has the following columns:
|
|
<OL>
|
|
<LI><B>TABLE_CAT</B> String => table catalog (may be null)
|
|
<LI><B>TABLE_SCHEM</B> String => table schema (may be null)
|
|
<LI><B>TABLE_NAME</B> String => table name
|
|
<LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
|
|
"VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
|
|
"LOCAL TEMPORARY", "ALIAS", "SYNONYM".
|
|
<LI><B>REMARKS</B> String => explanatory comment on the table
|
|
</OL>
|
|
|
|
<P><B>Note:</B> Some databases may not return information for
|
|
all tables.
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schemaPattern a schema name pattern; "" retrieves those
|
|
without a schema
|
|
@param tableNamePattern a table name pattern
|
|
@param types a list of table types to include; null returns all types
|
|
@return <code>ResultSet</code> - each row is a table description
|
|
@see #getSearchStringEscape
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetTables(const Catalog: string;
|
|
const SchemaPattern: string; const TableNamePattern: string;
|
|
const Types: TStringDynArray): IZResultSet;
|
|
var
|
|
I: Integer;
|
|
Key: string;
|
|
TableTypes: string;
|
|
begin
|
|
Key := GetTablesMetaDataCacheKey(Catalog,SchemaPattern,TableNamePattern,Types);
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(TableColumnsDynArray);
|
|
|
|
TableTypes := '';
|
|
for I := 0 to Length(Types) - 1 do
|
|
begin
|
|
if TableTypes <> '' then
|
|
TableTypes := TableTypes + ',';
|
|
TableTypes := TableTypes + AnsiQuotedStr(Types[I], '''');
|
|
end;
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_tables %s, %s, %s, %s',
|
|
[AQSNull(TableNamePattern), AQSNull(SchemaPattern), AQSNull(Catalog), AQSNull(TableTypes, '"')])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('TABLE_CAT',
|
|
GetStringByName('TABLE_CAT'));
|
|
Result.UpdateStringByName('TABLE_SCHEM',
|
|
GetStringByName('TABLE_SCHEM'));
|
|
Result.UpdateStringByName('TABLE_NAME',
|
|
GetStringByName('TABLE_NAME'));
|
|
Result.UpdateStringByName('TABLE_TYPE',
|
|
GetStringByName('TABLE_TYPE'));
|
|
Result.UpdateStringByName('REMARKS',
|
|
GetStringByName('REMARKS'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets the schema names available in this database. The results
|
|
are ordered by schema name.
|
|
|
|
<P>The schema column is:
|
|
<OL>
|
|
<LI><B>TABLE_SCHEM</B> String => schema name
|
|
</OL>
|
|
|
|
@return <code>ResultSet</code> - each row has a single String column that is a
|
|
schema name
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetSchemas: IZResultSet;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := 'get-schemas';
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(SchemaColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery('exec sp_jdbc_getschemas') do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('TABLE_SCHEM',
|
|
GetStringByName('TABLE_SCHEM'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets the catalog names available in this database. The results
|
|
are ordered by catalog name.
|
|
|
|
<P>The catalog column is:
|
|
<OL>
|
|
<LI><B>TABLE_CAT</B> String => catalog name
|
|
</OL>
|
|
|
|
@return <code>ResultSet</code> - each row has a single String column that is a
|
|
catalog name
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetCatalogs: IZResultSet;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := 'get-catalogs';
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(CatalogColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery('exec sp_jdbc_getcatalogs') do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('TABLE_CAT',
|
|
GetStringByName('TABLE_CAT'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets the table types available in this database. The results
|
|
are ordered by table type.
|
|
|
|
<P>The table type is:
|
|
<OL>
|
|
<LI><B>TABLE_TYPE</B> String => table type. Typical types are "TABLE",
|
|
"VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
|
|
"LOCAL TEMPORARY", "ALIAS", "SYNONYM".
|
|
</OL>
|
|
|
|
@return <code>ResultSet</code> - each row has a single String column that is a
|
|
table type
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetTableTypes: IZResultSet;
|
|
const
|
|
TableTypes: array[0..2] of string = ('SYSTEM TABLE', 'TABLE', 'VIEW');
|
|
var
|
|
I: Integer;
|
|
Key: string;
|
|
begin
|
|
Key := 'get-table-types';
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(TableTypeColumnsDynArray);
|
|
|
|
for I := 0 to 2 do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('TABLE_TYPE', TableTypes[I]);
|
|
Result.InsertRow;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of table columns available in
|
|
the specified catalog.
|
|
|
|
<P>Only column descriptions matching the catalog, schema, table
|
|
and column name criteria are returned. They are ordered by
|
|
TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION.
|
|
|
|
<P>Each column description has the following columns:
|
|
<OL>
|
|
<LI><B>TABLE_CAT</B> String => table catalog (may be null)
|
|
<LI><B>TABLE_SCHEM</B> String => table schema (may be null)
|
|
<LI><B>TABLE_NAME</B> String => table name
|
|
<LI><B>COLUMN_NAME</B> String => column name
|
|
<LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types
|
|
<LI><B>TYPE_NAME</B> String => Data source dependent type name,
|
|
for a UDT the type name is fully qualified
|
|
<LI><B>COLUMN_SIZE</B> int => column size. For char or date
|
|
types this is the maximum number of characters, for numeric or
|
|
decimal types this is precision.
|
|
<LI><B>BUFFER_LENGTH</B> is not used.
|
|
<LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
|
|
<LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
|
|
<LI><B>NULLABLE</B> int => is NULL allowed?
|
|
<UL>
|
|
<LI> columnNoNulls - might not allow NULL values
|
|
<LI> columnNullable - definitely allows NULL values
|
|
<LI> columnNullableUnknown - nullability unknown
|
|
</UL>
|
|
<LI><B>REMARKS</B> String => comment describing column (may be null)
|
|
<LI><B>COLUMN_DEF</B> String => default value (may be null)
|
|
<LI><B>SQL_DATA_TYPE</B> int => unused
|
|
<LI><B>SQL_DATETIME_SUB</B> int => unused
|
|
<LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
|
|
maximum number of bytes in the column
|
|
<LI><B>ORDINAL_POSITION</B> int => index of column in table
|
|
(starting at 1)
|
|
<LI><B>IS_NULLABLE</B> String => "NO" means column definitely
|
|
does not allow NULL values; "YES" means the column might
|
|
allow NULL values. An empty string means nobody knows.
|
|
</OL>
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schemaPattern a schema name pattern; "" retrieves those
|
|
without a schema
|
|
@param tableNamePattern a table name pattern
|
|
@param columnNamePattern a column name pattern
|
|
@return <code>ResultSet</code> - each row is a column description
|
|
@see #getSearchStringEscape
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetColumns(const Catalog: string;
|
|
const SchemaPattern: string; const TableNamePattern: string;
|
|
const ColumnNamePattern: string): IZResultSet;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := Format('get-columns:%s:%s:%s:%s',
|
|
[Catalog, SchemaPattern, TableNamePattern, ColumnNamePattern]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(TableColColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_columns %s, %s, %s, %s',
|
|
[AQSNull(TableNamePattern), AQSNull(SchemaPattern), AQSNull(Catalog), AQSNull(ColumnNamePattern)])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('TABLE_CAT',
|
|
''{GetStringByName('TABLE_CAT')});
|
|
Result.UpdateStringByName('TABLE_SCHEM',
|
|
''{GetStringByName('TABLE_SCHEM')});
|
|
Result.UpdateStringByName('TABLE_NAME',
|
|
GetStringByName('TABLE_NAME'));
|
|
Result.UpdateStringByName('COLUMN_NAME',
|
|
GetStringByName('COLUMN_NAME'));
|
|
//The value in the resultset will be used
|
|
// Result.UpdateShortByName('DATA_TYPE',
|
|
// Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'))));
|
|
Result.UpdateStringByName('TYPE_NAME',
|
|
GetStringByName('TYPE_NAME'));
|
|
Result.UpdateIntByName('COLUMN_SIZE',
|
|
GetIntByName('COLUMN_SIZE'));
|
|
Result.UpdateIntByName('BUFFER_LENGTH',
|
|
GetIntByName('BUFFER_LENGTH'));
|
|
Result.UpdateIntByName('DECIMAL_DIGITS',
|
|
GetIntByName('DECIMAL_DIGITS'));
|
|
Result.UpdateIntByName('NUM_PREC_RADIX',
|
|
GetShortByName('NUM_PREC_RADIX'));
|
|
Result.UpdateShortByName('NULLABLE',
|
|
GetShortByName('NULLABLE'));
|
|
Result.UpdateStringByName('REMARKS',
|
|
GetStringByName('REMARKS'));
|
|
Result.UpdateStringByName('COLUMN_DEF',
|
|
GetStringByName('COLUMN_DEF'));
|
|
Result.UpdateShortByName('SQL_DATA_TYPE',
|
|
GetShortByName('SQL_DATA_TYPE'));
|
|
Result.UpdateShortByName('SQL_DATETIME_SUB',
|
|
GetShortByName('SQL_DATETIME_SUB'));
|
|
Result.UpdateIntByName('CHAR_OCTET_LENGTH',
|
|
GetIntByName('CHAR_OCTET_LENGTH'));
|
|
Result.UpdateIntByName('ORDINAL_POSITION',
|
|
GetIntByName('ORDINAL_POSITION'));
|
|
Result.UpdateStringByName('IS_NULLABLE',
|
|
GetStringByName('IS_NULLABLE'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
Result.BeforeFirst;
|
|
with GetStatement.ExecuteQuery(
|
|
Format('select c.colid, c.name, c.type, c.prec, c.scale, c.status'
|
|
+ ' from syscolumns c inner join sysobjects o on (o.id = c.id)'
|
|
+ ' where o.name = "%s" order by colid', [TableNamePattern])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.Next;
|
|
Result.UpdateBooleanByName('AUTO_INCREMENT',
|
|
(GetShortByName('status') and $80) <> 0);
|
|
Result.UpdateNullByName('CASE_SENSITIVE');
|
|
Result.UpdateBooleanByName('SEARCHABLE',
|
|
not (GetShortByName('type') in [34, 35]));
|
|
Result.UpdateBooleanByName('WRITABLE',
|
|
((GetShortByName('status') and $80) = 0)
|
|
and (GetShortByName('type') <> 37));
|
|
Result.UpdateBooleanByName('DEFINITELYWRITABLE',
|
|
Result.GetBooleanByName('WRITABLE'));
|
|
Result.UpdateBooleanByName('READONLY',
|
|
not Result.GetBooleanByName('WRITABLE'));
|
|
if Result.GetBooleanByName('AUTO_INCREMENT') then
|
|
begin
|
|
Result.UpdateShortByName('NULLABLE', 1);
|
|
Result.UpdateStringByName('IS_NULLABLE', 'YES');
|
|
end;
|
|
Result.UpdateRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of the access rights for a table's columns.
|
|
|
|
<P>Only privileges matching the column name criteria are
|
|
returned. They are ordered by COLUMN_NAME and PRIVILEGE.
|
|
|
|
<P>Each privilige description has the following columns:
|
|
<OL>
|
|
<LI><B>TABLE_CAT</B> String => table catalog (may be null)
|
|
<LI><B>TABLE_SCHEM</B> String => table schema (may be null)
|
|
<LI><B>TABLE_NAME</B> String => table name
|
|
<LI><B>COLUMN_NAME</B> String => column name
|
|
<LI><B>GRANTOR</B> => grantor of access (may be null)
|
|
<LI><B>GRANTEE</B> String => grantee of access
|
|
<LI><B>PRIVILEGE</B> String => name of access (SELECT,
|
|
INSERT, UPDATE, REFRENCES, ...)
|
|
<LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
|
|
to grant to others; "NO" if not; null if unknown
|
|
</OL>
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schema a schema name; "" retrieves those without a schema
|
|
@param table a table name
|
|
@param columnNamePattern a column name pattern
|
|
@return <code>ResultSet</code> - each row is a column privilege description
|
|
@see #getSearchStringEscape
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetColumnPrivileges(const Catalog: string;
|
|
const Schema: string; const Table: string; const ColumnNamePattern: string): IZResultSet;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := Format('get-column-privileges:%s:%s:%s:%s',
|
|
[Catalog, Schema, Table, ColumnNamePattern]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(TableColPrivColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_getcolumnprivileges %s, %s, %s, %s',
|
|
[AQSNull(Catalog), AQSNull(Schema), AQSNull(Table),
|
|
AQSNullText(ColumnNamePattern, '''%''')])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('TABLE_CAT',
|
|
GetStringByName('TABLE_CAT'));
|
|
Result.UpdateStringByName('TABLE_SCHEM',
|
|
GetStringByName('TABLE_SCHEM'));
|
|
Result.UpdateStringByName('TABLE_NAME',
|
|
GetStringByName('TABLE_NAME'));
|
|
Result.UpdateStringByName('COLUMN_NAME',
|
|
GetStringByName('COLUMN_NAME'));
|
|
Result.UpdateStringByName('GRANTOR',
|
|
GetStringByName('GRANTOR'));
|
|
Result.UpdateStringByName('GRANTEE',
|
|
GetStringByName('GRANTEE'));
|
|
Result.UpdateStringByName('PRIVILEGE',
|
|
GetStringByName('PRIVILEGE'));
|
|
Result.UpdateStringByName('IS_GRANTABLE',
|
|
GetStringByName('IS_GRANTABLE'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of the access rights for each table available
|
|
in a catalog. Note that a table privilege applies to one or
|
|
more columns in the table. It would be wrong to assume that
|
|
this priviledge applies to all columns (this may be true for
|
|
some systems but is not true for all.)
|
|
|
|
<P>Only privileges matching the schema and table name
|
|
criteria are returned. They are ordered by TABLE_SCHEM,
|
|
TABLE_NAME, and PRIVILEGE.
|
|
|
|
<P>Each privilige description has the following columns:
|
|
<OL>
|
|
<LI><B>TABLE_CAT</B> String => table catalog (may be null)
|
|
<LI><B>TABLE_SCHEM</B> String => table schema (may be null)
|
|
<LI><B>TABLE_NAME</B> String => table name
|
|
<LI><B>GRANTOR</B> => grantor of access (may be null)
|
|
<LI><B>GRANTEE</B> String => grantee of access
|
|
<LI><B>PRIVILEGE</B> String => name of access (SELECT,
|
|
INSERT, UPDATE, REFRENCES, ...)
|
|
<LI><B>IS_GRANTABLE</B> String => "YES" if grantee is permitted
|
|
to grant to others; "NO" if not; null if unknown
|
|
</OL>
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schemaPattern a schema name pattern; "" retrieves those
|
|
without a schema
|
|
@param tableNamePattern a table name pattern
|
|
@return <code>ResultSet</code> - each row is a table privilege description
|
|
@see #getSearchStringEscape
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetTablePrivileges(const Catalog: string;
|
|
const SchemaPattern: string; const TableNamePattern: string): IZResultSet;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := Format('get-table-privileges:%s:%s:%s',
|
|
[Catalog, SchemaPattern, TableNamePattern]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(TablePrivColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_gettableprivileges %s, %s, %s',
|
|
[AQSNull(Catalog), AQSNull(SchemaPattern), AQSNull(TableNamePattern)])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('TABLE_CAT',
|
|
GetStringByName('TABLE_CAT'));
|
|
Result.UpdateStringByName('TABLE_SCHEM',
|
|
GetStringByName('TABLE_SCHEM'));
|
|
Result.UpdateStringByName('TABLE_NAME',
|
|
GetStringByName('TABLE_NAME'));
|
|
Result.UpdateStringByName('GRANTOR',
|
|
GetStringByName('GRANTOR'));
|
|
Result.UpdateStringByName('GRANTEE',
|
|
GetStringByName('GRANTEE'));
|
|
Result.UpdateStringByName('PRIVILEGE',
|
|
GetStringByName('PRIVILEGE'));
|
|
Result.UpdateStringByName('IS_GRANTABLE',
|
|
GetStringByName('IS_GRANTABLE'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of a table's columns that are automatically
|
|
updated when any value in a row is updated. They are
|
|
unordered.
|
|
|
|
<P>Each column description has the following columns:
|
|
<OL>
|
|
<LI><B>SCOPE</B> short => is not used
|
|
<LI><B>COLUMN_NAME</B> String => column name
|
|
<LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
|
|
<LI><B>TYPE_NAME</B> String => Data source dependent type name
|
|
<LI><B>COLUMN_SIZE</B> int => precision
|
|
<LI><B>BUFFER_LENGTH</B> int => length of column value in bytes
|
|
<LI><B>DECIMAL_DIGITS</B> short => scale
|
|
<LI><B>PSEUDO_COLUMN</B> short => is this a pseudo column
|
|
like an Oracle ROWID
|
|
<UL>
|
|
<LI> versionColumnUnknown - may or may not be pseudo column
|
|
<LI> versionColumnNotPseudo - is NOT a pseudo column
|
|
<LI> versionColumnPseudo - is a pseudo column
|
|
</UL>
|
|
</OL>
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schema a schema name; "" retrieves those without a schema
|
|
@param table a table name
|
|
@return <code>ResultSet</code> - each row is a column description
|
|
@exception SQLException if a database access error occurs
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetVersionColumns(const Catalog: string;
|
|
const Schema: string; const Table: string): IZResultSet;
|
|
var
|
|
MSCol_Type: string;
|
|
Key: string;
|
|
begin
|
|
Key := Format('get-version-columns:%s:%s:%s', [Catalog, Schema, Table]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(TableColVerColumnsDynArray);
|
|
|
|
MSCol_Type := '''V''';
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_getversioncolumns %s, %s, %s',
|
|
[AQSNull(Catalog), AQSNull(Schema), AQSNull(Table)])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateShortByName('SCOPE',
|
|
GetShortByName('SCOPE'));
|
|
Result.UpdateStringByName('COLUMN_NAME',
|
|
GetStringByName('COLUMN_NAME'));
|
|
Result.UpdateShortByName('DATA_TYPE',
|
|
Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'))));
|
|
Result.UpdateStringByName('TYPE_NAME',
|
|
GetStringByName('TYPE_NAME'));
|
|
Result.UpdateIntByName('COLUMN_SIZE',
|
|
GetIntByName('COLUMN_SIZE'));
|
|
Result.UpdateIntByName('BUFFER_LENGTH',
|
|
GetIntByName('BUFFER_LENGTH'));
|
|
Result.UpdateIntByName('DECIMAL_DIGITS',
|
|
GetIntByName('DECIMAL_DIGITS'));
|
|
Result.UpdateShortByName('PSEUDO_COLUMN',
|
|
GetShortByName('PSEUDO_COLUMN'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of a table's primary key columns. They
|
|
are ordered by COLUMN_NAME.
|
|
|
|
<P>Each primary key column description has the following columns:
|
|
<OL>
|
|
<LI><B>TABLE_CAT</B> String => table catalog (may be null)
|
|
<LI><B>TABLE_SCHEM</B> String => table schema (may be null)
|
|
<LI><B>TABLE_NAME</B> String => table name
|
|
<LI><B>COLUMN_NAME</B> String => column name
|
|
<LI><B>KEY_SEQ</B> short => sequence number within primary key
|
|
<LI><B>PK_NAME</B> String => primary key name (may be null)
|
|
</OL>
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schema a schema name; "" retrieves those
|
|
without a schema
|
|
@param table a table name
|
|
@return <code>ResultSet</code> - each row is a primary key column description
|
|
@exception SQLException if a database access error occurs
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetPrimaryKeys(const Catalog: string;
|
|
const Schema: string; const Table: string): IZResultSet;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := Format('get-primary-keys:%s:%s:%s', [Catalog, Schema, Table]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(PrimaryKeyColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_primarykey %s, %s, %s',
|
|
[AQSNull(Catalog), AQSNull(Schema), AQSNull(Table)])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('TABLE_CAT',
|
|
GetStringByName('TABLE_CAT'));
|
|
Result.UpdateStringByName('TABLE_SCHEM',
|
|
GetStringByName('TABLE_SCHEM'));
|
|
Result.UpdateStringByName('TABLE_NAME',
|
|
GetStringByName('TABLE_NAME'));
|
|
Result.UpdateStringByName('COLUMN_NAME',
|
|
GetStringByName('COLUMN_NAME'));
|
|
Result.UpdateShortByName('KEY_SEQ',
|
|
GetShortByName('KEY_SEQ'));
|
|
Result.UpdateStringByName('PK_NAME',
|
|
GetStringByName('PK_NAME'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of the primary key columns that are
|
|
referenced by a table's foreign key columns (the primary keys
|
|
imported by a table). They are ordered by PKTABLE_CAT,
|
|
PKTABLE_SCHEM, PKTABLE_NAME, and KEY_SEQ.
|
|
|
|
<P>Each primary key column description has the following columns:
|
|
<OL>
|
|
<LI><B>PKTABLE_CAT</B> String => primary key table catalog
|
|
being imported (may be null)
|
|
<LI><B>PKTABLE_SCHEM</B> String => primary key table schema
|
|
being imported (may be null)
|
|
<LI><B>PKTABLE_NAME</B> String => primary key table name
|
|
being imported
|
|
<LI><B>PKCOLUMN_NAME</B> String => primary key column name
|
|
being imported
|
|
<LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
|
|
<LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
|
|
<LI><B>FKTABLE_NAME</B> String => foreign key table name
|
|
<LI><B>FKCOLUMN_NAME</B> String => foreign key column name
|
|
<LI><B>KEY_SEQ</B> short => sequence number within foreign key
|
|
<LI><B>UPDATE_RULE</B> short => What happens to
|
|
foreign key when primary is updated:
|
|
<UL>
|
|
<LI> importedNoAction - do not allow update of primary
|
|
key if it has been imported
|
|
<LI> importedKeyCascade - change imported key to agree
|
|
with primary key update
|
|
<LI> importedKeySetNull - change imported key to NULL if
|
|
its primary key has been updated
|
|
<LI> importedKeySetDefault - change imported key to default values
|
|
if its primary key has been updated
|
|
<LI> importedKeyRestrict - same as importedKeyNoAction
|
|
(for ODBC 2.x compatibility)
|
|
</UL>
|
|
<LI><B>DELETE_RULE</B> short => What happens to
|
|
the foreign key when primary is deleted.
|
|
<UL>
|
|
<LI> importedKeyNoAction - do not allow delete of primary
|
|
key if it has been imported
|
|
<LI> importedKeyCascade - delete rows that import a deleted key
|
|
<LI> importedKeySetNull - change imported key to NULL if
|
|
its primary key has been deleted
|
|
<LI> importedKeyRestrict - same as importedKeyNoAction
|
|
(for ODBC 2.x compatibility)
|
|
<LI> importedKeySetDefault - change imported key to default if
|
|
its primary key has been deleted
|
|
</UL>
|
|
<LI><B>FK_NAME</B> String => foreign key name (may be null)
|
|
<LI><B>PK_NAME</B> String => primary key name (may be null)
|
|
<LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
|
|
constraints be deferred until commit
|
|
<UL>
|
|
<LI> importedKeyInitiallyDeferred - see SQL92 for definition
|
|
<LI> importedKeyInitiallyImmediate - see SQL92 for definition
|
|
<LI> importedKeyNotDeferrable - see SQL92 for definition
|
|
</UL>
|
|
</OL>
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schema a schema name; "" retrieves those
|
|
without a schema
|
|
@param table a table name
|
|
@return <code>ResultSet</code> - each row is a primary key column description
|
|
@see #getExportedKeys
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetImportedKeys(const Catalog: string;
|
|
const Schema: string; const Table: string): IZResultSet;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := Format('get-imported-keys:%s:%s:%s', [Catalog, Schema, Table]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(ImportedKeyColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_importkey %s, %s, %s',
|
|
[AQSNull(Catalog), AQSNull(Schema), AQSNull(Table)])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('PKTABLE_CAT',
|
|
GetStringByName('PKTABLE_CAT'));
|
|
Result.UpdateStringByName('PKTABLE_SCHEM',
|
|
GetStringByName('PKTABLE_SCHEM'));
|
|
Result.UpdateStringByName('PKTABLE_NAME',
|
|
GetStringByName('PKTABLE_NAME'));
|
|
Result.UpdateStringByName('PKCOLUMN_NAME',
|
|
GetStringByName('PKCOLUMN_NAME'));
|
|
Result.UpdateStringByName('FKTABLE_CAT',
|
|
GetStringByName('FKTABLE_CAT'));
|
|
Result.UpdateStringByName('FKTABLE_SCHEM',
|
|
GetStringByName('FKTABLE_SCHEM'));
|
|
Result.UpdateStringByName('FKTABLE_NAME',
|
|
GetStringByName('FKTABLE_NAME'));
|
|
Result.UpdateStringByName('FKCOLUMN_NAME',
|
|
GetStringByName('FKCOLUMN_NAME'));
|
|
Result.UpdateShortByName('KEY_SEQ',
|
|
GetShortByName('KEY_SEQ'));
|
|
Result.UpdateShortByName('UPDATE_RULE',
|
|
GetShortByName('UPDATE_RULE'));
|
|
Result.UpdateShortByName('DELETE_RULE',
|
|
GetShortByName('DELETE_RULE'));
|
|
Result.UpdateStringByName('FK_NAME',
|
|
GetStringByName('FK_NAME'));
|
|
Result.UpdateStringByName('PK_NAME',
|
|
GetStringByName('PK_NAME'));
|
|
Result.UpdateIntByName('DEFERRABILITY',
|
|
GetIntByName('DEFERRABILITY'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of the foreign key columns that reference a
|
|
table's primary key columns (the foreign keys exported by a
|
|
table). They are ordered by FKTABLE_CAT, FKTABLE_SCHEM,
|
|
FKTABLE_NAME, and KEY_SEQ.
|
|
|
|
<P>Each foreign key column description has the following columns:
|
|
<OL>
|
|
<LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
|
|
<LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
|
|
<LI><B>PKTABLE_NAME</B> String => primary key table name
|
|
<LI><B>PKCOLUMN_NAME</B> String => primary key column name
|
|
<LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
|
|
being exported (may be null)
|
|
<LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
|
|
being exported (may be null)
|
|
<LI><B>FKTABLE_NAME</B> String => foreign key table name
|
|
being exported
|
|
<LI><B>FKCOLUMN_NAME</B> String => foreign key column name
|
|
being exported
|
|
<LI><B>KEY_SEQ</B> short => sequence number within foreign key
|
|
<LI><B>UPDATE_RULE</B> short => What happens to
|
|
foreign key when primary is updated:
|
|
<UL>
|
|
<LI> importedNoAction - do not allow update of primary
|
|
key if it has been imported
|
|
<LI> importedKeyCascade - change imported key to agree
|
|
with primary key update
|
|
<LI> importedKeySetNull - change imported key to NULL if
|
|
its primary key has been updated
|
|
<LI> importedKeySetDefault - change imported key to default values
|
|
if its primary key has been updated
|
|
<LI> importedKeyRestrict - same as importedKeyNoAction
|
|
(for ODBC 2.x compatibility)
|
|
</UL>
|
|
<LI><B>DELETE_RULE</B> short => What happens to
|
|
the foreign key when primary is deleted.
|
|
<UL>
|
|
<LI> importedKeyNoAction - do not allow delete of primary
|
|
key if it has been imported
|
|
<LI> importedKeyCascade - delete rows that import a deleted key
|
|
<LI> importedKeySetNull - change imported key to NULL if
|
|
its primary key has been deleted
|
|
<LI> importedKeyRestrict - same as importedKeyNoAction
|
|
(for ODBC 2.x compatibility)
|
|
<LI> importedKeySetDefault - change imported key to default if
|
|
its primary key has been deleted
|
|
</UL>
|
|
<LI><B>FK_NAME</B> String => foreign key name (may be null)
|
|
<LI><B>PK_NAME</B> String => primary key name (may be null)
|
|
<LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
|
|
constraints be deferred until commit
|
|
<UL>
|
|
<LI> importedKeyInitiallyDeferred - see SQL92 for definition
|
|
<LI> importedKeyInitiallyImmediate - see SQL92 for definition
|
|
<LI> importedKeyNotDeferrable - see SQL92 for definition
|
|
</UL>
|
|
</OL>
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schema a schema name; "" retrieves those
|
|
without a schema
|
|
@param table a table name
|
|
@return <code>ResultSet</code> - each row is a foreign key column description
|
|
@see #getImportedKeys
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetExportedKeys(const Catalog: string;
|
|
const Schema: string; const Table: string): IZResultSet;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := Format('get-exported-keys:%s:%s:%s', [Catalog, Schema, Table]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(ExportedKeyColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_exportkey %s, %s, %s',
|
|
[AQSNull(Catalog), AQSNull(Schema), AQSNull(Table)])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('PKTABLE_CAT',
|
|
GetStringByName('PKTABLE_CAT'));
|
|
Result.UpdateStringByName('PKTABLE_SCHEM',
|
|
GetStringByName('PKTABLE_SCHEM'));
|
|
Result.UpdateStringByName('PKTABLE_NAME',
|
|
GetStringByName('PKTABLE_NAME'));
|
|
Result.UpdateStringByName('PKCOLUMN_NAME',
|
|
GetStringByName('PKCOLUMN_NAME'));
|
|
Result.UpdateStringByName('FKTABLE_CAT',
|
|
GetStringByName('FKTABLE_CAT'));
|
|
Result.UpdateStringByName('FKTABLE_SCHEM',
|
|
GetStringByName('FKTABLE_SCHEM'));
|
|
Result.UpdateStringByName('FKTABLE_NAME',
|
|
GetStringByName('FKTABLE_NAME'));
|
|
Result.UpdateStringByName('FKCOLUMN_NAME',
|
|
GetStringByName('FKCOLUMN_NAME'));
|
|
Result.UpdateShortByName('KEY_SEQ',
|
|
GetShortByName('KEY_SEQ'));
|
|
Result.UpdateShortByName('UPDATE_RULE',
|
|
GetShortByName('UPDATE_RULE'));
|
|
Result.UpdateShortByName('DELETE_RULE',
|
|
GetShortByName('DELETE_RULE'));
|
|
Result.UpdateStringByName('FK_NAME',
|
|
GetStringByName('FK_NAME'));
|
|
Result.UpdateStringByName('PK_NAME',
|
|
GetStringByName('PK_NAME'));
|
|
Result.UpdateIntByName('DEFERRABILITY',
|
|
GetIntByName('DEFERRABILITY'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of the foreign key columns in the foreign key
|
|
table that reference the primary key columns of the primary key
|
|
table (describe how one table imports another's key.) This
|
|
should normally return a single foreign key/primary key pair
|
|
(most tables only import a foreign key from a table once.) They
|
|
are ordered by FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, and
|
|
KEY_SEQ.
|
|
|
|
<P>Each foreign key column description has the following columns:
|
|
<OL>
|
|
<LI><B>PKTABLE_CAT</B> String => primary key table catalog (may be null)
|
|
<LI><B>PKTABLE_SCHEM</B> String => primary key table schema (may be null)
|
|
<LI><B>PKTABLE_NAME</B> String => primary key table name
|
|
<LI><B>PKCOLUMN_NAME</B> String => primary key column name
|
|
<LI><B>FKTABLE_CAT</B> String => foreign key table catalog (may be null)
|
|
being exported (may be null)
|
|
<LI><B>FKTABLE_SCHEM</B> String => foreign key table schema (may be null)
|
|
being exported (may be null)
|
|
<LI><B>FKTABLE_NAME</B> String => foreign key table name
|
|
being exported
|
|
<LI><B>FKCOLUMN_NAME</B> String => foreign key column name
|
|
being exported
|
|
<LI><B>KEY_SEQ</B> short => sequence number within foreign key
|
|
<LI><B>UPDATE_RULE</B> short => What happens to
|
|
foreign key when primary is updated:
|
|
<UL>
|
|
<LI> importedNoAction - do not allow update of primary
|
|
key if it has been imported
|
|
<LI> importedKeyCascade - change imported key to agree
|
|
with primary key update
|
|
<LI> importedKeySetNull - change imported key to NULL if
|
|
its primary key has been updated
|
|
<LI> importedKeySetDefault - change imported key to default values
|
|
if its primary key has been updated
|
|
<LI> importedKeyRestrict - same as importedKeyNoAction
|
|
(for ODBC 2.x compatibility)
|
|
</UL>
|
|
<LI><B>DELETE_RULE</B> short => What happens to
|
|
the foreign key when primary is deleted.
|
|
<UL>
|
|
<LI> importedKeyNoAction - do not allow delete of primary
|
|
key if it has been imported
|
|
<LI> importedKeyCascade - delete rows that import a deleted key
|
|
<LI> importedKeySetNull - change imported key to NULL if
|
|
its primary key has been deleted
|
|
<LI> importedKeyRestrict - same as importedKeyNoAction
|
|
(for ODBC 2.x compatibility)
|
|
<LI> importedKeySetDefault - change imported key to default if
|
|
its primary key has been deleted
|
|
</UL>
|
|
<LI><B>FK_NAME</B> String => foreign key name (may be null)
|
|
<LI><B>PK_NAME</B> String => primary key name (may be null)
|
|
<LI><B>DEFERRABILITY</B> short => can the evaluation of foreign key
|
|
constraints be deferred until commit
|
|
<UL>
|
|
<LI> importedKeyInitiallyDeferred - see SQL92 for definition
|
|
<LI> importedKeyInitiallyImmediate - see SQL92 for definition
|
|
<LI> importedKeyNotDeferrable - see SQL92 for definition
|
|
</UL>
|
|
</OL>
|
|
|
|
@param primaryCatalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param primarySchema a schema name; "" retrieves those
|
|
without a schema
|
|
@param primaryTable the table name that exports the key
|
|
@param foreignCatalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param foreignSchema a schema name; "" retrieves those
|
|
without a schema
|
|
@param foreignTable the table name that imports the key
|
|
@return <code>ResultSet</code> - each row is a foreign key column description
|
|
@see #getImportedKeys
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetCrossReference(const PrimaryCatalog: string;
|
|
const PrimarySchema: string; const PrimaryTable: string; const ForeignCatalog: string;
|
|
const ForeignSchema: string; const ForeignTable: string): IZResultSet;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := Format('get-cross-reference:%s:%s:%s:%s:%s:%s',
|
|
[PrimaryCatalog, PrimarySchema, PrimaryTable, ForeignCatalog,
|
|
ForeignSchema, ForeignTable]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(CrossRefColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_getcrossreferences %s, %s, %s, %s, %s, %s',
|
|
[AQSNull(PrimaryCatalog), AQSNull(PrimarySchema), AQSNull(PrimaryTable),
|
|
AQSNull(ForeignCatalog), AQSNull(ForeignSchema), AQSNull(ForeignTable)])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('PKTABLE_CAT',
|
|
GetStringByName('PKTABLE_CAT'));
|
|
Result.UpdateStringByName('PKTABLE_SCHEM',
|
|
GetStringByName('PKTABLE_SCHEM'));
|
|
Result.UpdateStringByName('PKTABLE_NAME',
|
|
GetStringByName('PKTABLE_NAME'));
|
|
Result.UpdateStringByName('PKCOLUMN_NAME',
|
|
GetStringByName('PKCOLUMN_NAME'));
|
|
Result.UpdateStringByName('FKTABLE_CAT',
|
|
GetStringByName('FKTABLE_CAT'));
|
|
Result.UpdateStringByName('FKTABLE_SCHEM',
|
|
GetStringByName('FKTABLE_SCHEM'));
|
|
Result.UpdateStringByName('FKTABLE_NAME',
|
|
GetStringByName('FKTABLE_NAME'));
|
|
Result.UpdateStringByName('FKCOLUMN_NAME',
|
|
GetStringByName('FKCOLUMN_NAME'));
|
|
Result.UpdateShortByName('KEY_SEQ',
|
|
GetShortByName('KEY_SEQ'));
|
|
Result.UpdateShortByName('UPDATE_RULE',
|
|
GetShortByName('UPDATE_RULE'));
|
|
Result.UpdateShortByName('DELETE_RULE',
|
|
GetShortByName('DELETE_RULE'));
|
|
Result.UpdateStringByName('FK_NAME',
|
|
GetStringByName('FK_NAME'));
|
|
Result.UpdateStringByName('PK_NAME',
|
|
GetStringByName('PK_NAME'));
|
|
Result.UpdateIntByName('DEFERRABILITY',
|
|
GetIntByName('DEFERRABILITY'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of all the standard SQL types supported by
|
|
this database. They are ordered by DATA_TYPE and then by how
|
|
closely the data type maps to the corresponding JDBC SQL type.
|
|
|
|
<P>Each type description has the following columns:
|
|
<OL>
|
|
<LI><B>TYPE_NAME</B> String => Type name
|
|
<LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types
|
|
<LI><B>PRECISION</B> int => maximum precision
|
|
<LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal
|
|
(may be null)
|
|
<LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal
|
|
(may be null)
|
|
<LI><B>CREATE_PARAMS</B> String => parameters used in creating
|
|
the type (may be null)
|
|
<LI><B>NULLABLE</B> short => can you use NULL for this type?
|
|
<UL>
|
|
<LI> typeNoNulls - does not allow NULL values
|
|
<LI> typeNullable - allows NULL values
|
|
<LI> typeNullableUnknown - nullability unknown
|
|
</UL>
|
|
<LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive?
|
|
<LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type:
|
|
<UL>
|
|
<LI> typePredNone - No support
|
|
<LI> typePredChar - Only supported with WHERE .. LIKE
|
|
<LI> typePredBasic - Supported except for WHERE .. LIKE
|
|
<LI> typeSearchable - Supported for all WHERE ..
|
|
</UL>
|
|
<LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned?
|
|
<LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value?
|
|
<LI><B>AUTO_INCREMENT</B> boolean => can it be used for an
|
|
auto-increment value?
|
|
<LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name
|
|
(may be null)
|
|
<LI><B>MINIMUM_SCALE</B> short => minimum scale supported
|
|
<LI><B>MAXIMUM_SCALE</B> short => maximum scale supported
|
|
<LI><B>SQL_DATA_TYPE</B> int => unused
|
|
<LI><B>SQL_DATETIME_SUB</B> int => unused
|
|
<LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10
|
|
</OL>
|
|
|
|
@return <code>ResultSet</code> - each row is an SQL type description
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetTypeInfo: IZResultSet;
|
|
var
|
|
Key: string;
|
|
begin
|
|
Key := 'get-type-info';
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(TypeInfoColumnsDynArray);
|
|
|
|
with GetStatement.ExecuteQuery('exec sp_jdbc_datatype_info') do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('TYPE_NAME',
|
|
GetStringByName('TYPE_NAME'));
|
|
Result.UpdateShortByName('DATA_TYPE',
|
|
Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'))));
|
|
Result.UpdateIntByName('PRECISION',
|
|
GetIntByName('PRECISION'));
|
|
Result.UpdateStringByName('LITERAL_PREFIX',
|
|
GetStringByName('LITERAL_PREFIX'));
|
|
Result.UpdateStringByName('LITERAL_SUFFIX',
|
|
GetStringByName('LITERAL_SUFFIX'));
|
|
Result.UpdateStringByName('CREATE_PARAMS',
|
|
GetStringByName('CREATE_PARAMS'));
|
|
Result.UpdateShortByName('NULLABLE',
|
|
GetShortByName('NULLABLE'));
|
|
Result.UpdateBooleanByName('CASE_SENSITIVE',
|
|
GetShortByName('CASE_SENSITIVE') = 1);
|
|
Result.UpdateShortByName('SEARCHABLE',
|
|
GetShortByName('SEARCHABLE'));
|
|
Result.UpdateBooleanByName('UNSIGNED_ATTRIBUTE',
|
|
GetShortByName('UNSIGNED_ATTRIBUTE') = 1);
|
|
Result.UpdateBooleanByName('FIXED_PREC_SCALE',
|
|
GetShortByName('FIXED_PREC_SCALE') = 1);
|
|
Result.UpdateBooleanByName('AUTO_INCREMENT',
|
|
GetShortByName('AUTO_INCREMENT') = 1);
|
|
Result.UpdateStringByName('LOCAL_TYPE_NAME',
|
|
GetStringByName('LOCAL_TYPE_NAME'));
|
|
Result.UpdateShortByName('MINIMUM_SCALE',
|
|
GetShortByName('MINIMUM_SCALE'));
|
|
Result.UpdateShortByName('MAXIMUM_SCALE',
|
|
GetShortByName('MAXIMUM_SCALE'));
|
|
Result.UpdateShortByName('SQL_DATA_TYPE',
|
|
GetShortByName('SQL_DATA_TYPE'));
|
|
Result.UpdateShortByName('SQL_DATETIME_SUB',
|
|
GetShortByName('SQL_DATETIME_SUB'));
|
|
Result.UpdateShortByName('NUM_PREC_RADIX',
|
|
GetShortByName('NUM_PREC_RADIX'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Gets a description of a table's indices and statistics. They are
|
|
ordered by NON_UNIQUE, TYPE, INDEX_NAME, and ORDINAL_POSITION.
|
|
|
|
<P>Each index column description has the following columns:
|
|
<OL>
|
|
<LI><B>TABLE_CAT</B> String => table catalog (may be null)
|
|
<LI><B>TABLE_SCHEM</B> String => table schema (may be null)
|
|
<LI><B>TABLE_NAME</B> String => table name
|
|
<LI><B>NON_UNIQUE</B> boolean => Can index values be non-unique?
|
|
false when TYPE is tableIndexStatistic
|
|
<LI><B>INDEX_QUALIFIER</B> String => index catalog (may be null);
|
|
null when TYPE is tableIndexStatistic
|
|
<LI><B>INDEX_NAME</B> String => index name; null when TYPE is
|
|
tableIndexStatistic
|
|
<LI><B>TYPE</B> short => index type:
|
|
<UL>
|
|
<LI> tableIndexStatistic - this identifies table statistics that are
|
|
returned in conjuction with a table's index descriptions
|
|
<LI> tableIndexClustered - this is a clustered index
|
|
<LI> tableIndexHashed - this is a hashed index
|
|
<LI> tableIndexOther - this is some other style of index
|
|
</UL>
|
|
<LI><B>ORDINAL_POSITION</B> short => column sequence number
|
|
within index; zero when TYPE is tableIndexStatistic
|
|
<LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
|
|
tableIndexStatistic
|
|
<LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
|
|
"D" => descending, may be null if sort sequence is not supported;
|
|
null when TYPE is tableIndexStatistic
|
|
<LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatistic, then
|
|
this is the number of rows in the table; otherwise, it is the
|
|
number of unique values in the index.
|
|
<LI><B>PAGES</B> int => When TYPE is tableIndexStatisic then
|
|
this is the number of pages used for the table, otherwise it
|
|
is the number of pages used for the current index.
|
|
<LI><B>FILTER_CONDITION</B> String => Filter condition, if any.
|
|
(may be null)
|
|
</OL>
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schema a schema name; "" retrieves those without a schema
|
|
@param table a table name
|
|
@param unique when true, return only indices for unique values;
|
|
when false, return indices regardless of whether unique or not
|
|
@param approximate when true, result is allowed to reflect approximate
|
|
or out of data values; when false, results are requested to be
|
|
accurate
|
|
@return <code>ResultSet</code> - each row is an index column description
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetIndexInfo(const Catalog: string;
|
|
const Schema: string; const Table: string; Unique: Boolean;
|
|
Approximate: Boolean): IZResultSet;
|
|
var
|
|
Is_Unique, Accuracy: string;
|
|
Key: string;
|
|
begin
|
|
Key := Format('get-index-info:%s:%s:%s:%s:%s',
|
|
[Catalog, Schema, Table, BoolToStr(Unique), BoolToStr(Approximate)]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(IndexInfoColumnsDynArray);
|
|
|
|
if Unique then
|
|
Is_Unique := '''1'''
|
|
else Is_Unique := '''0''';
|
|
if Approximate then
|
|
Accuracy := '''1'''
|
|
else Accuracy := '''0''';
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_getindexinfo %s, %s, %s, %s, %s',
|
|
[AQSNull(Catalog), AQSNull(Schema), AQSNull(Table), Is_Unique, Accuracy])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('TABLE_CAT',
|
|
GetStringByName('TABLE_CAT'));
|
|
Result.UpdateStringByName('TABLE_SCHEM',
|
|
GetStringByName('TABLE_SCHEM'));
|
|
Result.UpdateStringByName('TABLE_NAME',
|
|
GetStringByName('TABLE_NAME'));
|
|
Result.UpdateBooleanByName('NON_UNIQUE',
|
|
GetShortByName('NON_UNIQUE') = 1);
|
|
Result.UpdateStringByName('INDEX_QUALIFIER',
|
|
GetStringByName('INDEX_QUALIFIER'));
|
|
Result.UpdateStringByName('INDEX_NAME',
|
|
GetStringByName('INDEX_NAME'));
|
|
Result.UpdateShortByName('TYPE',
|
|
GetShortByName('TYPE'));
|
|
Result.UpdateShortByName('ORDINAL_POSITION',
|
|
GetShortByName('ORDINAL_POSITION'));
|
|
Result.UpdateStringByName('COLUMN_NAME',
|
|
GetStringByName('COLUMN_NAME'));
|
|
Result.UpdateStringByName('ASC_OR_DESC',
|
|
GetStringByName('ASC_OR_DESC'));
|
|
Result.UpdateIntByName('CARDINALITY',
|
|
GetIntByName('CARDINALITY'));
|
|
Result.UpdateIntByName('PAGES',
|
|
GetIntByName('PAGES'));
|
|
Result.UpdateStringByName('FILTER_CONDITION',
|
|
GetStringByName('FILTER_CONDITION'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Does the database support the given result set type?
|
|
@param type defined in <code>java.sql.ResultSet</code>
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsResultSetType(
|
|
_Type: TZResultSetType): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
Does the database support the concurrency type in combination
|
|
with the given result set type?
|
|
|
|
@param type defined in <code>java.sql.ResultSet</code>
|
|
@param concurrency type defined in <code>java.sql.ResultSet</code>
|
|
@return <code>true</code> if so; <code>false</code> otherwise
|
|
}
|
|
function TZSybaseDatabaseMetadata.SupportsResultSetConcurrency(
|
|
_Type: TZResultSetType; Concurrency: TZResultSetConcurrency): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
{**
|
|
|
|
Gets a description of the user-defined types defined in a particular
|
|
schema. Schema-specific UDTs may have type JAVA_OBJECT, STRUCT,
|
|
or DISTINCT.
|
|
|
|
<P>Only types matching the catalog, schema, type name and type
|
|
criteria are returned. They are ordered by DATA_TYPE, TYPE_SCHEM
|
|
and TYPE_NAME. The type name parameter may be a fully-qualified
|
|
name. In this case, the catalog and schemaPattern parameters are
|
|
ignored.
|
|
|
|
<P>Each type description has the following columns:
|
|
<OL>
|
|
<LI><B>TYPE_CAT</B> String => the type's catalog (may be null)
|
|
<LI><B>TYPE_SCHEM</B> String => type's schema (may be null)
|
|
<LI><B>TYPE_NAME</B> String => type name
|
|
<LI><B>CLASS_NAME</B> String => Java class name
|
|
<LI><B>DATA_TYPE</B> String => type value defined in java.sql.Types.
|
|
One of JAVA_OBJECT, STRUCT, or DISTINCT
|
|
<LI><B>REMARKS</B> String => explanatory comment on the type
|
|
</OL>
|
|
|
|
<P><B>Note:</B> If the driver does not support UDTs, an empty
|
|
result set is returned.
|
|
|
|
@param catalog a catalog name; "" retrieves those without a
|
|
catalog; null means drop catalog name from the selection criteria
|
|
@param schemaPattern a schema name pattern; "" retrieves those
|
|
without a schema
|
|
@param typeNamePattern a type name pattern; may be a fully-qualified name
|
|
@param types a list of user-named types to include (JAVA_OBJECT,
|
|
STRUCT, or DISTINCT); null returns all types
|
|
@return <code>ResultSet</code> - each row is a type description
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetUDTs(const Catalog: string;
|
|
const SchemaPattern: string; const TypeNamePattern: string;
|
|
const Types: TIntegerDynArray): IZResultSet;
|
|
var
|
|
I: Integer;
|
|
UDTypes: string;
|
|
Key: string;
|
|
begin
|
|
Key := '';
|
|
for I := Low(Types) to High(Types) do
|
|
Key := Key + ':' + IntToStr(Types[I]);
|
|
Key := Format('get-udts:%s:%s:%s%s',
|
|
[Catalog, SchemaPattern, TypeNamePattern, Key]);
|
|
|
|
Result := GetResultSetFromCache(Key);
|
|
if Result = nil then
|
|
begin
|
|
Result := ConstructVirtualResultSet(UDTColumnsDynArray);
|
|
|
|
UDTypes := '';
|
|
for I := 0 to Length(Types) - 1 do
|
|
begin
|
|
if Length(UDTypes) > 0 then
|
|
UDTypes := UDTypes + ',';
|
|
UDTypes := UDTypes + AnsiQuotedStr(IntToStr(Types[I]), '''');
|
|
end;
|
|
|
|
with GetStatement.ExecuteQuery(
|
|
Format('exec sp_jdbc_getudts %s, %s, %s, %s',
|
|
[AQSNull(Catalog), AQSNullText(SchemaPattern, '''%'''),
|
|
AQSNullText(TypeNamePattern, '''%'''), AQSNull(UDTypes, '"')])) do
|
|
begin
|
|
while Next do
|
|
begin
|
|
Result.MoveToInsertRow;
|
|
Result.UpdateStringByName('TYPE_CAT',
|
|
GetStringByName('TYPE_CAT'));
|
|
Result.UpdateStringByName('TYPE_SCHEM',
|
|
GetStringByName('TYPE_SCHEM'));
|
|
Result.UpdateStringByName('TYPE_NAME',
|
|
GetStringByName('TYPE_NAME'));
|
|
Result.UpdateStringByName('JAVA_CLASS',
|
|
GetStringByName('JAVA_CLASS'));
|
|
Result.UpdateShortByName('DATA_TYPE',
|
|
Ord(ConvertODBCToSqlType(GetShortByName('DATA_TYPE'))));
|
|
Result.UpdateStringByName('REMARKS',
|
|
GetStringByName('REMARKS'));
|
|
Result.InsertRow;
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
AddResultSetToCache(Key, Result);
|
|
end;
|
|
end;
|
|
|
|
{**
|
|
Create a statement for use
|
|
|
|
@return TZDBLibStatement
|
|
}
|
|
function TZSybaseDatabaseMetadata.GetStatement: IZSTatement;
|
|
begin
|
|
Result := GetConnection.CreateStatement;
|
|
end;
|
|
|
|
end.
|
|
|