Chapter 48 – SQL/CLI: General Functions¶
Note
You are reading a digital copy of SQL-99 Complete, Really, a book that documents the SQL-99 standard.
For more information specific to CrateDB, check out the CrateDB Reference.
In this chapter, we discuss SQLDataSources
, SQLGetFunctions
and
SQLGetInfo
. We call these the “general” functions because they are used
primarily in applications which are not tied to a specific DBMS or a specific
database. Generalized applications need to find out what is available, as part
of a long initialization process. Here are the descriptions of the three
general functions.
Table of Contents
SQLDataSources¶
Function Prototype:
SQLRETURN SQLDataSources(
SQLHENV henv, /* 32-bit input */
SQLSMALLINT Direction, /* 16-bit input, =
SQL_FETCH_FIRST or SQL_FETCH_NEXT */
SQLCHAR *ServerName, /* pointer to char* output */
SQLSMALLINT BufferLength1, /* 16-bit input */
SQLSMALLINT *NameLength1, /* pointer to 16-bit output */
SQLCHAR *Description, /* pointer to char* output */
SQLSMALLINT BufferLength2, /* 16-bit input */
SQLSMALLINT *NameLength2 /* pointer to 16-bit output */
);
Job: Return names of data sources – that is, servers or databases.
Algorithm:
If (henv is not really an env handle or env is skeleton)
return error: CLI-specific condition-invalid handle
Empty the diagnostics area associated with henv.
If (Direction is not SQL_FIRST (2)or SQL_NEXT (1))
return error: HY103 CLI-specific condition-invalid retrieval code
If (Direction == SQL_FIRST (2))
/* Cursor position is for first row of "Data Sources" Table */
If (Direction is SQL_NEXT (1))
/* Cursor position is for next row of "Data Sources" Table
(it's 1st row if we've never called SQLDataSources before)
(it's 1st row if last call to SQLDataSources returned "no data") */
If (Cursor position is now past end)
return with warning: 02000 no data -
"Fetch" into ServerName and Description parameters
/* The usual Character Set Retrieval rules apply. */
Notes:
The SQL Standard is firm about the meaning of the term “data source”: the
SQLDataSources
function is supposed to return names of SQL-servers. For some single-tier desktop DBMSs (which are not based on a client-server architecture), it is more reasonable to expect that the names returned here will be names of databases. In any case, the name is something you can use in aSQLConnect
call.You would use this function for browsing (“What servers can I connect to?”) or for checking availability (“Is server
X
up yet?”). In many commercial installations the application is tightly linked to a particular server, so callingSQLDataSources
has no point – either you can callSQLConnect
and succeed, or you cannot. There is a big implementation-defined question here, namely, how does anybody know what servers are out there? That depends on how the system is configured, but – sometimes – there is a query to see what names are established on the network, or a directory search for Catalog files.In theory, the maximum length of
ServerName
should be the implementation-defined maximum length of aVARCHAR
string. In practice, the maximum length ofServerName
is 128 characters.This is one of the very few functions for which the input handle is a
henv
. You can callSQLGetDataSources
before allocating adbc
or connecting. There might be several data sources associated with anenv
.Imagine that there is a Table “
Data Sources
” containing twoCHAR
Columns: “servername
” or “databasename
”, and “description
”. TheSQLDataSources
function willFETCH
a single row from this Table.SQLDataSources
would have been implemented as a Catalog function – that is, it would have returned a result set – if it were not for the inconvenient fact that we want to retrieve data sources information before we connect.
Example: This example displays a list of available servers; assume that
the “Data Sources
” Table looks like this:
"Data Sources"
"servername" "description"
Wally A server on the organization's main computer
Sammy A local server used for test purposes
#include "sqlcli.h"
SQLHENV henv;
SQLCHAR name[128+1], description[1024];
SQLSMALLINT name_length, description_length;
SQLRETURN sqlreturn;
...
SQLAllocHandle(SQL_HANDLE_ENV,NULL,&henv);
for (;;) {
sqlreturn = SQLDataSources(
henv, /* henv parameter */
SQL_FETCH_NEXT, /* Direction */
name, /* *ServerName */
sizeof(name), /* BufferLength1 */
&name_length, /* *NameLength1 */
description, /* *Description */
sizeof(description), /* BufferLength2 */
&description_length /* NameLength2 */
);
if (sqlreturn == SQL_NO_DATA) break;
printf("ServerName = %s. Description = %s.\n",name,description); }
SQLFreeHandle(SQL_HANDLE_ENV,henv);
ODBC: This function has been available since ODBC 1.0. The Driver Manager
handles the call, by checking the registry of data sources which have been
installed using the ODBC installation program. In fact, SQLDataSources
is
very much an ODBC sort of call, since it is difficult to see how one could find
a server list without using some sort of non-standard “Driver Manager”.
Tip
With Windows 3.x the ODBC driver information is stored in an .INI
file, which you can query directly with GetPrivateProfileString
. With
Windows95, the ODBC driver information is stored in the registry.
SQLGetFunctions¶
Function Prototype:
SQLRETURN SQLGetFunctions(
SQLHDBC hdbc, /* 32-bit input */
SQLSMALLINT FunctionId, /* 32-bit input */
SQLSMALLINT *Supported /* pointer to 16-bit output */
);
Job: Find out whether a specified CLI function is supported. The legal list
of FunctionID
values, as defined (with #define
) in sqlcli.h
,
follows – function codes are in alphabetical order; the version of standard
SQL, or ODBC, which requires support of the function is noted after the
function’s numeric code:
#define SQL_API_SQLALLOCCONNECT 1 SQL-92
#define SQL_API_SQLALLOCENV 2 SQL-92
#define SQL_API_SQLALLOCHANDLE 1001 SQL-92
#define SQL_API_SQLALLOCHANDLESTD 74 X/Open
#define SQL_API_SQLALLOCSTMT 3 SQL-92
#define SQL_API_SQLBINDCOL 4 SQL-92
#define SQL_API_SQLBINDPARAM 1002 ODBC 3
#define SQL_API_SQLBINDPARAMETER 72 SQL-92
#define SQL_API_SQLBROWSECONNECT 55 ODBC 3
#define SQL_API_SQLBULKOPERATIONS 24 ODBC 3
#define SQL_API_SQLCANCEL 5 SQL-92
#define SQL_API_SQLCLOSECURSOR 1003 SQL-92
#define SQL_API_SQLCOLATTRIBUTE 6 SQL-92
#define SQL_API_SQLCOLATTRIBUTES 6 ODBC 2
#define SQL_API_SQLCOLUMNPRIVILEGES 56 SQL-92
#define SQL_API_SQLCOLUMNS 40 SQL3
#define SQL_API_SQLCONNECT 7 SQL-92
#define SQL_API_SQLCOPYDESC 1004 SQL-92
#define SQL_API_SQLDATASOURCES 57 SQL-92
#define SQL_API_SQLDESCRIBECOL 8 SQL-92
#define SQL_API_SQLDESCRIBEPARAM 58 ODBC 3
#define SQL_API_SQLDISCONNECT 9 SQL-92
#define SQL_API_SQLDRIVERCONNECT 41 ODBC 3
#define SQL_API_SQLDRIVERS 71 ODBC 3
#define SQL_API_SQLENDTRAN 1005 SQL-92
#define SQL_API_SQLERROR 10 SQL-92
#define SQL_API_SQLEXECDIRECT 11 SQL-92
#define SQL_API_SQLEXECUTE 12 SQL-92
#define SQL_API_SQLEXTENDEDFETCH 59 ODBC 3
#define SQL_API_SQLFETCH 13 SQL-92
#define SQL_API_SQLFETCHSCROLL 1021 SQL-92
#define SQL_API_SQLFOREIGNKEYS 60 SQL-92
#define SQL_API_SQLFREECONNECT 14 SQL-92
#define SQL_API_SQLFREEENV 15 SQL-92
#define SQL_API_SQLFREEHANDLE 1006 SQL-92
#define SQL_API_SQLFREELOCATOR 1031 SQL3
#define SQL_API_SQLFREESTMT 16 SQL-92
#define SQL_API_SQLGETCONNECTATTR 1007 SQL-92
#define SQL_API_SQLGETCONNECTOPTION 42 ODBC 2
#define SQL_API_SQLGETCURSORNAME 17 SQL-92
#define SQL_API_SQLGETDATA 43 SQL-92
#define SQL_API_SQLGETDESCFIELD 1008 SQL-92
#define SQL_API_SQLGETDESCREC 1009 SQL-92
#define SQL_API_SQLGETDIAGFIELD 1010 SQL-92
#define SQL_API_SQLGETDIAGREC 1011 SQL-92
#define SQL_API_SQLGETENVATTR 1012 SQL-92
#define SQL_API_SQLGETFUNCTIONS 44 SQL-92
#define SQL_API_SQLGETINFO 45 SQL-92
#define SQL_API_SQLGETLENGTH 1022 SQL-92
#define SQL_API_SQLGETPARAMDATA 1025 SQL-92
#define SQL_API_SQLGETPOSITION 1023 SQL-92
#define SQL_API_SQLGETSTMTATTR 1014 SQL-92
#define SQL_API_SQLGETSTMTOPTIONS 46 ODBC 2
#define SQL_API_SQLGETSUBSTRING 1024 SQL3
#define SQL_API_SQLGETTYPEINFO 47 SQL-92
#define SQL_API_SQLMORERESULTS 61 SQL-92
#define SQL_API_SQLNATIVESQL 62 ODBC 3
#define SQL_API_SQLNUMPARAMS 63 ODBC 3
#define SQL_API_SQLNUMRESULTCOLS 18 SQL-92
#define SQL_API_SQLPARAMDATA 48 SQL-92
#define SQL_API_SQLPARAMETERS 2002 SQL-92
#define SQL_API_SQLPARAMOPTIONS 64 ODBC 3
#define SQL_API_SQLPREPARE 19 SQL-92
#define SQL_API_SQLPRIMARYKEYS 65 SQL-92
#define SQL_API_SQLPROCEDURECOLUMNS 66 ODBC 3
#define SQL_API_SQLPROCEDURES 67 ODBC 3
#define SQL_API_SQLPUTDATA 49 SQL-92
#define SQL_API_SQLROUTINEPRIVILEGES 1026 SQL-92
#define SQL_API_SQLROUTINES 2003 SQL-92
#define SQL_API_SQLROWCOUNT 20 SQL-92
#define SQL_API_SQLSETCONNECTATTR 1016 SQL-92
#define SQL_API_SQLSETCONNECTOPTION 50 ODBC 2
#define SQL_API_SQLSETCURSORNAME 21 SQL-92
#define SQL_API_SQLSETDESCFIELD 1017 SQL-92
#define SQL_API_SQLSETDESCREC 1018 SQL-92
#define SQL_API_SQLSETENVATTR 1019 SQL-92
#define SQL_API_SQLSETPARAM 2 ODBC 2
#define SQL_API_SQLSETPOS 68 ODBC 2
#define SQL_API_SQLSETSCROLLOPTIONS 69 ODBC 2
#define SQL_API_SQLSETSTMTATTR 1020 SQL-92
#define SQL_API_SQLSETSTMTOPTION 51 ODBC 2
#define SQL_API_SQLSPECIALCOLUMNS 52 SQL3
#define SQL_API_SQLSTATISTICS 53 X/Open
#define SQL_API_SQLTABLEPRIVILEGES 70 SQL-92
#define SQL_API_SQLTABLES 54 SQL3
#define SQL_API_SQLTRANSACT 23 ODBC 2
Algorithm:
If (hdbc is not really a handle of a dbc)
return error: CLI-specific condition-invalid handle
Empty the dbc's diagnostics area.
If (no connection opened on hdbc)
return error: 08003 connection exception-connection does not exist
If (the function identified by FunctionId is supported)
Set *Supported = 1 (true);
Else
Set *Supported = 0 (false).
Notes:
SQL_API_SQLCOLATTRIBUTE
andSQL_API_SQLCOLATTRIBUTES
have the same value: 6. This error is no longer important, sinceSQLColAttributes
was only an ODBC 2.0 function.Calling
SQLGetFunctions(...,SQL_API_SQLGETFUNCTION,...)
looks a little like asking a person “Are you awake?”, i.e.: the answer is either “yes” or you get no answer at all. But in some contexts it’s a perfectly reasonable question. For instance, all versions of ODBC include a Driver Manager – a DLL layer which is separate from the DBMS itself (the “driver” and the “data source”). In an ODBC context, you’re really asking the Driver Manager a question about the driver, and that’s a question you can expect either a “yes” or a “no” answer for.It’s clear from the
FunctionID
value chart that some CLI functions are old, some are new, some are implementation-specific, some are standard. That’s why it makes sense to callSQLGetFunctions
right after connecting, and branch to an appropriate path depending on which functions are supported. TheSQLGetInfo
function is useful for the same sort of purpose.If you are using MS-Windows and you are calling the DBMS directly, the question you really want to ask is: is the function name exported?
Example: Although Microsoft’s documentation marks the ODBC function
SQLStatistics()
as “ISO 92”, it’s not an ISO Standard function. So
before using it, we will ask whether our DBMS supports it. Here’s how.
#include "sqlcli.h"
/* In case SQL_API_STATISTICS isn't in sqlcli.h, we define it here. */
#define SQL_API_SQLSTATISTICS 53
SQLHENV henv;
SQLHDBC hdbc;
SQLSMALLINT supported;
void main ()
{
SQLAllocHandle(SQL_HANDLE_ENV,...);
SQLAllocConnect(SQL_HANDLE_DBC,...);
SQLConnect(hdbc,...);
if (SQLGetFunctions(hdbc,SQL_API_SQLSTATISTICS,&supported)<0) {
printf("SQLGetFunctions failed.\n"); }
else {
if (!supported) {
printf("SQLStatistics is not supported.\n"); }
else {
printf("SQLStatistics is supported.\n");
SQLDisconnect(...);
SQLFreeHandle(SQL_HANDLE_DBC,...);
SQLFreeHandle(SQL_HANDLE_ENV,...);
ODBC: The SQLGetFunctions
function has been around since ODBC
version 1.0. The third parameter, *Supported
, can be a pointer to an array.
SQLGetInfo¶
Function Prototype:
SQLRETURN SQLGetInfo(
SQLHDBC hdbc, /* 32-bit input */
SQLSMALLINT InfoType, /* 16-bit input */
SQLPOINTER InfoValue, /* pointer to ANY* output */
SQLINTEGER BufferLength, /* 32-bit input */
SQLINTEGER *StringLength /* pointer to 32-bit output */
);
Job: Ask whether a DBMS supports a specified feature, and if it does, which of several possible syntax variations the DBMS uses.
The SQLGetInfo
function’s InfoType
parameter has 47 possible values,
which we’ll describe in the following paragraphs. In what follows, each
paragraph begins with a value (the InfoType
value), a name (the #define
of this value in sqlcli.h
) and the <data type> of the value that
SQLGetInfo
returns, followed by a few remarks.
24 SQL_ACCESSIBLE_ROUTINES -- CHAR(1)
The result is ‘Y
’ if
routines metadata – such as the rows in
INFORMATION_SCHEMA.ROUTINES
– is accessible only to users who hold EXECUTE
Privileges on routines; otherwise the result is ‘N
’. In ODBC, this code does
not exist; 24
is the code for SQL_CURSOR_ROLLBACK_BEHAVIOR
.
19 SQL_ACCESSIBLE_TABLES -- CHAR(1)
The result is ‘Y
’ if Tables metadata – such as the rows inINFORMATION_SCHEMA.TABLES
– is accessible only to users who holdSELECT
Privileges on Tables; otherwise the result is ‘N
’. A standard DBMS should return ‘N
’, since access toINFORMATION_SCHEMA
Views is possible if you hold any Privilege, not just theSELECT
Privilege. This code determines the operation of the CLI Catalog functions:SQLColumnPrivileges
,SQLColumns
,SQLForeignKeys
,SQLPrimaryKeys
,SQLResultSetStructure
,SQLSpecialColumns
,SQLTablePrivileges
,SQLTables
. In ODBC, this code exists, but the meaning is different.86 SQL_ALTER_TABLE -- INTEGER
The return is a bit map: one bit on for eachALTER TABLE
clause the DBMS supports:If
ALTER TABLE ... ADD COLUMN
:0001 hex (SQL_AT_ADD_COLUMN)
If
ALTER TABLE ... DROP COLUMN
:0002 hex (SQL_AT_DROP_COLUMN)
If
ALTER TABLE ... ALTER COLUMN
:0004 hex (SQL_AT_ALTER_COLUMN)
If
ALTER TABLE ... ADD CONSTRAINT
:0008 hex (SQL_AT_ADD_CONSTRAINT)
If
ALTER TABLE ... DROP CONSTRAINT
:0010 hex (SQL_AT_DROP_CONSTRAINT)
Any SQL-92 DBMS must return 001b hex
(all bits except ALTER COLUMN
on). Any SQL3 DBMS must return 001f hex
(all bits on). In ODBC, this
code exists but the meaning is different.
10003 SQL_CATALOG_NAME -- CHAR(1)
The return is ‘Y
’ if the DBMS supports <Catalog name>s (as qualifiers, presumably); ‘N
’ if not. Any SQL-92 DBMS must return ‘Y
’.10004 SQL_COLLATING_SEQUENCE -- CHAR(254)
The return is the <identifier> of “the default Collation of [the server]” – which is ambiguous. Probably it’s the <identifier> of the default Collation of thedbc
's default Character set – which is useless. If you want the Schema’s Character set,SELECT
fromINFORMATION_SCHEMA.SCHEMATA
. If you want the Collation of a Base table’s Column,SELECT
fromINFORMATION_SCHEMA.COLUMNS
. If you want the Collation of a result set Column, call theSQLGetDescField
function. In ODBC, the designation for this code isSQL_COLLATION_SEQ
, and “ISO 8859-1
” or “EBCDIC
” are possible returns.23 SQL_CURSOR_COMMIT_BEHAVIOR -- SMALLINT
The return is a bit map, with one bit on, determined by what actions the DBMS takes whenCOMMIT
happens:[close Cursor, delete prepared statements]
DELETE
:0000 hex (SQL_CB_DELETE)
[close Cursor, keep prepared statements]
CLOSE
:0001 hex (SQL_CB_CLOSE)
[keep Cursor open, keep prepared statements]
PRESERVE
:0002 hex (SQL_CB_PRESERVE)
A standard SQL DBMS should return
0000 hex (SQL_CB_DELETE)
.
XXX CURSOR HOLDABLE -- XXX
The return is1
(SQL_HOLDABLE
) if the DBMS supports holdable Cursors; otherwise it is0
(SQL_NONHOLDABLE
).10001 SQL_CURSOR_SENSITIVITY -- INTEGER
The return is a bit map, with zero or more bits on, determined by the DBMS’s behaviour when rows are updated outside the Cursor:[don’t see rows updated during same transaction]:
0001 hex (SQL_INSENSITIVE)
[see rows updated during same transaction]:
0002 hex (SQL_SENSITIVE)
[can’t tell whether we see them or not]:
0000 hex (SQL_UNSPECIFIED) or 0000 hex (SQL_ASENSITIVE)
2 SQL_DATA_SOURCE_NAME -- CHAR(128)
The return is the name of a data source (in client/server terms: a server name). This is the name that was passed in theSQLConnect
call.25 SQL_DATA_SOURCE_READ_ONLY -- CHAR(1)
The return is ‘Y
’ if the data source (in client/server terms: the server) cannot allow data to be “modified” – an undefined word. Presumably, the meaning is: every transaction begins with the implicit statementSET TRANSACTION READ ONLY
.17 SQL_DBMS_NAME -- CHAR(254)
The return is the name of the DBMS. It’s implementation-defined, but one can assume that there will be a vendor name here. Thesqlcli.h
file does not containSQL_DBMS_NAME
.18 SQL_DBMS_VERSION -- CHAR(254)
The return is the version number of the DBMS, in a rigid format:nn.nn.nnnn
[optional description], wheren
is any decimal digit. Examples: “00.00.0000
”, “01.02.03 Vendor X's Version #1 Release #2 Patch #3
”. In ODBC, the name isSQL_DBMS_VER
.26 SQL_DEFAULT_TRANSACTION_ISOLATION -- INTEGER
The return is a bitmask, with one bit on for the default transaction isolation level – that is, what the transaction isolation level is if you can’t executeSET TRANSACTION ISOLATION LEVEL {READ COMMITTED | READ UNCOMMITTED | REPEATABLE READ | SERIALIZABLE}
. The possible values are:0001 hex (SQL_TXN_READ_UNCOMMITTED) 0002 hex (SQL_TXN_READ_COMMITTED) 0004 hex (SQL_TXN_REPEATABLE_READ) 0008 hex (SQL_TXN_SERIALIZABLE)
A standard DBMS should return
SQL_TXN_SERIALIZABLE
.10002 SQL_DESCRIBE_PARAMETER -- CHAR(1)
The return is ‘Y
’ if the DBMS is capable of “describing dynamic parameters” – which is ambiguous. Apparently, the return has nothing to do with the DBMS’s ability to support “auto-populate of IPD” or the non-standardSQLDescribeParameter
function. Apparently, all DBMSs which support the embedded SQLDESCRIBE INPUT
statement should return ‘Y
’; otherwise they should return ‘N
’.8 SQL_FETCH_DIRECTION -- INTEGER
The return is a bitmask, with zero or more bits on, depending on the options one can use with theSQLFetchScroll
function. The possible values are:0001 hex (SQL_FD_FETCH_NEXT) 0002 hex (SQL_FD_FETCH_FIRST) 0004 hex (SQL_FD_FETCH_LAST) 0008 hex (SQL_FD_FETCH_PRIOR) 0010 hex (SQL_FD_FETCH_ABSOLUTE) 0020 hex (SQL_FD_FETCH_RELATIVE)
A standard DBMS should return
003f hex
– that is, all bits on.81 SQL_GETDATA_EXTENSIONS -- INTEGER
The return is a bitmask, with zero or more bits on, depending on the DBMS’s ability to handle out-of-orderSQLGetData
calls. Minimally, a DBMS allowsSQLGetData
only for Columns that were not bound withSQLBindCol
, and only in sequence (that is, after getting information for Columnn
, you can only get information for Columnn+1
). The possible options are:[if you can call
SQLGetData
for bound Columns]:0001 hex (SQL_GD_ANY_COLUMN)
[if you can call
SQLGetData
in any order]:0002 hex (SQL_GD_ANY_ORDER)
20000 SQL_GETPARAMDATA_EXTENSIONS -- INTEGER
The return is a bitmask, with zero or more bits on, depending on the DBMS’s ability to handle out-of-orderSQLGetParamData
calls. Minimally, a DBMS allowsSQLGetParamData
only for Columns that were not bound, and only in sequence (that is, after getting information for parametern
you can only get information for parametern+1
). The possible options are:[if you can call
SQLGetParamData
for bound Columns]:0001 hex (SQL_GPD_ANY_COLUMN)
[if you can call
SQLGetParamData
in any order]:0002 hex (SQL_GPD_ANY_ORDER)
Compare this with
SQL_GETDATA_EXTENSIONS
.
28 SQL_<identifier>_CASE -- SMALLINT
Returns a number between1
and4
, depending how the DBMS stores <regular identifier>s. The possible options are:[change to upper case]:
1 (SQL_IC_UPPER)
[change to lower case]:
2 (SQL_IC_LOWER)
[don’t change case]:
3 (SQL_IC_SENSITIVE)
[don’t change case, but do case-insensitive searches]:
4 (SQL_IC_MIXED)
A standard DBMS should always return
SQL_IC_UPPER
, since only <delimited identifier>s are stored in mixed case.
73 SQL_INTEGRITY -- CHAR(1) The return is '``Y
’ if the DBMS supports basic integrity Constraints:NOT NULL
,UNIQUE
,PRIMARY KEY
,FOREIGN KEY ... NO ACTION
,CHECK
and Column defaults. Otherwise the return is ‘N
’. A standard DBMS should return ‘Y
’. In ODBC, code73
isSQL_OPT_IEF
, and the return is ‘Y
’ if the DBMS supports the optional integrity enhancement facility of SQL-89.34 SQL_MAXIMUM_CATALOG_NAME_LENGTH -- SMALLINT
The return is the length, in characters, of the largest possible <Catalog name>, without qualifiers or introducers. Expect 18 for an SQL-89 DBMS, 128 for a later DBMS.30 SQL_MAXIMUM_COLUMN_NAME_LENGTH -- SMALLINT
The return is the length, in characters, of the largest possible <Column name>, without qualifiers or introducers. Expect 18 for an SQL-89 DBMS, 128 for a later DBMS.97 SQL_MAXIMUM_COLUMNS_IN_GROUP_BY -- SMALLINT
The return is the largest number of Columns that aGROUP BY
clause can hold (zero if that’s unknown or unlimited). Expect 6 for a DBMS that meets the FIPS 127-2 entry-level spec, 15 for a DBMS that meets the FIPS 127-2 intermediate-level spec.99 SQL_MAXIMUM_COLUMNS_IN_ORDER_BY -- SMALLINT
The return is the largest number of Columns that anORDER BY
clause can hold (zero if that’s unknown or unlimited). Expect 6 for a DBMS that meets the FIPS 127-2 entry-level spec, 15 for a DBMS that meets the FIPS 127-2 intermediate-level spec.100 SQL_MAXIMUM_COLUMNS_IN_SELECT -- SMALLINT
The return is the largest number of Columns that a select list can hold (zero if that’s unknown or unlimited). Expect 100 for a DBMS that meets the FIPS 127-2 entry-level spec, 250 for a DBMS that meets the FIPS 127-2 intermediate-level spec.101 SQL_MAXIMUM_COLUMNS_IN_TABLE -- SMALLINT
The return is the largest number of Columns that a Base table can hold (zero if that’s unknown or unlimited). Expect 100 for a DBMS that meets the FIPS 127-2 entry-level spec, 250 for a DBMS that meets the FIPS 127-2 intermediate-level spec.1 SQL_MAXIMUM_CONCURRENT_ACTIVITIES -- SMALLINT
The return is the largest number ofstmt
s that can be active at the same time. With some implementations, it might be possible to allocate twostmt
s, i.e.: callSQLAllocHandle(SQL_HANDLE_STMT,...)
twice, but impossible to “select” with bothhstmt#1
andhstmt#2
. The return is zero if maximum concurrent activities is unknown. (Astmt
is “active” if it is associated with an open Cursor or a deferred parameter.)31 SQL_MAXIMUM_CURSOR_NAME_LENGTH -- SMALLINT
The return is the length, in characters, of the largest possible <Cursor name>, without qualifiers or introducers. Expect 18 for an SQL-89 DBMS, 128 for a later DBMS.0 SQL_MAXIMUM_DRIVER_CONNECTIONS -- SMALLINT
The return is the maximum number of connections between one driver and one server, or the maximum number of connections period, or zero if the maximum is not fixed.10005 SQL_MAXIMUM_<identifier>_LENGTH -- SMALLINT
The return is the length, in characters, of the largest possible <identifier> for any kind of Object. This value won’t be greater than any of theSQL_MAXIMUM_..._NAME_LENGTH
values. Expect 18 for an SQL-89 DBMS, 128 for a later DBMS.32 SQL_MAXIMUM_SCHEMA_NAME_LENGTH -- SMALLINT
The return is the length, in characters, of the largest possible <Schema name>, without qualifiers or introducers. Expect 18 for an SQL-89 DBMS, 128 for a later DBMS.20000 SQL_MAXIMUM_STMT_OCTETS -- SMALLINT
<< XXX the number is wrong, 20000 isSQL_GETPARAMDATA_EXTENSIONS
>> The return is the maximum number of octets that can exist in any SQL statement, or zero if there’s no fixed limit. This is the maximum size of the string parameter in anSQLPrepare
orSQLExecDirect
function call. In ODBC, this code does not exist; the ODBC codeSQL_MAXIMUM_STATEMENT_LENGTH
is a different value.20001 SQL_MAXIMUM_STMT_OCTETS_DATA -- SMALLINT
The return is the maximum number of octets that can exist in an SQL-data statement (such asINSERT
), or zero if there’s no fixed limit.20002 SQL_MAXIMUM_STMT_OCTETS_SCHEMA -- SMALLINT
The return is the maximum number of octets that can exist in an SQL-Schema statement (such asCREATE SCHEMA
), or zero if there’s no fixed limit.35 SQL_MAXIMUM_TABLE_NAME_LENGTH -- SMALLINT
The return is the length, in characters, of the largest possible <Table name>, without qualifiers or introducers. Expect 18 for an SQL-89 DBMS, 128 for a later DBMS. But don’t be surprised if it’s smaller: many implementations treat <Table name> as “file name”, and are therefore subject to whatever constraints the operating system imposes.106 SQL_MAXIMUM_TABLES_IN_SELECT -- SMALLINT
The return is the maximum number of <Table name>s which may appear in a query’sFROM
clause – that is, afterSELECT ... FROM
. This will be less than or equal to the maximum number of joins, and will be less than or equal to the maximum number of <Table reference>s in an SQL statement as a whole, after Views are expanded. A FIPS entry-level DBMS would return 15 for the maximum number of <Table reference>s in an SQL statement, a FIPS intermediate-level DBMS would return 50.107 SQL_MAXIMUM_USER_NAME_LENGTH -- SMALLINT
The return is the length, in characters, of the largest possible <AuthorizationID>, without introducers or qualifiers. The value is the same as the contents ofSESSION_USER
. Expect 18 from an SQL-89 or FIPS 127-2 entry level DBMS, expect 128 from a more powerful DBMS – unless the DBMS gets <AuthorizationID>s from an outside source, such as the operating system’s login name. In that case, the limit ultimately depends on what the operating system says.85 SQL_NULL_COLLATION -- SMALLINT
Returns a number between 1 and 2, depending on the placement ofNULL
values in sort sequences (ORDER BY
). The possible options are:[treat
NULL
s as “greater than” all other values]:1 (SQL_NC_HIGH)
[treat
NULL
s as “less than” all other values]:2 (SQL_NC_LOW)
90 SQL_ORDER_BY_COLUMNS_IN_SELECT -- CHAR(1)
Returns ‘Y
’ if the DBMS allows only thoseORDER BY
Columns which also appear in the select list; otherwise ‘N
’. For example:SELECT column_1 FROM Table_1 ORDER BY column_2;
is illegal in SQL-92 (so an SQL-92 DBMS would return ‘Y
’), but is legal in SQL3.115 SQL_OUTER_JOIN_CAPABILITIES -- INTEGER
(NotCHAR(1)
, there was an error in early versions of the SQL Standard.) The return is a bitmask, with zero or more bits on, depending on the outer join variations that the DBMS supports. The possible options are:[simple LEFT OUTER JOIN]:
0001 hex (SQL_OUTER_JOIN_LEFT)
[simple RIGHT OUTER JOIN]:
0002 hex (SQL_OUTER_JOIN_RIGHT)
[FULL OUTER JOIN works]:
0004 hex(SQL_OUTER_JOIN_FULL)
[outer joins may be nested]:
0008 hex(SQL_OUTER_JOIN_NESTED)
[ON-clause Columns needn’t be in Table order]:
0010 hex (SQL_OUTER_JOIN_NOT_ORDERED)
[inner Table can be INNER JOIN]:
0020 hex (SQL_OUTER_JOIN_INNER)
[ON predicate needn’t be “=” comparison]:
0040 hex (SQL_OUTER_JOIN_ALL_COMPARISON_OPS)
20003 SQL_REF_LENGTH -- SMALLINT
The return is the length, in octets, of a <reference type>43 SQL_SCROLL_CONCURRENCY -- INTEGER
The return is a bitmask, with zero or more bits on, depending on the DBMS’s ability to handle concurrency (multi-user) problems while dealing with scroll Cursors. The possible options are:[read-only scrollable Cursors are okay]:
0001 hex (SQL_SCCO_READ_ONLY)
[updatable scrollable Cursors are okay in conjunction with lowest locking level]:
0002 hex (SQL_SCCO_LOCK)
[updatable scrollable Cursors are okay in conjunction with optimistic concurrency – row <identifier>s or timestamps]:
0004 hex SQL_SCCO_OPT_ROWVER)
[updatable scrollable Cursors are okay in conjunction with optimistic concurrency – comparing values]:
0008 hex (SQL_SCCO_OPT_VALUES)
14 SQL_SEARCH_PATTERN_ESCAPE -- CHAR(1)
The return is the fixed escape character which can be used for pattern matching in some of the CLI Catalog functions (e.g.:SQLTables
). Conceptually: if the search-pattern-escape is'~'
, then the metadata search conducted for such functions implicitly contains a clause “... LIKE ... ESCAPE '~' ...
”. In ODBC, the DBMS may return ‘’ if search-pattern escape is not supported for Catalog functions.13 SQL_SERVER_NAME -- CHAR(128)
The return is a character string: the implementation-defined character string which is the “actual name” of a server. This often will be the same as the string returned forSQL_DATA_SOURCE_NAME
, but some implementations make a distinction between “data source” and “server”.94 SQL_SPECIAL_CHARACTERS -- CHAR(254)
The return is a character string containing all characters “other than upper case letters, lower case letters, digits and underscore” which can appear in <regular identifier>s.Note 1: This definition has nothing to do with the SQL Standard’s definition for special characters.
Note 2: This definition is not the same as the definition ODBC uses.
Note 3: An SQL standard DBMS will return a blank string here. If you want to use strange non-alphabetic characters in names, use <delimited identifier>s.
46 SQL_TRANSACTION_CAPABLE -- SMALLINT
The return is a number indicating what sort of SQL statements the DBMS allows within a transaction. The possible options are:[transactions are not supported at all]:
0 (SQL_TC_NONE)
[DML only, DDL causes error]:
1 (SQL_TC_DML)
[DML okay, DDL okay]:
2 (SQL_TC_ALL)
[DML okay, DDL causes
COMMIT
]:3 (SQL_TC_COMMIT)
[DML okay, DDL is ignored]:
4 (SQL_TC_IGNORE)
DML stands for “data manipulation language” (
SELECT
,INSERT
, etc.); DDL stands for “data definition language” (ALTER
,DROP
,GRANT
,CREATE
,REVOKE
). This addresses one of the implementation-defined questions in standard SQL: is a DDL statement just like any other or does it have to be in a transaction of its own? Since many DBMSs will automaticallyCOMMIT
before and after a DDL statement, you can expect the most common return to beSQL_TC_COMMIT
. No standard SQL DBMS will returnSQL_TC_NONE
. In ODBC, the code name isSQL_TXN_CAPABLE
.72 SQL_TRANSACTION_ISOLATION_OPTION -- INTEGER
The return is a bitmask, with zero or more bits on, depending on the isolation levels the DBMS supports. The possible options are:[supports
READ UNCOMMITTED
level]:0001 hex (SQL_TRANSACTION_READ_UNCOMMITTED)
[supports
READ COMMITTED
level]:0002 hex (SQL_TRANSACTION_READ_COMMITTED)
[supports
REPEATABLE READ
level]:0004 hex (SQL_TRANSACTION_REPEATABLE_READ)
[supports
SERIALIZABLE
level]:0008 hex (SQL_TRANSACTION_SERIALIZABLE)
Standard SQL DBMSs will at least return
SQL_TRANSACTION_SERIALIZABLE
, sinceSERIALIZABLE
must be the default isolation level. Standard SQL DBMSs will allow all four options inSET TRANSACTION
statements, but it’s implementation-defined whether a DBMS can in fact go to a higher level. For instance, the DBMS may respond to aSET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
request by setting the isolation level toSERIALIZABLE
, a higher level. In ODBC, the code name isSQL_TXN_ISOLATION_OPTION
.47 SQL_USER_NAME -- CHAR(128)
The return is a character string which is the same valueCURRENT_USER
function.
Algorithm:
If (hdbc is not a handle of a dbc)
return error: CLI-specific condition-invalid handle
If (dbc is not connected)
return error: 08003 connection exception-connection does not exist
Empty the dbc's diagnostics area.
If (InfoType not a valid code)
return error: HY096 CLI-specific condition-invalid information type
Notes:
You want to write a portable DBMS application? Then you have to keep asking yourself: does every DBMS support the feature(s) you’re using, in the way you use them? Hint: the answer is no. We’ve come a long way in the last few years, and the support for “standard SQL” is a lot better than it once was. But there are always DBMSs behind the curve, and always applications that push the envelope. The
SQLGetInfo
function is designed to provide information for the most common questions and unresolved issues.Many
SQLGetInfo
variants ask about non-standard features or non-standard behaviour. If you know that your DBMS is completely standard, then you shouldn’t have to ask these questions.
Example: In this code snippet we will use the four main types of
SQLGetInfo
returns: to a smallint, to a bitmask, to a CHAR(1)
string
and to a long string. We assume that SQLConnect
has happened already.
#include "sqlcli.h"
...
SQLSMALLINT max_columns;
char y_or_n ## [2]:
;
SQLSMALLINT fd;
CHAR server_name ## [129]:
;
SQLINTEGER server_name_size;
...
SQLGetInfo(hdbc,SQL_ORDER_BY_COLUMNS_IN_SELECT,y_or_n,2,NULL);
if (y_or_n ## [0]:
=='Y')
/* order-by Columns must be in the select list */;
SQLGetInfo(hdbc,SQL_MAXIMUM_COLUMNS_IN_TABLE,&max_columns,NULL,NULL);
if (max_columns > 10)
/* more than 10 Columns are allowed in a select list * */
SQLGetInfo(hdbc,SQL_FETCH_DIRECTION,&fdirection,NULL,NULL);
if ( fetchdirection & FD_FETCH_ABSOLUTE)
/* SQLFetchScroll can be done with FETCH ABSOLUTE */;
SQLGetInfo(hdbc,SQL_SERVER_NAME,server_name,129,&server_name_size);
if (server_name_size>0) {
/* server_name has the name of a server, null-terminated. */;
ODBC: The SQLGetInfo
function has been around since ODBC 1.0.
Compare the ODBC prototype for SQLGetInfo
with the standard SQL prototype:
ODBC Standard SQL
SQLRETURN SQLGetInfo( SQLRETURN SQLGetInfo(
SQLHDBC hdbc, SQLHDBC hdbc,
SQLSMALLINT InfoType, SQLSMALLINT InfoType,
SQLPOINTER InfoValue, SQLPOINTER InfoValue,
SQLSMALLINT BufferLength, SQLINTEGER BufferLength,
SQLSMALLINT *StringLength SQLINTEGER *StringLength
); );
The types are incompatible! This will probably be fixed by the time you read this – check this book’s web site to see how the matter was resolved.
And that’s it for the CLI general functions. In the next chapter, we’ll take a look at the deferred parameter functions.