odbchelper.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. Copyright (c) 2007-2022 Bruce A Henderson
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions are met:
  6. * Redistributions of source code must retain the above copyright
  7. notice, this list of conditions and the following disclaimer.
  8. * Redistributions in binary form must reproduce the above copyright
  9. notice, this list of conditions and the following disclaimer in the
  10. documentation and/or other materials provided with the distribution.
  11. * Neither the auther nor the names of its contributors may be used to
  12. endorse or promote products derived from this software without specific
  13. prior written permission.
  14. THIS SOFTWARE IS PROVIDED BY Bruce A Henderson ``AS IS'' AND ANY
  15. EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
  18. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  21. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #ifdef WIN32
  26. #include <windows.h>
  27. #include <sqlext.h>
  28. #include <odbcinst.h>
  29. #else
  30. #include <isqlext.h>
  31. #include <iodbcinst.h>
  32. #endif
  33. #include <stdio.h>
  34. #include <brl.mod/blitz.mod/blitz.h>
  35. int bmx_odbc_SQLAllocHandle(SQLSMALLINT type, SQLHANDLE * inputHandle, SQLHANDLE * outputHandle) {
  36. int r = 0;
  37. if (inputHandle) {
  38. r = SQLAllocHandle(type, inputHandle, outputHandle);
  39. } else {
  40. r = SQLAllocHandle(type, SQL_NULL_HANDLE, outputHandle);
  41. }
  42. return r;
  43. }
  44. BBString * bmx_odbc_envError(SQLHANDLE * handle, int * code) {
  45. SQLTCHAR state[SQL_SQLSTATE_SIZE+1];
  46. SQLTCHAR description[SQL_MAX_MESSAGE_LENGTH + 1];
  47. description[0] = 0;
  48. SQLINTEGER actualCode;
  49. SQLSMALLINT actualSize;
  50. SQLLEN numRecs = 0;
  51. SQLGetDiagField(SQL_HANDLE_STMT, handle, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);
  52. if (numRecs > 0) {
  53. SQLRETURN result = SQLGetDiagRec(SQL_HANDLE_ENV, handle, 1, (SQLTCHAR*)state, &actualCode, description, SQL_MAX_MESSAGE_LENGTH, &actualSize);
  54. if (result == SQL_SUCCESS || result == SQL_SUCCESS_WITH_INFO) {
  55. // we got error details ok, so we can fill in the code, and return the text...
  56. *code = actualCode;
  57. return bbStringFromUTF8Bytes(description, actualSize);
  58. }
  59. }
  60. return &bbEmptyString;
  61. }
  62. const char * bmx_odbc_connError(SQLHANDLE * handle, int * code, int * size) {
  63. SQLTCHAR state[SQL_SQLSTATE_SIZE+1];
  64. SQLTCHAR description[SQL_MAX_MESSAGE_LENGTH + 1];
  65. description[0] = 0;
  66. SQLINTEGER actualCode;
  67. SQLSMALLINT actualSize;
  68. SQLLEN numRecs = 0;
  69. SQLGetDiagField(SQL_HANDLE_STMT, handle, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);
  70. if (numRecs > 0) {
  71. SQLRETURN result = SQLGetDiagRec(SQL_HANDLE_DBC, handle, 1, (SQLTCHAR*)state, &actualCode, description, SQL_MAX_MESSAGE_LENGTH, &actualSize);
  72. if (result == SQL_SUCCESS || result == SQL_SUCCESS_WITH_INFO) {
  73. // we got error details ok, so we can fill in the code, and return the text...
  74. *code = actualCode;
  75. return bbStringFromUTF8Bytes(description, actualSize);
  76. }
  77. }
  78. return &bbEmptyString;
  79. }
  80. const char * bmx_odbc_stmtError(SQLHANDLE * handle, int * code, int * size) {
  81. SQLTCHAR state[SQL_SQLSTATE_SIZE+1];
  82. SQLTCHAR description[SQL_MAX_MESSAGE_LENGTH + 1];
  83. description[0] = 0;
  84. SQLINTEGER actualCode;
  85. SQLSMALLINT actualSize;
  86. SQLLEN numRecs = 0;
  87. SQLGetDiagField(SQL_HANDLE_STMT, handle, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);
  88. if (numRecs > 0) {
  89. SQLRETURN result = SQLGetDiagRec(SQL_HANDLE_STMT, handle, 1, (SQLTCHAR*)state, &actualCode, description, SQL_MAX_MESSAGE_LENGTH, &actualSize);
  90. if (result == SQL_SUCCESS || result == SQL_SUCCESS_WITH_INFO) {
  91. // we got error details ok, so we can fill in the code, and return the text...
  92. *code = actualCode;
  93. return bbStringFromUTF8Bytes(description, actualSize);
  94. }
  95. }
  96. return &bbEmptyString;
  97. }
  98. void bmx_odbc_setattr_odbc3(SQLHANDLE * handle) {
  99. SQLSetEnvAttr(handle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_UINTEGER);
  100. }
  101. int bmx_odbc_SQLDriverConnect(SQLHANDLE * handle, const char * connectString, int connectLength) {
  102. SQLTCHAR buffer[1024];
  103. SQLSMALLINT buffSize;
  104. int result = SQLDriverConnect(handle, NULL, (SQLCHAR*)connectString, connectLength, buffer, 1024, &buffSize, SQL_DRIVER_NOPROMPT);
  105. return result;
  106. }
  107. int bmx_odbc_toggleTransaction(SQLHANDLE * handle, int toggle) {
  108. int result;
  109. if (toggle) {
  110. result = SQLSetConnectAttr(handle, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_IS_UINTEGER);
  111. } else {
  112. result = SQLSetConnectAttr(handle, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER);
  113. }
  114. return result;
  115. }
  116. int bmx_odbc_commitTransaction(SQLHANDLE * handle) {
  117. int result = SQLEndTran(SQL_HANDLE_DBC, handle, SQL_COMMIT);
  118. return result;
  119. }
  120. int bmx_odbc_rollbackTransaction(SQLHANDLE * handle) {
  121. int result = SQLEndTran(SQL_HANDLE_DBC, handle, SQL_ROLLBACK);
  122. return result;
  123. }
  124. void bmx_odbc_disconnectAndFree(SQLHANDLE * handle) {
  125. SQLDisconnect(handle);
  126. SQLFreeHandle(SQL_HANDLE_DBC, handle);
  127. }
  128. int bmx_odbc_freeEnvHandle(SQLHANDLE * handle) {
  129. int result = SQLFreeHandle(SQL_HANDLE_ENV, handle);
  130. return result;
  131. }
  132. int bmx_odbc_freeStmtHandle(SQLHANDLE * handle) {
  133. int result = SQLFreeHandle(SQL_HANDLE_STMT, handle);
  134. return result;
  135. }
  136. int bmx_odbc_SQLRowCount(SQLHSTMT * handle, int * num) {
  137. SQLLEN len;
  138. int result = SQLRowCount(handle, &len);
  139. *num = len;
  140. return result;
  141. }
  142. int bmx_odbc_setForwardCursor(SQLHSTMT * handle) {
  143. int result = SQLSetStmtAttr(handle, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, SQL_IS_UINTEGER);
  144. return result;
  145. }
  146. int bmx_odbc_execute(SQLHSTMT * handle, const char * query, int length) {
  147. int result = SQLExecDirect(handle, (SQLCHAR *) query, (SQLINTEGER) length);
  148. return result;
  149. }
  150. void bmx_odbc_SQLNumResultCols(SQLHSTMT * handle, int * count) {
  151. SQLSMALLINT sCount;
  152. SQLNumResultCols(handle, &sCount);
  153. *count = (int)sCount;
  154. }
  155. int bmx_odbc_SQLDescribeCol(SQLHSTMT * handle, int column, char * columnName, int bufferLength,
  156. int * nameLength, int * dataType, int * columnSize, int * decimalDigits, int * nullable) {
  157. SQLSMALLINT sNameLength;
  158. SQLSMALLINT sDataType;
  159. SQLSMALLINT sDecimalDigits;
  160. SQLSMALLINT sNullable;
  161. SQLULEN csize;
  162. int result = SQLDescribeCol(handle, column, (SQLCHAR *)columnName, bufferLength,
  163. &sNameLength, &sDataType,
  164. &csize, &sDecimalDigits, &sNullable);
  165. *nameLength = (int)sNameLength;
  166. *dataType = (int)sDataType;
  167. *decimalDigits = (int)sDecimalDigits;
  168. *nullable = (int)sNullable;
  169. *columnSize = csize;
  170. return result;
  171. }
  172. int bmx_odbc_SQLFetchScroll(SQLHSTMT * handle) {
  173. int result = SQLFetchScroll(handle, SQL_FETCH_NEXT, 0);
  174. return result;
  175. }
  176. int bmx_odbc_SQLGetData_int(SQLHSTMT * handle, int index, int * value, int * indicator) {
  177. SQLLEN ind;
  178. int result = SQLGetData(handle, index, SQL_C_SLONG, value, 0, &ind);
  179. *indicator = ind;
  180. return result;
  181. }
  182. int bmx_odbc_SQLGetData_long(SQLHSTMT * handle, int index, BBInt64 * value, int * indicator) {
  183. SQLLEN ind;
  184. int result = SQLGetData(handle, index, SQL_C_SBIGINT, value, 0, &ind);
  185. *indicator = ind;
  186. return result;
  187. }
  188. int bmx_odbc_SQLGetData_double(SQLHSTMT * handle, int index, double * value, int * indicator) {
  189. SQLLEN ind;
  190. int result = SQLGetData(handle, index, SQL_C_DOUBLE, value, 0, &ind);
  191. *indicator = ind;
  192. return result;
  193. }
  194. int bmx_odbc_SQLGetData_string(SQLHSTMT * handle, int index, char * buffer, int bufferLength, int * indicator) {
  195. SQLLEN ind;
  196. int result = SQLGetData(handle, index, SQL_C_CHAR, buffer, bufferLength, &ind);
  197. *indicator = ind;
  198. return result;
  199. }
  200. int bmx_odbc_SQLGetData_date(SQLHSTMT * handle, int index, int * y, int * m, int * d, int * indicator) {
  201. SQLLEN ind;
  202. DATE_STRUCT date;
  203. int result = SQLGetData(handle, index, SQL_C_TYPE_DATE, &date, 0, &ind);
  204. *y = date.year;
  205. *m = date.month;
  206. *d = date.day;
  207. *indicator = ind;
  208. return result;
  209. }
  210. int bmx_odbc_SQLGetData_time(SQLHSTMT * handle, int index, int * hh, int * mm, int * ss, int * indicator) {
  211. SQLLEN ind;
  212. SQL_TIME_STRUCT time;
  213. int result = SQLGetData(handle, index, SQL_C_TYPE_TIMESTAMP, &time, 0, &ind);
  214. *hh = time.hour;
  215. *mm = time.minute;
  216. *ss = time.second;
  217. *indicator = ind;
  218. return result;
  219. }
  220. int bmx_odbc_SQLGetData_datetime(SQLHSTMT * handle, int index, int * y, int * m, int * d,
  221. int * hh, int * mm, int * ss, int * indicator) {
  222. SQLLEN ind;
  223. SQL_TIMESTAMP_STRUCT datetime;
  224. int result = SQLGetData(handle, index, SQL_C_TYPE_TIMESTAMP, &datetime, 0, &ind);
  225. *y = datetime.year;
  226. *m = datetime.month;
  227. *d = datetime.day;
  228. *hh = datetime.hour;
  229. *mm = datetime.minute;
  230. *ss = datetime.second;
  231. *indicator = ind;
  232. return result;
  233. }
  234. int bmx_odbc_prepare(SQLHSTMT * handle, const char * query, int length) {
  235. int result = SQLPrepare(handle, (SQLCHAR *) query, (SQLINTEGER) length);
  236. return result;
  237. }
  238. int bmx_odbc_executePrepared(SQLHSTMT * handle) {
  239. int result = SQLExecute(handle);
  240. return result;
  241. }
  242. int bmx_odbc_SQLBindParameter_int(SQLHSTMT * handle, int index, int * paramValue, int * isNull) {
  243. SQLLEN in;
  244. int result = SQLBindParameter(handle, index, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0,
  245. paramValue, 0, *isNull == SQL_NULL_DATA ? &in : NULL);
  246. *isNull = in;
  247. return result;
  248. }
  249. int bmx_odbc_SQLBindParameter_double(SQLHSTMT * handle, int index, double * paramValue, int * isNull) {
  250. SQLLEN in;
  251. int result = SQLBindParameter(handle, index, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0,
  252. paramValue, 0, *isNull == SQL_NULL_DATA ? &in : NULL);
  253. *isNull = in;
  254. return result;
  255. }
  256. int bmx_odbc_SQLBindParameter_long(SQLHSTMT * handle, int index, BBInt64 * paramValue, int * isNull) {
  257. SQLLEN in;
  258. int result = SQLBindParameter(handle, index, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0,
  259. paramValue, 0, *isNull == SQL_NULL_DATA ? &in : NULL);
  260. *isNull = in;
  261. return result;
  262. }
  263. int bmx_odbc_SQLBindParameter_string(SQLHSTMT * handle, int index, char * paramValue, int length, int * isNull) {
  264. SQLLEN in;
  265. int result = SQLBindParameter(handle, index, SQL_PARAM_INPUT, SQL_C_CHAR, (length > 4000) ? SQL_LONGVARCHAR : SQL_VARCHAR,
  266. length + 1, 0, paramValue, length + 1, &in);
  267. *isNull = in;
  268. return result;
  269. }
  270. int bmx_odbc_SQLTables(SQLHSTMT * handle, char * type, int length) {
  271. int result = SQLTables(handle, NULL, 0, NULL, 0, NULL, 0, (SQLCHAR *)type, length);
  272. return result;
  273. }