Skip to content

Driver/data_source features detection completion #18

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

Merged
merged 4 commits into from
Aug 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,6 @@ if /i not [%ARG:setup=%] == [%ARG%] (
)


REM presence of 'fetch': invoke FETCH "function"
if /i not [%ARG:fetch=%] == [%ARG%] (
call:FETCH
)


cd %BUILD_DIR%

REM Presence of 'clearlogs': invoke CLEARLOGS "function"
Expand All @@ -104,6 +98,9 @@ REM absence of nobuild: invoke BUILD "function";
REM 'all' and 'test' arguments presence checked inside the "function".
if /i [%ARG:nobuild=%] == [%ARG%] (
call:BUILD
if ERRORLEVEL 1 (
goto END
)
) else (
echo Invoked with 'nobuild', building skipped.
)
Expand Down Expand Up @@ -342,9 +339,15 @@ REM BUILD function: build various targets
if /i not [%ARG:tests=%] == [%ARG%] (
echo Building all the project (including tests^).
MSBuild ALL_BUILD.vcxproj %MSBUILD_ARGS%
if ERRORLEVEL 1 (
goto END
)
) else if /i not [%ARG:all=%] == [%ARG%] (
echo Building all the project.
MSBuild ALL_BUILD.vcxproj %MSBUILD_ARGS%
if ERRORLEVEL 1 (
goto END
)
) else if /i not [%ARG:suiteS=%] == [%ARG%] (
echo Building the test projects only.
for %%i in (test\test_*.vcxproj) do (
Expand Down Expand Up @@ -383,8 +386,10 @@ REM BUILD function: build various targets
echo Building the driver only.
REM file name expansion, cmd style...
for /f %%i in ("%DRIVER_BASE_NAME%*.vcxproj") do MSBuild %%~nxi %MSBUILD_ARGS%

if ERRORLEVEL 0 if /i not [%ARG:exports=%] == [%ARG%] (
if ERRORLEVEL 1 (
goto END
)
if /i not [%ARG:exports=%] == [%ARG%] (
dumpbin /exports %CFG_INTDIR%\%DRIVER_BASE_NAME%*.dll
)
)
Expand Down
10 changes: 8 additions & 2 deletions driver/catalogue.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ SQLSMALLINT copy_current_catalog(esodbc_dbc_st *dbc, SQLWCHAR *dest,
SQLSMALLINT used = -1; /*failure*/
SQLLEN row_cnt;
SQLLEN ind_len = SQL_NULL_DATA;
SQLWCHAR buff[ESODBC_MAX_IDENTIFIER_LEN];
SQLWCHAR buff[ESODBC_MAX_IDENTIFIER_LEN + /*\0*/1];
wstr_st catalog;

if (! SQL_SUCCEEDED(EsSQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt))) {
Expand Down Expand Up @@ -100,6 +100,7 @@ SQLSMALLINT copy_current_catalog(esodbc_dbc_st *dbc, SQLWCHAR *dest,
catalog = (wstr_st) {
buff, ind_len
};
buff[ind_len] = L'\0'; /* write_wstr() expects the 0-term */
DBGH(dbc, "current catalog (first value returned): `" LWPDL "`.",
LWSTR(&catalog));
}
Expand Down Expand Up @@ -155,13 +156,18 @@ size_t quote_tokens(SQLWCHAR *src, size_t len, SQLWCHAR *dest)
default:
if (! copying) {
*pos ++ = L'\''; /* start a new token */
copying = TRUE;
}
copying = TRUE;
}
*pos ++ = src[i];
}
if (copying) {
*pos ++ = L'\''; /* end last token */
} else if (dest < pos && pos[-1] == L',') {
/* trim last char, if it's a comma: LibreOffice (6.1.0.3) sends the
* table type string `VIEW,TABLE,%,` having the last `,` propagated to
* EsSQL, which rejects the query */
pos --;
}
/* should not overrun */
assert(i < 2/*see typ_buf below*/ * ESODBC_MAX_IDENTIFIER_LEN);
Expand Down
48 changes: 32 additions & 16 deletions driver/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,8 @@ static SQLRETURN process_config(esodbc_dbc_st *dbc, esodbc_dsn_attrs_st *attrs)
}
n = WCS2U8(urlw, cnt, dbc->url, n);
if (! n) {
ERRNH(dbc, "failed to U8 convert URL `" LWPDL "` [%d].",cnt, urlw, cnt);
ERRNH(dbc, "failed to U8 convert URL `" LWPDL "` [%d].",cnt, urlw,
cnt);
goto err;
}
dbc->url[n] = 0;
Expand Down Expand Up @@ -583,15 +584,16 @@ void cleanup_dbc(esodbc_dbc_st *dbc)
dbc->fetch.str = NULL;
dbc->fetch.slen = 0;
}
if (dbc->dsn.str && 0 < dbc->dsn.cnt) {
if (dbc->dsn.str) {
free(dbc->dsn.str);
dbc->dsn.str = NULL;
} else {
/* small hack: the API allows querying for a DSN also in the case a
* connection actually fails to be established; in which case the
* actual DSN value hasn't been allocated/copied. */
dbc->dsn.str = MK_WPTR("");
dbc->dsn.cnt = 0;
dbc->server.str = NULL; /* both values collocated in same segment */
dbc->server.cnt = 0;
} else {
assert(! dbc->dsn.cnt);
assert(! dbc->server.cnt);
assert(! dbc->server.str);
}
if (dbc->es_types) {
free(dbc->es_types);
Expand Down Expand Up @@ -1351,6 +1353,7 @@ SQLRETURN EsSQLDriverConnectW
BOOL disable_nonconn = FALSE;
BOOL prompt_user = TRUE;
int res;
size_t cnt;

init_dsn_attrs(&attrs);

Expand Down Expand Up @@ -1474,15 +1477,23 @@ SQLRETURN EsSQLDriverConnectW
"failed to load Elasticsearch/SQL types", 0);
}

/* save the original DSN for later inquiry by app */
dbc->dsn.str = malloc((orig_dsn.cnt + /*0*/1) * sizeof(SQLWCHAR));
/* save the original DSN and (new) server name for later inquiry by app */
cnt = orig_dsn.cnt + /*\0*/1;
cnt += attrs.server.cnt + /*\0*/1;
dbc->dsn.str = malloc(cnt * sizeof(SQLWCHAR)); /* alloc for both */
if (! dbc->dsn.str) {
ERRNH(dbc, "OOM for %zdB.", (orig_dsn.cnt + 1) * sizeof(SQLWCHAR));
RET_HDIAGS(dbc, SQL_STATE_HY001);
}
dbc->dsn.str[orig_dsn.cnt] = '\0';
/* copy DSN */
wcsncpy(dbc->dsn.str, orig_dsn.str, orig_dsn.cnt);
dbc->dsn.str[orig_dsn.cnt] = L'\0';
dbc->dsn.cnt = orig_dsn.cnt;
/* copy server name */
dbc->server.str = dbc->dsn.str + orig_dsn.cnt + /*\0*/1;
wcsncpy(dbc->server.str, attrs.server.str, attrs.server.cnt);
dbc->server.str[attrs.server.cnt] = L'\0';
dbc->server.cnt = attrs.server.cnt;

/* return the final connection string */
if (szConnStrOut || pcchConnStrOut) {
Expand Down Expand Up @@ -1608,14 +1619,19 @@ SQLRETURN EsSQLSetConnectAttrW(
break;

case SQL_ATTR_TXN_ISOLATION:
DBGH(dbc, "setting transaction isolation to: %u.",
DBGH(dbc, "attempt to set transaction isolation to: %u.",
(SQLUINTEGER)(uintptr_t)Value);
dbc->txn_isolation = (SQLUINTEGER)(uintptr_t)Value;
ERRH(dbc, "no support for transactions available.");
/* the driver advertises the data source as read-only, so no
* transaction level setting should occur. If an app seems to rely
* on it, we need to switch from ignoring the action to rejecting
* it: */
//RET_HDIAGS(dbc, SQL_STATE_HYC00);
break;

default:
ERRH(dbc, "unknown Attribute: %d.", Attribute);
RET_HDIAGS(DBCH(ConnectionHandle), SQL_STATE_HY092);
RET_HDIAGS(dbc, SQL_STATE_HY092);
}

return SQL_SUCCESS;
Expand Down Expand Up @@ -1673,9 +1689,9 @@ SQLRETURN EsSQLGetConnectAttrW(
break;

case SQL_ATTR_TXN_ISOLATION:
DBGH(dbc, "requested: transaction isolation: %u.",
dbc->txn_isolation);
*(SQLUINTEGER *)ValuePtr = dbc->txn_isolation;
DBGH(dbc, "requested: transaction isolation (0).");
ERRH(dbc, "no support for transactions available.");
*(SQLUINTEGER *)ValuePtr = 0;
break;

case SQL_ATTR_ACCESS_MODE:
Expand Down
59 changes: 12 additions & 47 deletions driver/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,33 +45,18 @@
#define ESODBC_QUOTE_CHAR "\""
#define ESODBC_PATTERN_ESCAPE "\\"
#define ESODBC_CATALOG_SEPARATOR ":"
#define ESODBC_CATALOG_LOCATION SQL_CL_START /* TODO: 2x check! */
#define ESODBC_CATALOG_TERM "clusterName"
#define ESODBC_TABLE_TERM "type" // TODO: or table?
#define ESODBC_SCHEMA_TERM "schema"
#define ESODBC_MAX_SCHEMA_LEN 0
#define ESODBC_PARAM_MARKER "?"

/* max # of active statements for a connection */
#define ESODBC_MAX_CONCURRENT_ACTIVITIES 0
/* maximum identifer length */
/* TODO: review@alpha */
/* match 'keyword' ES type length */
#define ESODBC_MAX_IDENTIFIER_LEN 256
/* the following lifted/derived from ES/SQL's JdbcDatabaseMetaData.java */
/* max columns in ORDER BY; 0 - no limit / unknown */
#define ESODBC_MAX_COLUMNS_IN_ORDER_BY 0
/* max columns in GROUP BY; 0 - no limit / unknown */
#define ESODBC_MAX_COLUMNS_IN_GROUP_BY 0
/* max columns in SELECT; 0 - no limit / unknown */
#define ESODBC_MAX_COLUMNS_IN_SELECT 0
/* "if the columns in the ORDER BY clause must be in the select list" */
#define ESODBC_ORDER_BY_COLUMNS_IN_SELECT "Y"
/* "the relationship between the columns in the GROUP BY clause and the
* nonaggregated columns in the select list" */
#define ESODBC_GROUP_BY SQL_GB_NO_RELATION
/* "how the data source handles the concatenation of NULL [.] with non-NULL" */
#define ESODBC_CONCAT_NULL_BEHAVIOR SQL_CB_NULL

/* 20 = len("18446744073709551616"), 1 << (sizeof(uint64_t) * 8bits) */
#define ESODBC_PRECISION_UINT64 20
Expand Down Expand Up @@ -164,7 +149,7 @@

/*
*
* Driver/Elasticsearch capabilities
* Driver/Elasticsearch capabilities (SQLGetInfo)
*
*/

Expand All @@ -178,49 +163,30 @@
#define ESODBC_ODBC_INTERFACE_CONFORMANCE SQL_OIC_CORE
#define ESODBC_GETDATA_EXTENSIONS (0 | \
SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND)
/* Read-only queries supported only */
#define ESODBC_DATA_SOURCE_READ_ONLY "Y"
/* no support for transactions */
#define ESODBC_TXN_CAPABLE SQL_TC_NONE
/* if asked (should not happen, since TXN_CAPABLE is NONE), all transaction
* levels advertised, since read only operations are supported and no
* transactions; this would need to be updated if updating ones will be
* introduced. */
#define ESODBC_DEF_TXN_ISOLATION (0 | \
SQL_TXN_READ_UNCOMMITTED | SQL_TXN_READ_COMMITTED | \
SQL_TXN_REPEATABLE_READ | SQL_TXN_SERIALIZABLE)

/* no schema support, but accepted (=currently ignored) by driver */
#define ESODBC_SCHEMA_USAGE SQL_SU_PROCEDURE_INVOCATION
/* the server supports catalog names */
#define ESODBC_CATALOG_NAME "Y"
/*
* Catalog support:
* - supported in: DML STATEMENTS, ODBC PROCEDURE INVOCATION.
* - not supported in: TABLE/INDEX/PRIVILEGE DEFINITION.
*/
#define ESODBC_CATALOG_USAGE (0 | \
SQL_CU_DML_STATEMENTS | SQL_CU_PROCEDURE_INVOCATION)
/* identifiers are case sensitive */
#define ESODBC_QUOTED_IDENTIFIER_CASE SQL_IC_SENSITIVE
/* what's allowed in an identifier name (eg. table, column, index) except
* [a-zA-Z0-9_], accepted in a delimited specification -> all printable ASCII
* (assuming ASCII is the limitation?? TODO ), 0x20-0x7E. */
#define ESODBC_SPECIAL_CHARACTERS " !\"#$%&'()*+,-./" /*[0-9]*/ \
";<=>?@" /*[A-Z]*/ "[\\]^" /*[_]*/ "`" /*[a-z]*/ "{|}~"
/* is 'column AS name' accepted? */
#define ESODBC_COLUMN_ALIAS "Y"
/* no procedures support */
#define ESODBC_PROCEDURES "N"
/* no driver support for multiple result sets */
#define ESODBC_MULT_RESULT_SETS "N"
/* no driver support for batching */
#define ESODBC_BATCH_SUPPORT 0UL
/* no driver support array of parameters */
#define ESODBC_PARAM_ARRAY_SELECTS SQL_PAS_NO_SELECT
/* no connection pooling or distributed transactions */
#define ESODBC_DTC_TRANSITION_COST 0

/* SQLFetchScroll() and SQLSetPos() capabilities.
* TODO: NEXT, ABS, RELATIVE: pending SetPos()
* TODO: BULK_FETC: pending bookmarks */
#define ESODBC_FORWARD_ONLY_CURSOR_ATTRIBUTES1 (0 | \
SQL_CA1_NEXT | SQL_CA1_ABSOLUTE | SQL_CA1_RELATIVE | \
SQL_CA1_LOCK_NO_CHANGE | \
SQL_CA1_POS_POSITION | \
SQL_CA1_BULK_FETCH_BY_BOOKMARK )
#define ESODBC_FORWARD_ONLY_CURSOR_ATTRIBUTES2 (0 | \
SQL_CA2_READ_ONLY_CONCURRENCY | \
SQL_CA2_SIMULATE_NON_UNIQUE ) /* tho no update/delete supported */

/*
* SELECT predicates:
Expand All @@ -235,7 +201,6 @@
* No JOIN support.
*/
#define ESODBC_SQL92_RELATIONAL_JOIN_OPERATORS 0LU
#define ESODBC_OJ_CAPABILITIES 0LU

/*
* String functions support:
Expand Down
68 changes: 63 additions & 5 deletions driver/handles.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,7 @@ SQLRETURN EsSQLAllocHandle(SQLSMALLINT HandleType,
ERRNH(env, "failed to callocate connection handle.");
RET_HDIAGS(env, SQL_STATE_HY001);
}
dbc->dsn.str = MK_WPTR(""); /* see explanation in cleanup_dbc() */
dbc->metadata_id = SQL_FALSE;
dbc->txn_isolation = ESODBC_DEF_TXN_ISOLATION;

/* rest of initialization done at connect time */

Expand Down Expand Up @@ -802,14 +800,54 @@ SQLRETURN EsSQLSetStmtAttrW(
break;

case SQL_ATTR_QUERY_TIMEOUT:
DBGH(stmt, "setting query timeout to: %u", (SQLULEN)ValuePtr);
DBGH(stmt, "setting query timeout to: %u.", (SQLULEN)ValuePtr);
stmt->query_timeout = (SQLULEN)ValuePtr;
break;

case SQL_ATTR_CURSOR_TYPE:
DBGH(stmt, "setting cursor type: %llu.", (SQLULEN)ValuePtr);
if ((SQLULEN)ValuePtr != SQL_CURSOR_FORWARD_ONLY) {
WARNH(stmt, "requested cursor_type substituted with "
"forward-only (%llu).", SQL_CURSOR_FORWARD_ONLY);
RET_HDIAGS(stmt, SQL_STATE_01S02);
}
break;

case SQL_ATTR_NOSCAN:
DBGH(stmt, "setting escape seq scanning: %llu -- NOOP.",
(SQLULEN)ValuePtr);
/* nothing to do: the driver never scans the input, ESSQL processes
* the escape sequences */
break;

case SQL_ATTR_CONCURRENCY:
DBGH(stmt, "setting concurrency: %llu.", (SQLULEN)ValuePtr);
if ((SQLULEN)ValuePtr != SQL_CONCUR_READ_ONLY) {
WARNH(stmt, "requested concurrency substituted with "
"read-only (%llu).", SQL_CONCUR_READ_ONLY);
RET_HDIAGS(stmt, SQL_STATE_01S02);
}
break;

case SQL_ATTR_MAX_ROWS:
DBGH(stmt, "setting max rows: %llu.", (SQLULEN)ValuePtr);
if ((SQLULEN)ValuePtr != 0) {
WARNH(stmt, "requested max_rows substituted with 0.");
RET_HDIAGS(stmt, SQL_STATE_01S02);
}
break;

case SQL_ATTR_CURSOR_SENSITIVITY:
DBGH(stmt, "setting cursor sensitivity: %llu.", (SQLULEN)ValuePtr);
if ((SQLULEN)ValuePtr != SQL_UNSPECIFIED) {
ERRH(stmt, "driver supports forward-only cursors.");
RET_HDIAGS(stmt, SQL_STATE_HYC00);
}
break;

default:
// FIXME
FIXME;
ERRH(stmt, "unknown Attribute: %d.", Attribute);
BUGH(stmt, "unknown Attribute: %d.", Attribute);
RET_HDIAGS(stmt, SQL_STATE_HY092);
}
/*INDENT-ON*/
Expand Down Expand Up @@ -899,6 +937,26 @@ SQLRETURN EsSQLGetStmtAttrW(
*(SQLULEN *)ValuePtr = SQL_UB_OFF;
break;

case SQL_ATTR_NOSCAN:
DBGH(stmt, "getting noscan: %llu.", SQL_NOSCAN_OFF);
*(SQLULEN *)ValuePtr = SQL_NOSCAN_OFF;
break;

case SQL_ATTR_CONCURRENCY:
DBGH(stmt, "getting concurrency: %llu.", SQL_CONCUR_READ_ONLY);
*(SQLULEN *)ValuePtr = SQL_CONCUR_READ_ONLY;
break;

case SQL_ATTR_MAX_ROWS:
DBGH(stmt, "getting max rows: 0.");
*(SQLULEN *)ValuePtr = 0;
break;

case SQL_ATTR_CURSOR_SENSITIVITY:
DBGH(stmt, "getting cursor sensitivity: %llu.", SQL_UNSPECIFIED);
*(SQLULEN *)ValuePtr = SQL_UNSPECIFIED;
break;

default:
ERRH(stmt, "unknown attribute: %d.", Attribute);
RET_HDIAGS(stmt, SQL_STATE_HY092);
Expand Down
Loading