forked from hdbc/hdbc-odbc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhdbc-odbc-helper.c
137 lines (121 loc) · 3.9 KB
/
hdbc-odbc-helper.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#if defined(mingw32_HOST_OS) || defined(mingw32_TARGET_OS) || defined(__MINGW32__)
#include <windows.h>
#include <winnt.h>
#endif
#include <sql.h>
#include <sqlext.h>
#include <stdio.h>
#include <stdlib.h>
#include "hdbc-odbc-helper.h"
SQLLEN nullDataHDBC = SQL_NULL_DATA;
int sqlSucceeded(SQLRETURN ret) {
return SQL_SUCCEEDED(ret);
}
/* Things can't finalize more than once.
We'd like to let people call them from the app.
Yet we'd also like to be able to have a ForeignPtr finalize them.
So, here's a little wrapper for things. */
void dbc_conditional_finalizer(finalizeonce *conn);
finalizeonce *wrapobjodbc(void *obj, finalizeonce *parentobj) {
finalizeonce *newobj;
newobj = malloc(sizeof(finalizeonce));
if (newobj == NULL) {
fprintf(stderr, "\nHDBC: could not allocate wrapper!\n");
return NULL;
}
newobj->isfinalized = 0;
newobj -> refcount = 1;
newobj->encapobj = obj;
newobj->extrainfo = NULL;
newobj->parent = parentobj;
if (parentobj != NULL)
(parentobj->refcount)++;
#ifdef HDBC_DEBUG
fprintf(stderr, "\nWrapped %p at %p\n", obj, newobj);
#endif
return newobj;
}
finalizeonce *wrapobjodbc_extra(void *obj, void *extra, finalizeonce *parentobj) {
finalizeonce *newobj = wrapobjodbc(obj, parentobj);
if (newobj != NULL)
newobj->extrainfo = extra;
return newobj;
}
void sqlFreeHandleSth_app(finalizeonce *res) {
#ifdef HDBC_DEBUG
fprintf(stderr, "\nApp cleanup of sth %p requested: %d\n",
res->encapobj, res->isfinalized);
#endif
if (res->isfinalized)
return;
SQLCloseCursor((SQLHSTMT) (res->encapobj));
SQLFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE) (res->encapobj));
res->isfinalized = 1;
res->encapobj = NULL;
}
void sqlFreeHandleSth_finalizer(finalizeonce *res) {
#ifdef HDBC_DEBUG
fprintf(stderr, "\nFinalizer cleanup of sth %p requested: %d\n",
res->encapobj, res->isfinalized);
#endif
sqlFreeHandleSth_app(res);
(res->refcount)--; /* Not really important since this is never a
parent */
(res->parent->refcount)--;
dbc_conditional_finalizer(res->parent);
free(res);
}
SQLRETURN sqlFreeHandleDbc_app(finalizeonce *res) {
SQLRETURN retval;
#ifdef HDBC_DEBUG
fprintf(stderr, "\nApp cleanup of dbc %p requested: %d\n",
res->encapobj, res->isfinalized);
#endif
if (res->isfinalized)
return 0;
retval = SQLDisconnect((SQLHDBC) (res->encapobj));
if (SQL_SUCCEEDED(retval)) {
SQLFreeHandle(SQL_HANDLE_DBC, (SQLHANDLE) (res->encapobj));
SQLFreeHandle(SQL_HANDLE_ENV, (SQLHANDLE) (res->extrainfo));
res->isfinalized = 1;
res->encapobj = NULL;
}
return retval;
}
void sqlFreeHandleDbc_finalizer(finalizeonce *res) {
#ifdef HDBC_DEBUG
fprintf(stderr, "\nFinalizer cleanup of dbc %p requested: %d\n",
res->encapobj, res->isfinalized);
#endif
(res->refcount)--;
dbc_conditional_finalizer(res);
}
void dbc_conditional_finalizer(finalizeonce *res) {
if (res->refcount < 1) {
/* Don't use sqlFreeHandleDbc_app here, because we want to clear it out
regardless of the success or failues of SQLDisconnect. */
if (! (res->isfinalized)) {
SQLDisconnect((SQLHDBC) (res->encapobj));
SQLFreeHandle(SQL_HANDLE_DBC, (SQLHANDLE) (res->encapobj));
SQLFreeHandle(SQL_HANDLE_ENV, (SQLHANDLE) (res->extrainfo));
res->encapobj = NULL;
res->isfinalized = 1;
}
free(res);
}
}
void *getSqlOvOdbc3(void) {
return (void *)SQL_OV_ODBC3;
}
SQLRETURN disableAutoCommit(SQLHDBC conn) {
return SQLSetConnectAttr(conn, SQL_ATTR_AUTOCOMMIT,
(SQLPOINTER) SQL_AUTOCOMMIT_OFF,
SQL_IS_UINTEGER);
}
SQLRETURN simpleSqlTables(SQLHSTMT stmt) {
return SQLTables(stmt, NULL, 0, NULL, 0, "%", 1, "TABLE", 5);
}
SQLRETURN simpleSqlColumns(SQLHSTMT stmt, SQLCHAR *tablename,
SQLSMALLINT tnlen) {
return SQLColumns(stmt, NULL, 0, NULL, 0, tablename, tnlen, "%", 1);
}