Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve capabilities reporting #64

Merged
merged 9 commits into from
Nov 21, 2018
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,16 @@ Required packages:

* MSBuild
- as the build tool;
* Windows SDK for UWP: C++
- for the CRT headers;
* Windows 10 SDK
- headers and libraries;
* VC++ toolset
- for the compiler;
* C++/CLI support
- for the command line environment and building.
- for the DSN editor C to C# CLI binding;
* C# support
- for the DSN editor C# form;
* F# support
- for the MSI packaging.

Optional packages:

Expand Down
4 changes: 0 additions & 4 deletions build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ REM
if [%BUILD_DIR%] == [] (
SET BUILD_DIR=%SRC_PATH%\builds
)
if not [%ESODBC_LOG_DIR%] == [] (
REM Strip the log level, if any present (format: path?level)
for /f "tokens=1 delims=?" %%a in ("%ESODBC_LOG_DIR%") do set LOGGING_DIR=%%a
)

REM
REM Perform the building steps
Expand Down
135 changes: 124 additions & 11 deletions driver/catalogue.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,59 @@
" CATALOG " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM


static SQLRETURN fake_answer(SQLHSTMT hstmt, const char *src, size_t cnt)
{
char *dup;

if (! (dup = strdup(src))) {
ERRNH(hstmt, "OOM with %zu.", cnt);
RET_HDIAGS(hstmt, SQL_STATE_HY001);
}
return attach_answer(STMH(hstmt), dup, cnt);

}

SQLRETURN EsSQLStatisticsW(
SQLHSTMT hstmt,
_In_reads_opt_(cchCatalogName) SQLWCHAR *szCatalogName,
SQLSMALLINT cchCatalogName,
_In_reads_opt_(cchSchemaName) SQLWCHAR *szSchemaName,
SQLSMALLINT cchSchemaName,
_In_reads_opt_(cchTableName) SQLWCHAR *szTableName,
SQLSMALLINT cchTableName,
SQLUSMALLINT fUnique,
SQLUSMALLINT fAccuracy)
{
/*INDENT-OFF*/
# define STATISTICS_EMPTY \
"{" \
"\"columns\":[" \
"{\"name\":\"TABLE_CAT\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"TABLE_SCHEM\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"TABLE_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"NON_UNIQUE\"," "\"type\":\"SHORT\"}," \
"{\"name\":\"INDEX_QUALIFIER\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"INDEX_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"TYPE\"," "\"type\":\"SHORT\"}," \
"{\"name\":\"ORDINAL_POSITION\"," "\"type\":\"SHORT\"}," \
"{\"name\":\"COLUMN_NAME \"," "\"type\":\"TEXT\"}," \
"{\"name\":\"ASC_OR_DESC\"," "\"type\":\"BYTE\"}," \
"{\"name\":\"CARDINALITY\"," "\"type\":\"INTEGER\"}," \
"{\"name\":\"PAGES\"," "\"type\":\"INTEGER\"}," \
"{\"name\":\"FILTER_CONDITION\"," "\"type\":\"TEXT\"}" \
"]," \
"\"rows\":[]" \
"}"
/*INDENT-ON*/

INFOH(hstmt, "no statistics available.");
return fake_answer(hstmt, STATISTICS_EMPTY,
sizeof(STATISTICS_EMPTY) - /*\0*/1);

# undef STATISTICS_EMPTY
}


/* writes into 'dest', of size 'room', the current catalog of 'dbc'.
* returns negative on error, or the char count written otherwise */
SQLSMALLINT copy_current_catalog(esodbc_dbc_st *dbc, SQLWCHAR *dest,
Expand Down Expand Up @@ -466,11 +519,29 @@ SQLRETURN EsSQLSpecialColumnsW
SQLUSMALLINT fNullable
)
{
// TODO: is there a "rowid" equivalent: ID uniquely a ROW in the table?
// or unique indexes equivalents
WARNH(hstmt, "no special columns available.");
STMT_FORCE_NODATA(STMH(hstmt));
return SQL_SUCCESS;
/*INDENT-OFF*/
# define SPECIAL_COLUMNS_EMPTY \
"{" \
"\"columns\":[" \
"{\"name\":\"SCOPE\"," "\"type\":\"SHORT\"}," \
"{\"name\":\"COLUMN_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"DATA_TYPE\"," "\"type\":\"SHORT\"}," \
"{\"name\":\"TYPE_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"COLUMN_SIZE\"," "\"type\":\"INTEGER\"}," \
"{\"name\":\"BUFFER_LENGTH\"," "\"type\":\"INTEGER\"}," \
"{\"name\":\"DECIMAL_DIGITS\"," "\"type\":\"SHORT\"}," \
"{\"name\":\"PSEUDO_COLUMN\"," "\"type\":\"SHORT\"}" \
"]," \
"\"rows\":[]" \
"}"
/*INDENT-ON*/


INFOH(hstmt, "no special columns available.");
return fake_answer(hstmt, SPECIAL_COLUMNS_EMPTY,
sizeof(SPECIAL_COLUMNS_EMPTY) - /*\0*/1);

# undef SPECIAL_COLUMNS_EMPTY
}


Expand All @@ -489,9 +560,34 @@ SQLRETURN EsSQLForeignKeysW(
_In_reads_opt_(cchFkTableName) SQLWCHAR *szFkTableName,
SQLSMALLINT cchFkTableName)
{
WARNH(hstmt, "no foreign keys supported.");
STMT_FORCE_NODATA(STMH(hstmt));
return SQL_SUCCESS;
/*INDENT-OFF*/
# define FOREIGN_KEYS_EMPTY \
"{" \
"\"columns\":[" \
"{\"name\":\"PKTABLE_CAT\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"PKTABLE_SCHEM\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"PKTABLE_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"PKCOLUMN_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"FKTABLE_CAT\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"FKTABLE_SCHEM\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"FKTABLE_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"FKCOLUMN_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"KEY_SEQ\"," "\"type\":\"SHORT\"}," \
"{\"name\":\"UPDATE_RULE\"," "\"type\":\"SHORT\"}," \
"{\"name\":\"DELETE_RULE\"," "\"type\":\"SHORT\"}," \
"{\"name\":\"FK_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"PK_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"DEFERRABILITY\"," "\"type\":\"SHORT\"}" \
"]," \
"\"rows\":[]" \
"}"
/*INDENT-ON*/

INFOH(hstmt, "no foreign keys supported.");
return fake_answer(hstmt, FOREIGN_KEYS_EMPTY,
sizeof(FOREIGN_KEYS_EMPTY) - /*\0*/1);

# undef FOREIGN_KEYS_EMPTY
}

SQLRETURN EsSQLPrimaryKeysW(
Expand All @@ -503,9 +599,26 @@ SQLRETURN EsSQLPrimaryKeysW(
_In_reads_opt_(cchTableName) SQLWCHAR *szTableName,
SQLSMALLINT cchTableName)
{
/*INDENT-OFF*/
# define PRIMARY_KEYS_EMPTY \
"{" \
"\"columns\":[" \
"{\"name\":\"TABLE_CAT\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"TABLE_SCHEM\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"TABLE_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"COLUMN_NAME\"," "\"type\":\"TEXT\"}," \
"{\"name\":\"KEY_SEQ\"," "\"type\":\"SHORT\"}," \
"{\"name\":\"PK_NAME\"," "\"type\":\"TEXT\"}" \
"]," \
"\"rows\":[]" \
"}"
/*INDENT-ON*/

INFOH(hstmt, "no primary keys supported.");
STMT_FORCE_NODATA(STMH(hstmt));
return SQL_SUCCESS;
return fake_answer(hstmt, PRIMARY_KEYS_EMPTY,
sizeof(PRIMARY_KEYS_EMPTY) - /*\0*/1);

# undef PRIMARY_KEYS_EMPTY
}

/* vim: set noet fenc=utf-8 ff=dos sts=0 sw=4 ts=4 : */
/* vim: set noet fenc=utf-8 ff=dos sts=0 sw=4 ts=4 tw=78 : */
12 changes: 11 additions & 1 deletion driver/catalogue.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ SQLSMALLINT copy_current_catalog(esodbc_dbc_st *dbc, SQLWCHAR *dest,
SQLSMALLINT room);


SQLRETURN EsSQLStatisticsW(
SQLHSTMT hstmt,
_In_reads_opt_(cchCatalogName) SQLWCHAR *szCatalogName,
SQLSMALLINT cchCatalogName,
_In_reads_opt_(cchSchemaName) SQLWCHAR *szSchemaName,
SQLSMALLINT cchSchemaName,
_In_reads_opt_(cchTableName) SQLWCHAR *szTableName,
SQLSMALLINT cchTableName,
SQLUSMALLINT fUnique,
SQLUSMALLINT fAccuracy);
SQLRETURN EsSQLTablesW(
SQLHSTMT StatementHandle,
_In_reads_opt_(NameLength1) SQLWCHAR *CatalogName,
Expand Down Expand Up @@ -80,4 +90,4 @@ SQLRETURN EsSQLPrimaryKeysW(
#endif /* __CATALOGUE_H__ */


/* vim: set noet fenc=utf-8 ff=dos sts=0 sw=4 ts=4 : */
/* vim: set noet fenc=utf-8 ff=dos sts=0 sw=4 ts=4 tw=78 : */
31 changes: 28 additions & 3 deletions driver/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -2056,7 +2056,7 @@ SQLRETURN EsSQLSetConnectAttrW(
INFOH(dbc, "no ANSI/Unicode specific behaviour (app is: %s).",
(uintptr_t)Value == SQL_AA_TRUE ? "ANSI" : "Unicode");
//state = SQL_STATE_IM001;
return SQL_ERROR; /* error means ANSI */
return SQL_ERROR; /* error means same ANSI/Unicode behavior */

/* https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/automatic-population-of-the-ipd */
case SQL_ATTR_AUTO_IPD:
Expand Down Expand Up @@ -2128,6 +2128,7 @@ SQLRETURN EsSQLSetConnectAttrW(
break;

case SQL_ATTR_CONNECTION_DEAD:
/* read only attribute */
RET_HDIAGS(dbc, SQL_STATE_HY092);
break;

Expand All @@ -2152,6 +2153,14 @@ SQLRETURN EsSQLSetConnectAttrW(
ERRH(dbc, "no traslation support available.");
RET_HDIAGS(dbc, SQL_STATE_IM009);

case SQL_ATTR_CURRENT_CATALOG:
DBGH(dbc, "setting current catalog to: `" LWPDL "`.",
/* string should be 0-term'd */
0 <= StringLength ? StringLength : SHRT_MAX,
(SQLWCHAR *)Value);
ERRH(dbc, "setting catalog name not supported.");
RET_HDIAGS(dbc, SQL_STATE_HYC00);

case SQL_ATTR_TRACE:
case SQL_ATTR_TRACEFILE: /* DM-only */
case SQL_ATTR_ENLIST_IN_DTC:
Expand All @@ -2161,8 +2170,17 @@ SQLRETURN EsSQLSetConnectAttrW(
ERRH(dbc, "unsupported attribute %ld.", Attribute);
RET_HDIAGS(dbc, SQL_STATE_HYC00);

#ifndef NDEBUG
/* MS Access/Jet proprietary info type */
case 30002:
ERRH(dbc, "unsupported info type.");
RET_HDIAGS(DBCH(ConnectionHandle), SQL_STATE_HY092);
#endif

default:
ERRH(dbc, "unknown Attribute: %d.", Attribute);
// FIXME: add the other attributes
FIXME;
RET_HDIAGS(dbc, SQL_STATE_HY092);
}

Expand Down Expand Up @@ -2270,14 +2288,21 @@ SQLRETURN EsSQLGetConnectAttrW(
ERRH(dbc, "unsupported attribute %ld.", Attribute);
RET_HDIAGS(dbc, SQL_STATE_HY000);

#ifndef NDEBUG
/* MS Access/Jet proprietary info type */
case 30002:
ERRH(dbc, "unsupported info type.");
RET_HDIAGS(DBCH(ConnectionHandle), SQL_STATE_HY092);
#endif

default:
ERRH(dbc, "unknown Attribute type %ld.", Attribute);
// FIXME: add the other attributes
FIXME;
ERRH(dbc, "unknown Attribute type %d.", Attribute);
RET_HDIAGS(DBCH(ConnectionHandle), SQL_STATE_HY092);
}

return SQL_SUCCESS;
}

/* vim: set noet fenc=utf-8 ff=dos sts=0 sw=4 ts=4 : */
/* vim: set noet fenc=utf-8 ff=dos sts=0 sw=4 ts=4 tw=78 : */
12 changes: 10 additions & 2 deletions driver/convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,15 @@ static inline void write_out_octets(
DBGH(stmt, "length of data available for transfer: %ld", *octet_len_ptr);
}

/* if an application doesn't specify the conversion, use column's type */
/*
* If an application doesn't specify the conversion, use column's type.
*
* Note: in case the ARD binds a SQL_C_DEFAULT, the driver won't check the
* size of the bound buffer for fixed types: "SQLFetch never truncates data
* converted to fixed-length data types; it always assumes that the length of
* the data buffer is the size of the data type."
* TODO: accommodate apps that do?
*/
static inline SQLSMALLINT get_rec_c_type(esodbc_rec_st *arec,
esodbc_rec_st *irec)
{
Expand Down Expand Up @@ -2890,4 +2898,4 @@ SQLRETURN c2sql_varchar(esodbc_rec_st *arec, esodbc_rec_st *irec,
}


/* vim: set noet fenc=utf-8 ff=dos sts=0 sw=4 ts=4 : */
/* vim: set noet fenc=utf-8 ff=dos sts=0 sw=4 ts=4 tw=78 : */
21 changes: 20 additions & 1 deletion driver/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,28 @@
* respect yet (ex., see CURRENT_ functions). */
#define ESODBC_SQL_CONFORMANCE SQL_SC_SQL92_ENTRY
/* Driver conformance level: CORE.
* No scrollabe cursors et al. just yet */
* No scrollabe cursors et al. just yet.
* https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/interface-conformance-levels
*/
#define ESODBC_ODBC_INTERFACE_CONFORMANCE SQL_OIC_CORE
#define ESODBC_GETDATA_EXTENSIONS (0 | \
SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND)

/*
* Deprecated info types.
*/
#define ESODBC_FETCH_DIRECTION SQL_FD_FETCH_NEXT
#define ESODBC_POS_OPERATIONS 0L
#define ESODBC_LOCK_TYPES 0L
#define ESODBC_POSITIONED_STATEMENTS 0L
/* equivalent to ESODBC_ODBC_INTERFACE_CONFORMANCE above */
#define ESODBC_ODBC_API_CONFORMANCE SQL_OAC_LEVEL1
#define ESODBC_SCROLL_CONCURRENCY SQL_SCCO_READ_ONLY
/* equivalent to ESODBC_SQL_CONFORMANCE above */
#define ESODBC_ODBC_SQL_CONFORMANCE SQL_OSC_MINIMUM
//#define ESODBC_ODBC_SQL_CONFORMANCE SQL_OSC_CORE
#define ESODBC_STATIC_SENSITIVITY 0L

/*
* Catalog support:
* - supported in: DML STATEMENTS, ODBC PROCEDURE INVOCATION.
Expand Down Expand Up @@ -403,3 +420,5 @@
#define ESODBC_ES_TO_SQL_NESTED ESODBC_SQL_NESTED

#endif /* __DEFS_H__ */

/* vim: set noet fenc=utf-8 ff=dos sts=0 sw=4 ts=4 tw=78 : */
Loading