Skip to content
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
37 changes: 30 additions & 7 deletions driver/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ SQLRETURN post_json(esodbc_stmt_st *stmt, const cstr_st *u8body)

DBGH(stmt, "POSTing JSON [%zd] `" LCPDL "`.", u8body->cnt, LCSTR(u8body));

ESODBC_MUX_LOCK(&dbc->curl_mux);

if (! dbc->curl) {
init_curl(dbc);
}
Expand Down Expand Up @@ -370,6 +372,8 @@ SQLRETURN post_json(esodbc_stmt_st *stmt, const cstr_st *u8body)
DBGH(stmt, "libcurl: request succesfull, received code %ld and %zd bytes"
" back.", code, apos);

ESODBC_MUX_UNLOCK(&dbc->curl_mux);

if (code != 200) {
ERRH(stmt, "libcurl: non-200 HTTP response code %ld received.", code);
/* expect a 200 with body; everything else is failure (todo?) */
Expand All @@ -387,6 +391,8 @@ SQLRETURN post_json(esodbc_stmt_st *stmt, const cstr_st *u8body)
res != CURLE_OK ? curl_easy_strerror(res) : "<unspecified>", res);
err_net: /* the error occured after the request hit hit the network */
cleanup_curl(dbc);
ESODBC_MUX_UNLOCK(&dbc->curl_mux);

if (abuff) {
free(abuff);
abuff = NULL;
Expand Down Expand Up @@ -594,7 +600,7 @@ void cleanup_dbc(esodbc_dbc_st *dbc)
} else {
assert(dbc->no_types == 0);
}
assert(dbc->abuff == NULL); /* reminder for when going multithreaded */
assert(dbc->abuff == NULL);
cleanup_curl(dbc);
}

Expand Down Expand Up @@ -1575,10 +1581,26 @@ SQLRETURN EsSQLSetConnectAttrW(
DBGH(dbc, "setting metadata_id to %u.", (SQLULEN)Value);
dbc->metadata_id = (SQLULEN)Value;
break;

case SQL_ATTR_ASYNC_ENABLE:
DBGH(dbc, "setting async enable to %u.", (SQLULEN)Value);
dbc->async_enable = (SQLULEN)Value;
ERRH(dbc, "no support for async API (setting param: %llu)",
(SQLULEN)(uintptr_t)Value);
if ((SQLULEN)(uintptr_t)Value == SQL_ASYNC_ENABLE_ON) {
RET_HDIAGS(dbc, SQL_STATE_HYC00);
}
break;
case SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE:
ERRH(dbc, "no support for async API (setting param: %llu)",
(SQLULEN)(uintptr_t)Value);
if ((SQLULEN)(uintptr_t)Value == SQL_ASYNC_DBC_ENABLE_ON) {
RET_HDIAGS(dbc, SQL_STATE_HY114);
}
break;
case SQL_ATTR_ASYNC_DBC_EVENT:
// case SQL_ATTR_ASYNC_DBC_PCALLBACK:
// case SQL_ATTR_ASYNC_DBC_PCONTEXT:
ERRH(dbc, "no support for async API (attr: %ld)", Attribute);
RET_HDIAGS(dbc, SQL_STATE_S1118);

case SQL_ATTR_QUIET_MODE:
DBGH(dbc, "setting window handler to 0x%p.", Value);
Expand Down Expand Up @@ -1631,17 +1653,18 @@ SQLRETURN EsSQLGetConnectAttrW(
ERRH(dbc, "failed to get current catalog.");
RET_STATE(dbc->hdr.diag.state);
}
if (StringLengthPtr);
*StringLengthPtr = (SQLINTEGER)used;
if (StringLengthPtr) {
*StringLengthPtr = (SQLINTEGER)used;
}
break;

case SQL_ATTR_METADATA_ID:
DBGH(dbc, "requested: metadata_id: %u.", dbc->metadata_id);
*(SQLULEN *)ValuePtr = dbc->metadata_id;
break;
case SQL_ATTR_ASYNC_ENABLE:
DBGH(dbc, "requested: async enable: %u.", dbc->async_enable);
*(SQLULEN *)ValuePtr = dbc->async_enable;
DBGH(dbc, "getting async mode: %llu", SQL_ASYNC_ENABLE_OFF);
*(SQLULEN *)ValuePtr = SQL_ASYNC_ENABLE_OFF;
break;

case SQL_ATTR_QUIET_MODE:
Expand Down
3 changes: 1 addition & 2 deletions driver/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@
#define ESODBC_PARAM_MARKER "?"

/* max # of active statements for a connection */
/* TODO: review@alpha */
#define ESODBC_MAX_CONCURRENT_ACTIVITIES 16
#define ESODBC_MAX_CONCURRENT_ACTIVITIES 0
/* maximum identifer length */
/* TODO: review@alpha */
/* match 'keyword' ES type length */
Expand Down
6 changes: 6 additions & 0 deletions driver/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ typedef enum {
SQL_STATE_HY109,
SQL_STATE_HY110,
SQL_STATE_HY111,
SQL_STATE_HY114,
SQL_STATE_HYC00,
SQL_STATE_HYT00,
SQL_STATE_HYT01,
Expand All @@ -138,6 +139,7 @@ typedef enum {
SQL_STATE_IM013,
SQL_STATE_IM014,
SQL_STATE_IM015,
SQL_STATE_S1118,
SQL_STATE_MAX
} esodbc_state_et;

Expand Down Expand Up @@ -379,6 +381,8 @@ static esodbc_errors_st esodbc_errors[] = {
SQL_ERROR},
{MK_WPTR("HY111"), MK_WPTR("Invalid bookmark value"),
SQL_ERROR},
{MK_WPTR("HY114"), MK_WPTR("Driver does not support connection-level "
"asynchronous function execution"), SQL_ERROR},
{MK_WPTR("HYC00"), MK_WPTR("Optional feature not implemented"),
SQL_ERROR},
{MK_WPTR("HYT00"), MK_WPTR("Timeout expired"),
Expand Down Expand Up @@ -417,6 +421,8 @@ static esodbc_errors_st esodbc_errors[] = {
SQL_ERROR},
{MK_WPTR("IM015"), MK_WPTR("Corrupt file data source"),
SQL_ERROR},
{MK_WPTR("S1118"), MK_WPTR("Driver does not support asynchronous "
"notification"), SQL_ERROR},
};
/*INDENT-ON*/

Expand Down
34 changes: 23 additions & 11 deletions driver/handles.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ static void init_hheader(esodbc_hhdr_st *hdr, SQLSMALLINT type, void *parent)
{
hdr->type = type;
init_diagnostic(&hdr->diag);
ESODBC_MUX_INIT(&hdr->mutex);
hdr->parent = parent;
}

Expand Down Expand Up @@ -225,7 +226,6 @@ SQLRETURN EsSQLAllocHandle(SQLSMALLINT HandleType,
}
dbc->dsn.str = MK_WPTR(""); /* see explanation in cleanup_dbc() */
dbc->metadata_id = SQL_FALSE;
dbc->async_enable = SQL_ASYNC_ENABLE_OFF;
dbc->txn_isolation = ESODBC_DEF_TXN_ISOLATION;

/* rest of initialization done at connect time */
Expand Down Expand Up @@ -261,9 +261,10 @@ SQLRETURN EsSQLAllocHandle(SQLSMALLINT HandleType,
* Note: these attributes won't propagate at statement level when
* set at connection level. */
stmt->metadata_id = dbc->metadata_id;
stmt->async_enable = dbc->async_enable;
stmt->sql2c_conversion = CONVERSION_UNCHECKED;

ESODBC_MUX_INIT(&dbc->curl_mux);

DBGH(dbc, "new Statement handle allocated @0x%p.", *OutputHandle);
break;

Expand Down Expand Up @@ -303,6 +304,7 @@ SQLRETURN EsSQLAllocHandle(SQLSMALLINT HandleType,

SQLRETURN EsSQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle)
{
esodbc_dbc_st *dbc;
esodbc_stmt_st *stmt;
esodbc_desc_st *desc;

Expand All @@ -314,13 +316,13 @@ SQLRETURN EsSQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle)
switch(HandleType) {
case SQL_HANDLE_ENV: /* Environment Handle */
// TODO: check if there are connections (_DBC)
free(Handle);
break;
case SQL_HANDLE_DBC: /* Connection Handle */
// TODO: remove from (potential) list?
dbc = DBCH(Handle);
/* app/DM should have SQLDisconnect'ed, but just in case */
cleanup_dbc(DBCH(Handle));
free(Handle);
cleanup_dbc(dbc);
ESODBC_MUX_DEL(&dbc->curl_mux);
break;
case SQL_HANDLE_STMT:
// TODO: remove from (potential) list?
Expand All @@ -332,7 +334,6 @@ SQLRETURN EsSQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle)
clear_desc(stmt->ird, FALSE);
clear_desc(stmt->apd, FALSE);
clear_desc(stmt->ipd, FALSE);
free(stmt);
break;

// FIXME:
Expand All @@ -356,6 +357,8 @@ SQLRETURN EsSQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle)
return SQL_INVALID_HANDLE;
}

ESODBC_MUX_DEL(&HDRH(Handle)->mutex);
free(Handle);
return SQL_SUCCESS;
}

Expand Down Expand Up @@ -479,7 +482,7 @@ SQLRETURN EsSQLSetEnvAttr(SQLHENV EnvironmentHandle,
case SQL_ATTR_CONNECTION_POOLING:
case SQL_ATTR_CP_MATCH:
RET_HDIAG(ENVH(EnvironmentHandle), SQL_STATE_HYC00,
"Connection pooling not yet supported", 0);
"Connection pooling not supported", 0);

case SQL_ATTR_ODBC_VERSION:
switch ((intptr_t)Value) {
Expand Down Expand Up @@ -767,10 +770,19 @@ SQLRETURN EsSQLSetStmtAttrW(
DBGH(stmt, "setting metadata_id to: %u", (SQLULEN)ValuePtr);
stmt->metadata_id = (SQLULEN)ValuePtr;
break;

case SQL_ATTR_ASYNC_ENABLE:
DBGH(stmt, "setting async_enable to: %u", (SQLULEN)ValuePtr);
stmt->async_enable = (SQLULEN)ValuePtr;
ERRH(stmt, "no support for async API (setting param: %llu)",
(SQLULEN)(uintptr_t)ValuePtr);
if ((SQLULEN)(uintptr_t)ValuePtr == SQL_ASYNC_ENABLE_ON) {
RET_HDIAGS(stmt, SQL_STATE_HYC00);
}
break;
case SQL_ATTR_ASYNC_STMT_EVENT:
// case SQL_ATTR_ASYNC_STMT_PCALLBACK:
// case SQL_ATTR_ASYNC_STMT_PCONTEXT:
ERRH(stmt, "no support for async API (attr: %ld)", Attribute);
RET_HDIAGS(stmt, SQL_STATE_S1118);

case SQL_ATTR_MAX_LENGTH:
ulen = (SQLULEN)ValuePtr;
Expand Down Expand Up @@ -834,8 +846,8 @@ SQLRETURN EsSQLGetStmtAttrW(
*(SQLULEN *)ValuePtr = stmt->metadata_id;
break;
case SQL_ATTR_ASYNC_ENABLE:
DBGH(stmt, "getting async_enable: %llu", stmt->async_enable);
*(SQLULEN *)ValuePtr = stmt->async_enable;
DBGH(stmt, "getting async mode: %llu", SQL_ASYNC_ENABLE_OFF);
*(SQLULEN *)ValuePtr = SQL_ASYNC_ENABLE_OFF;
break;
case SQL_ATTR_MAX_LENGTH:
DBGH(stmt, "getting max_length: %llu", stmt->max_length);
Expand Down
19 changes: 13 additions & 6 deletions driver/handles.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ typedef struct struct_hheader { /* handle header */
SQLSMALLINT type;
/* diagnostic/state keeping */
esodbc_diag_st diag;
/* ODBC API multi-threading exclusive lock */
esodbc_mutex_lt mutex;
/* back reference to "parent" structure (in type hierarchy) */
union {
struct struct_env *env;
Expand Down Expand Up @@ -145,17 +147,13 @@ typedef struct struct_dbc {
size_t alen; /* size of abuff */
size_t apos; /* current write position in the abuff */
size_t amax; /* maximum length (bytes) that abuff can grow to */
esodbc_mutex_lt curl_mux; /* mutex for above 'networking' members */

/* window handler */
HWND hwin;
/* "the catalog is a database", "For a single-tier driver, the catalog
* might be a directory" */
SQLWCHAR *catalog;
// TODO: statement list?

/* options */
SQLULEN metadata_id; // default: SQL_FALSE
SQLULEN async_enable; // default: SQL_ASYNC_ENABLE_OFF
SQLUINTEGER txn_isolation; // default: SQL_TXN_*
} esodbc_dbc_st;

Expand Down Expand Up @@ -307,7 +305,6 @@ typedef struct struct_stmt {
/* options */
SQLULEN bookmarks; //default: SQL_UB_OFF
SQLULEN metadata_id; // default: copied from connection
SQLULEN async_enable; // default: copied from connection
/* "the maximum amount of data that the driver returns from a character or
* binary column" */
SQLULEN max_length;
Expand Down Expand Up @@ -437,13 +434,23 @@ SQLRETURN EsSQLSetDescRec(
_Inout_opt_ SQLLEN *Indicator);


/*
* Macros to convert ODBC API generic handles into implementation types.
*/
#define ENVH(_h) ((esodbc_env_st *)(_h))
#define DBCH(_h) ((esodbc_dbc_st *)(_h))
#define STMH(_h) ((esodbc_stmt_st *)(_h))
#define DSCH(_h) ((esodbc_desc_st *)(_h))
/* this will only work if member stays first in handles (see struct decl). */
#define HDRH(_h) ((esodbc_hhdr_st *)(_h))

/*
* Locking macros for ODBC API calls.
*/
#define HND_LOCK(_h) ESODBC_MUX_LOCK(&HDRH(_h)->mutex)
#define HND_TRYLOCK(_h) ESODBC_MUX_TRYLOCK(&HDRH(_h)->mutex)
#define HND_UNLOCK(_h) ESODBC_MUX_UNLOCK(&HDRH(_h)->mutex)


/* wraper of RET_CDIAG, compatible with any defined handle */
#define RET_HDIAG(_hp/*handle ptr*/, _s/*tate*/, _t/*char text*/, _c/*ode*/) \
Expand Down
28 changes: 18 additions & 10 deletions driver/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,19 +123,29 @@ SQLRETURN EsSQLGetInfoW(SQLHDBC ConnectionHandle,
return write_wstr(dbc, InfoValue, &MK_WSTR(ESODBC_SQL_SPEC_STRING),
BufferLength, StringLengthPtr);

case SQL_ASYNC_MODE:
DBGH(dbc, "requested: async mode (%lu).", SQL_AM_NONE);
*(SQLUINTEGER *)InfoValue = SQL_AM_NONE;
break;

/* "if the driver can execute functions asynchronously on the
* connection handle" */
case SQL_ASYNC_DBC_FUNCTIONS:
/* TODO: review@alpha */
*(SQLUSMALLINT *)InfoValue = SQL_FALSE;
DBGH(dbc, "requested: support for async fuctions: no.");
DBGH(dbc, "requested: async DBC functions (no - %lu).",
SQL_ASYNC_DBC_NOT_CAPABLE);
*(SQLUINTEGER *)InfoValue = SQL_ASYNC_DBC_NOT_CAPABLE;
break;

/* "if the driver supports asynchronous notification" */
case SQL_ASYNC_NOTIFICATION:
// FIXME: review@alpha */
DBGH(dbc, "requested: async notification (no - %lu).",
SQL_ASYNC_NOTIFICATION_NOT_CAPABLE);
*(SQLUINTEGER *)InfoValue = SQL_ASYNC_NOTIFICATION_NOT_CAPABLE;
DBGH(dbc, "requested: support for async notifications: no.");
break;

case SQL_MAX_ASYNC_CONCURRENT_STATEMENTS:
DBGH(dbc, "requested: async concurrent statements (0).");
*(SQLUINTEGER *)InfoValue = 0;
break;

/* "the maximum number of active statements that the driver can
Expand All @@ -159,8 +169,6 @@ SQLRETURN EsSQLGetInfoW(SQLHDBC ConnectionHandle,

case SQL_GETDATA_EXTENSIONS:
DBGH(dbc, "requested: GetData extentions.");
// FIXME: review@alpha
// TODO: GetData review
*(SQLUINTEGER *)InfoValue = ESODBC_GETDATA_EXTENSIONS;
break;

Expand Down Expand Up @@ -735,9 +743,10 @@ SQLRETURN EsSQLGetDiagFieldW(
return write_wstr(&dummy, DiagInfoPtr, wstrp, BufferLength,
StringLengthPtr);

case SQL_DIAG_CONNECTION_NAME:
/* same as SQLGetInfo(SQL_DATA_SOURCE_NAME) */
case SQL_DIAG_SERVER_NAME: /* TODO: keep same as _CONNECTION_NAME? */
case SQL_DIAG_CONNECTION_NAME:
/* TODO: this must be the server name, not DSN. */
case SQL_DIAG_SERVER_NAME:
switch (HandleType) {
case SQL_HANDLE_DBC:
wstrp = &DBCH(Handle)->dsn;
Expand Down Expand Up @@ -912,7 +921,6 @@ SQLRETURN EsSQLGetFunctions(SQLHDBC ConnectionHandle,
}
}

// TODO: does this require connecting to the server?
return SQL_SUCCESS;
}

Expand Down
Loading