@zowe/db2-for-zowe-cli 6.1.17 → 6.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/README.md +12 -10
  2. package/lib/Db2PluginLifeCycle.d.ts +11 -9
  3. package/lib/Db2PluginLifeCycle.js +18 -13
  4. package/lib/Db2PluginLifeCycle.js.map +1 -1
  5. package/node_modules/axios/CHANGELOG.md +62 -0
  6. package/node_modules/axios/README.md +233 -5
  7. package/node_modules/axios/dist/axios.js +387 -89
  8. package/node_modules/axios/dist/axios.min.js +3 -3
  9. package/node_modules/axios/dist/axios.min.js.map +1 -1
  10. package/node_modules/axios/dist/browser/axios.cjs +458 -98
  11. package/node_modules/axios/dist/esm/axios.js +458 -98
  12. package/node_modules/axios/dist/esm/axios.min.js +2 -2
  13. package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
  14. package/node_modules/axios/dist/node/axios.cjs +568 -116
  15. package/node_modules/axios/index.d.cts +4 -0
  16. package/node_modules/axios/index.d.ts +4 -0
  17. package/node_modules/axios/lib/adapters/fetch.js +64 -11
  18. package/node_modules/axios/lib/adapters/http.js +134 -50
  19. package/node_modules/axios/lib/adapters/xhr.js +52 -3
  20. package/node_modules/axios/lib/core/Axios.js +19 -14
  21. package/node_modules/axios/lib/core/InterceptorManager.js +107 -8
  22. package/node_modules/axios/lib/core/buildFullPath.js +1 -13
  23. package/node_modules/axios/lib/core/dispatchRequest.js +8 -2
  24. package/node_modules/axios/lib/core/mergeConfig.js +1 -1
  25. package/node_modules/axios/lib/core/methodList.js +17 -0
  26. package/node_modules/axios/lib/defaults/index.js +2 -1
  27. package/node_modules/axios/lib/env/data.js +1 -1
  28. package/node_modules/axios/lib/helpers/Http2Sessions.js +2 -0
  29. package/node_modules/axios/lib/helpers/HttpStatusCode.js +11 -1
  30. package/node_modules/axios/lib/helpers/fromDataURI.js +5 -4
  31. package/node_modules/axios/lib/helpers/normalizeURLForProtocolCheck.js +24 -0
  32. package/node_modules/axios/lib/helpers/progressEventReducer.js +1 -1
  33. package/node_modules/axios/lib/helpers/resolveConfig.js +4 -2
  34. package/node_modules/axios/lib/helpers/shouldBypassProxy.js +182 -6
  35. package/node_modules/axios/lib/helpers/throttle.js +3 -2
  36. package/node_modules/axios/lib/helpers/toFormData.js +14 -21
  37. package/node_modules/axios/lib/utils.js +134 -13
  38. package/node_modules/axios/package.json +1 -1
  39. package/node_modules/ibm_db/APIDocumentation.md +2883 -2024
  40. package/node_modules/ibm_db/LICENSE +23 -23
  41. package/node_modules/ibm_db/README.md +735 -735
  42. package/node_modules/ibm_db/binding.gyp +99 -98
  43. package/node_modules/ibm_db/installer/driverInstall.js +984 -958
  44. package/node_modules/ibm_db/installer/ifx.sh +38 -38
  45. package/node_modules/ibm_db/installer/setenv.sh +23 -23
  46. package/node_modules/ibm_db/installer/testODBCConnection.bat +51 -51
  47. package/node_modules/ibm_db/installer/testODBCConnection.sh +61 -61
  48. package/node_modules/ibm_db/lib/climacros.js +431 -431
  49. package/node_modules/ibm_db/lib/odbc.js +4293 -3487
  50. package/node_modules/ibm_db/lib/simple-queue.js +41 -41
  51. package/node_modules/ibm_db/package.json +70 -70
  52. package/node_modules/ibm_db/src/odbc.cpp +1495 -1396
  53. package/node_modules/ibm_db/src/odbc.h +477 -473
  54. package/node_modules/ibm_db/src/odbc_connection.cpp +1762 -1612
  55. package/node_modules/ibm_db/src/odbc_connection.h +228 -215
  56. package/node_modules/ibm_db/src/odbc_result.cpp +1547 -1547
  57. package/node_modules/ibm_db/src/odbc_result.h +152 -152
  58. package/node_modules/ibm_db/src/odbc_statement.cpp +2047 -861
  59. package/node_modules/ibm_db/src/odbc_statement.h +257 -135
  60. package/node_modules/ibm_db/src/strptime.c +389 -389
  61. package/node_modules/ibm_db/src/strptime.h +46 -46
  62. package/node_modules/ibm_db/test/README +23 -23
  63. package/node_modules/ibm_db/test/bench-insert.js +62 -62
  64. package/node_modules/ibm_db/test/bench-insertBatch10.js +74 -74
  65. package/node_modules/ibm_db/test/bench-insertBatch100.js +75 -75
  66. package/node_modules/ibm_db/test/bench-insertBatch1000.js +75 -75
  67. package/node_modules/ibm_db/test/bench-insertBatch10000.js +75 -75
  68. package/node_modules/ibm_db/test/bench-prepare-bind-execute-closeSync.js +60 -60
  69. package/node_modules/ibm_db/test/bench-prepare-bind-executeNonQuery.js +53 -53
  70. package/node_modules/ibm_db/test/bench-prepare-bindSync-execute-closeSync.js +50 -50
  71. package/node_modules/ibm_db/test/bench-prepare-bindSync-executeNonQuery.js +48 -48
  72. package/node_modules/ibm_db/test/bench-prepare-execute-closeSync.js +51 -51
  73. package/node_modules/ibm_db/test/bench-prepare-executeNonQuery.js +47 -47
  74. package/node_modules/ibm_db/test/bench-prepare-not.js +43 -43
  75. package/node_modules/ibm_db/test/bench-query-fetch.js +59 -59
  76. package/node_modules/ibm_db/test/bench-query-fetchAll.js +49 -49
  77. package/node_modules/ibm_db/test/bench-query-fetchAllSync.js +43 -43
  78. package/node_modules/ibm_db/test/bench-query.js +40 -40
  79. package/node_modules/ibm_db/test/bench-querySync-fetchArray.js +28 -28
  80. package/node_modules/ibm_db/test/bench-querySync.js +29 -29
  81. package/node_modules/ibm_db/test/common.d.ts +10 -10
  82. package/node_modules/ibm_db/test/common.js +127 -127
  83. package/node_modules/ibm_db/test/config.json +7 -7
  84. package/node_modules/ibm_db/test/config.zos.json +4 -4
  85. package/node_modules/ibm_db/test/data/sample1.txt +9 -9
  86. package/node_modules/ibm_db/test/data/trc.fmt +30114 -30114
  87. package/node_modules/ibm_db/test/nodeEE-leak-huge-query.js +152 -152
  88. package/node_modules/ibm_db/test/nodeEE-leak-multiple-query-multiple-connections.js +148 -148
  89. package/node_modules/ibm_db/test/nodeEE-leak-multiple-query-pool-connections.js +154 -154
  90. package/node_modules/ibm_db/test/nodeEE-leak-multiple-query.js +133 -133
  91. package/node_modules/ibm_db/test/nodeEE-stress-async-waterfall-multiple-connections.js +174 -174
  92. package/node_modules/ibm_db/test/nodeEE-stress-async-waterfall.js +169 -169
  93. package/node_modules/ibm_db/test/nodeEE-stress-mixed-query-multiple-connections.js +159 -159
  94. package/node_modules/ibm_db/test/nodeEE-stress-mixed-query.js +148 -148
  95. package/node_modules/ibm_db/test/odbc-bench.c +123 -123
  96. package/node_modules/ibm_db/test/perfTest.js +53 -53
  97. package/node_modules/ibm_db/test/quick-example.sh +30 -30
  98. package/node_modules/ibm_db/test/quick-example.ts +80 -80
  99. package/node_modules/ibm_db/test/run-bench.js +96 -96
  100. package/node_modules/ibm_db/test/run-nodeEE.js +132 -132
  101. package/node_modules/ibm_db/test/run-tests.js +132 -138
  102. package/node_modules/ibm_db/test/sql-cli.js +28 -28
  103. package/node_modules/ibm_db/test/test-all-data-types.js +109 -109
  104. package/node_modules/ibm_db/test/test-array-insert.js +178 -178
  105. package/node_modules/ibm_db/test/test-async-await.js +105 -105
  106. package/node_modules/ibm_db/test/test-attributes.js +34 -34
  107. package/node_modules/ibm_db/test/test-bad-pool-connection-prepare-execute.js +57 -57
  108. package/node_modules/ibm_db/test/test-basic-test.js +138 -138
  109. package/node_modules/ibm_db/test/test-binary-array-insert.js +73 -73
  110. package/node_modules/ibm_db/test/test-blob-from-file.js +90 -90
  111. package/node_modules/ibm_db/test/test-blob-insert.js +144 -144
  112. package/node_modules/ibm_db/test/test-blob-stream-insert.js +321 -299
  113. package/node_modules/ibm_db/test/test-blob-to-file.js +370 -370
  114. package/node_modules/ibm_db/test/test-block-fetch.js +364 -364
  115. package/node_modules/ibm_db/test/test-blocking-issue210.js +123 -123
  116. package/node_modules/ibm_db/test/test-call-async.js +64 -64
  117. package/node_modules/ibm_db/test/test-call-stmt.js +53 -53
  118. package/node_modules/ibm_db/test/test-cancel.js +703 -0
  119. package/node_modules/ibm_db/test/test-chinese-char.js +59 -59
  120. package/node_modules/ibm_db/test/test-connection.js +306 -0
  121. package/node_modules/ibm_db/test/test-date.js +32 -32
  122. package/node_modules/ibm_db/test/test-dbclob.js +93 -93
  123. package/node_modules/ibm_db/test/test-decimals.js +135 -135
  124. package/node_modules/ibm_db/test/test-describe-metadata.js +148 -0
  125. package/node_modules/ibm_db/test/test-executeFile.js +167 -167
  126. package/node_modules/ibm_db/test/test-executeFileSync.js +85 -85
  127. package/node_modules/ibm_db/test/test-fetch-apis.js +146 -146
  128. package/node_modules/ibm_db/test/test-fetchN.js +130 -130
  129. package/node_modules/ibm_db/test/test-getinfo.js +197 -197
  130. package/node_modules/ibm_db/test/test-ibm-db-issue14.js +58 -58
  131. package/node_modules/ibm_db/test/test-ibm-db-issue17.js +54 -54
  132. package/node_modules/ibm_db/test/test-ibm-db-issue18.js +54 -54
  133. package/node_modules/ibm_db/test/test-issue-1059-fetchAll-undefined.js +67 -67
  134. package/node_modules/ibm_db/test/test-issue-1080-array-blob-insert.js +40 -0
  135. package/node_modules/ibm_db/test/test-issue-54.js +39 -39
  136. package/node_modules/ibm_db/test/test-issue-get-column-value-2.js +44 -44
  137. package/node_modules/ibm_db/test/test-issue211.js +80 -80
  138. package/node_modules/ibm_db/test/test-issue253.js +39 -39
  139. package/node_modules/ibm_db/test/test-max-pool-size.js +96 -96
  140. package/node_modules/ibm_db/test/test-memory-leaks-new-objects.js +32 -32
  141. package/node_modules/ibm_db/test/test-multi-open-query-close.js +75 -75
  142. package/node_modules/ibm_db/test/test-param-put-data.js +713 -0
  143. package/node_modules/ibm_db/test/test-pool-idle-connection.js +72 -72
  144. package/node_modules/ibm_db/test/test-pool-operations.js +325 -0
  145. package/node_modules/ibm_db/test/test-pool-stale-connections.js +111 -111
  146. package/node_modules/ibm_db/test/test-pool-uncommited.js +33 -33
  147. package/node_modules/ibm_db/test/test-prepare-execute.js +339 -0
  148. package/node_modules/ibm_db/test/test-prepareSync-multiple-execution.js +93 -93
  149. package/node_modules/ibm_db/test/test-primary-foreign-keys.js +246 -0
  150. package/node_modules/ibm_db/test/test-procedures.js +243 -0
  151. package/node_modules/ibm_db/test/test-promise-all-data-types.js +42 -42
  152. package/node_modules/ibm_db/test/test-query-operations.js +405 -0
  153. package/node_modules/ibm_db/test/test-quick-example.js +25 -25
  154. package/node_modules/ibm_db/test/test-row-array-insert.js +167 -167
  155. package/node_modules/ibm_db/test/test-sp-array.js +54 -54
  156. package/node_modules/ibm_db/test/test-sp-dbc-6000.js +88 -88
  157. package/node_modules/ibm_db/test/test-sp-memleak.js +136 -136
  158. package/node_modules/ibm_db/test/test-sp-resultset-execute.js +269 -269
  159. package/node_modules/ibm_db/test/test-sp-resultset.js +228 -228
  160. package/node_modules/ibm_db/test/test-transactions.js +261 -0
  161. package/node_modules/ibm_db/test/test-typescript.js +48 -48
  162. package/node_modules/ibm_db/test/test-xml-datatype.js +70 -70
  163. package/node_modules/ibm_db/test/testWebApp.js +56 -56
  164. package/node_modules/ibm_db/test/trace +51 -51
  165. package/node_modules/ibm_db/test/typescript-apis-test.js +978 -978
  166. package/node_modules/ibm_db/test/webapp.html +17 -17
  167. package/node_modules/ibm_db/test/webapp.js +79 -79
  168. package/node_modules/ibm_db/typescript/README.md +28 -28
  169. package/node_modules/ibm_db/typescript/dist/Database.d.ts +26 -0
  170. package/node_modules/ibm_db/typescript/dist/ODBCStatement.d.ts +93 -0
  171. package/package.json +10 -6
  172. package/node_modules/ibm_db/test/disabled/test-binding-statement-rebinding.js +0 -59
  173. package/node_modules/ibm_db/test/disabled/test-open-dont-close.js +0 -12
  174. package/node_modules/ibm_db/test/disabled/test-param-select-with-booleans-only.js +0 -21
  175. package/node_modules/ibm_db/test/disabled/test-param-select-with-decimals-only.js +0 -20
  176. package/node_modules/ibm_db/test/disabled/test-param-select-with-null.js +0 -21
  177. package/node_modules/ibm_db/test/disabled/test-param-select-with-nulls-mixed.js +0 -23
  178. package/node_modules/ibm_db/test/disabled/test-param-select-with-numbers-mixed.js +0 -22
  179. package/node_modules/ibm_db/test/disabled/test-param-select-with-numbers-only.js +0 -24
  180. package/node_modules/ibm_db/test/disabled/test-param-select-with-strings-only.js +0 -23
  181. package/node_modules/ibm_db/test/disabled/test-param-select-with-unicode.js +0 -15
  182. package/node_modules/ibm_db/test/disabled/test-prepare-bind-execute-closeSync.js +0 -62
  183. package/node_modules/ibm_db/test/disabled/test-prepare-bind-execute-error.js +0 -49
  184. package/node_modules/ibm_db/test/disabled/test-prepare-bind-execute-long-string.js +0 -63
  185. package/node_modules/ibm_db/test/disabled/test-prepare-bind-executeNonQuery.js +0 -63
  186. package/node_modules/ibm_db/test/disabled/test-prepare-bindSync-execute-closeSync.js +0 -46
  187. package/node_modules/ibm_db/test/disabled/test-prepare-bindSync-executeNonQuery.js +0 -50
  188. package/node_modules/ibm_db/test/disabled/test-prepare.js +0 -34
  189. package/node_modules/ibm_db/test/disabled/test-prepareSync.js +0 -29
  190. package/node_modules/ibm_db/test/disabled/test-query-select-fetchAll.js +0 -23
  191. package/node_modules/ibm_db/test/disabled/test-query-select-fetchAllSync.js +0 -23
  192. package/node_modules/ibm_db/test/disabled/test-query-select-unicode.js +0 -15
  193. package/node_modules/ibm_db/test/disabled/test-querySync-select-unicode.js +0 -20
  194. package/node_modules/ibm_db/test/test-affected-rows.js +0 -55
  195. package/node_modules/ibm_db/test/test-bad-connection-string.js +0 -30
  196. package/node_modules/ibm_db/test/test-binding-connection-timeOut.js +0 -31
  197. package/node_modules/ibm_db/test/test-binding-statement-executeSync.js +0 -84
  198. package/node_modules/ibm_db/test/test-binding-transaction-commit.js +0 -79
  199. package/node_modules/ibm_db/test/test-binding-transaction-commitSync.js +0 -53
  200. package/node_modules/ibm_db/test/test-closed.js +0 -14
  201. package/node_modules/ibm_db/test/test-connection-object.js +0 -16
  202. package/node_modules/ibm_db/test/test-describe-column.js +0 -92
  203. package/node_modules/ibm_db/test/test-describe-database.js +0 -18
  204. package/node_modules/ibm_db/test/test-describe-table.js +0 -31
  205. package/node_modules/ibm_db/test/test-domains-open.js +0 -19
  206. package/node_modules/ibm_db/test/test-global-open-close.js +0 -11
  207. package/node_modules/ibm_db/test/test-instantiate-one-and-end.js +0 -9
  208. package/node_modules/ibm_db/test/test-multi-open-close.js +0 -45
  209. package/node_modules/ibm_db/test/test-multi-openSync-closeSync.js +0 -52
  210. package/node_modules/ibm_db/test/test-open-close.js +0 -29
  211. package/node_modules/ibm_db/test/test-open-connectTimeout.js +0 -33
  212. package/node_modules/ibm_db/test/test-openSync.js +0 -31
  213. package/node_modules/ibm_db/test/test-pool-close.js +0 -120
  214. package/node_modules/ibm_db/test/test-pool-connect.js +0 -36
  215. package/node_modules/ibm_db/test/test-pool-rollbackTransaction.js +0 -35
  216. package/node_modules/ibm_db/test/test-prepareSync-bad-sql.js +0 -34
  217. package/node_modules/ibm_db/test/test-promise-open-close.js +0 -33
  218. package/node_modules/ibm_db/test/test-query-create-table-fetchSync.js +0 -23
  219. package/node_modules/ibm_db/test/test-query-create-table.js +0 -12
  220. package/node_modules/ibm_db/test/test-query-drop-table.js +0 -13
  221. package/node_modules/ibm_db/test/test-query-insert.js +0 -38
  222. package/node_modules/ibm_db/test/test-query-select-fetch.js +0 -21
  223. package/node_modules/ibm_db/test/test-query-select-fetchMode-array.js +0 -17
  224. package/node_modules/ibm_db/test/test-query-select.js +0 -64
  225. package/node_modules/ibm_db/test/test-queryResult.js +0 -35
  226. package/node_modules/ibm_db/test/test-queryStream.js +0 -43
  227. package/node_modules/ibm_db/test/test-querySync-select-with-exception.js +0 -25
  228. package/node_modules/ibm_db/test/test-querySync-select.js +0 -28
  229. package/node_modules/ibm_db/test/test-require-and-end.js +0 -8
  230. package/node_modules/ibm_db/test/test-statement-close.js +0 -118
  231. package/node_modules/ibm_db/test/test-transaction-commit-sync.js +0 -54
  232. package/node_modules/ibm_db/test/test-transaction-commit.js +0 -79
@@ -1,1612 +1,1762 @@
1
- /*
2
- Copyright (c) 2013, Dan VerWeire <dverweire@gmail.com>
3
- Copyright (c) 2010, Lee Smith<notwink@gmail.com>
4
-
5
- Permission to use, copy, modify, and/or distribute this software for any
6
- purpose with or without fee is hereby granted, provided that the above
7
- copyright notice and this permission notice appear in all copies.
8
-
9
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
- */
17
-
18
- #include <string.h>
19
- #include <time.h>
20
- #include <uv.h>
21
-
22
- #include "odbc.h"
23
- #include "odbc_connection.h"
24
- #include "odbc_result.h"
25
- #include "odbc_statement.h"
26
-
27
- Napi::FunctionReference ODBCConnection::constructor;
28
-
29
- Napi::Object ODBCConnection::Init(Napi::Env env, Napi::Object exports)
30
- {
31
- DEBUG_PRINTF("ODBCConnection::Init\n");
32
-
33
- Napi::Function func = DefineClass(env, "ODBCConnection", {
34
- InstanceMethod("open", &ODBCConnection::Open, NAPI_METHOD_ATTR),
35
- InstanceMethod("openSync", &ODBCConnection::OpenSync, NAPI_METHOD_ATTR),
36
- InstanceMethod("close", &ODBCConnection::Close, NAPI_METHOD_ATTR),
37
- InstanceMethod("closeSync", &ODBCConnection::CloseSync, NAPI_METHOD_ATTR),
38
- InstanceMethod("createDbSync", &ODBCConnection::CreateDbSync, NAPI_METHOD_ATTR),
39
- InstanceMethod("dropDbSync", &ODBCConnection::DropDbSync, NAPI_METHOD_ATTR),
40
- InstanceMethod("createStatement", &ODBCConnection::CreateStatement, NAPI_METHOD_ATTR),
41
- InstanceMethod("createStatementSync", &ODBCConnection::CreateStatementSync, NAPI_METHOD_ATTR),
42
- InstanceMethod("query", &ODBCConnection::Query, NAPI_METHOD_ATTR),
43
- InstanceMethod("querySync", &ODBCConnection::QuerySync, NAPI_METHOD_ATTR),
44
- InstanceMethod("beginTransaction", &ODBCConnection::BeginTransaction, NAPI_METHOD_ATTR),
45
- InstanceMethod("beginTransactionSync", &ODBCConnection::BeginTransactionSync, NAPI_METHOD_ATTR),
46
- InstanceMethod("endTransaction", &ODBCConnection::EndTransaction, NAPI_METHOD_ATTR),
47
- InstanceMethod("endTransactionSync", &ODBCConnection::EndTransactionSync, NAPI_METHOD_ATTR),
48
- InstanceMethod("setIsolationLevel", &ODBCConnection::SetIsolationLevel, NAPI_METHOD_ATTR),
49
- InstanceMethod("getInfo", &ODBCConnection::GetInfo, NAPI_METHOD_ATTR),
50
- InstanceMethod("getInfoSync", &ODBCConnection::GetInfoSync, NAPI_METHOD_ATTR),
51
- InstanceMethod("getTypeInfo", &ODBCConnection::GetTypeInfo, NAPI_METHOD_ATTR),
52
- InstanceMethod("getTypeInfoSync", &ODBCConnection::GetTypeInfoSync, NAPI_METHOD_ATTR),
53
- InstanceMethod("getFunctions", &ODBCConnection::GetFunctions, NAPI_METHOD_ATTR),
54
- InstanceMethod("getFunctionsSync", &ODBCConnection::GetFunctionsSync, NAPI_METHOD_ATTR),
55
- InstanceMethod("setAttr", &ODBCConnection::SetAttr, NAPI_METHOD_ATTR),
56
- InstanceMethod("setAttrSync", &ODBCConnection::SetAttrSync, NAPI_METHOD_ATTR),
57
- InstanceMethod("columns", &ODBCConnection::Columns, NAPI_METHOD_ATTR),
58
- InstanceMethod("tables", &ODBCConnection::Tables, NAPI_METHOD_ATTR),
59
- InstanceAccessor("connected", &ODBCConnection::ConnectedGetter, nullptr, napi_enumerable),
60
- InstanceAccessor("connectTimeout", &ODBCConnection::ConnectTimeoutGetter, &ODBCConnection::ConnectTimeoutSetter, napi_enumerable),
61
- InstanceAccessor("systemNaming", &ODBCConnection::SystemNamingGetter, &ODBCConnection::SystemNamingSetter, napi_enumerable),
62
- });
63
-
64
- constructor = Napi::Persistent(func);
65
- constructor.SuppressDestruct();
66
- exports.Set("ODBCConnection", func);
67
- return exports;
68
- }
69
-
70
- ODBCConnection::~ODBCConnection()
71
- {
72
- DEBUG_PRINTF("ODBCConnection::~ODBCConnection\n");
73
- this->Free();
74
- }
75
-
76
- void ODBCConnection::Free()
77
- {
78
- DEBUG_PRINTF("ODBCConnection::Free m_hDBC = %i \n", m_hDBC);
79
- if (m_hDBC)
80
- {
81
- SQLDisconnect(m_hDBC);
82
- SQLFreeHandle(SQL_HANDLE_DBC, m_hDBC);
83
- m_hDBC = (SQLHDBC)NULL;
84
- }
85
- }
86
-
87
- ODBCConnection::ODBCConnection(const Napi::CallbackInfo &info) : Napi::ObjectWrap<ODBCConnection>(info)
88
- {
89
- Napi::Env env = info.Env();
90
- DEBUG_PRINTF("ODBCConnection::New - Entry\n");
91
-
92
- if (info.Length() < 2 || !info[0].IsExternal() || !info[1].IsExternal())
93
- {
94
- Napi::TypeError::New(env, "ODBCConnection::New requires 2 external arguments").ThrowAsJavaScriptException();
95
- return;
96
- }
97
-
98
- m_hENV = (SQLHENV)((intptr_t)info[0].As<Napi::External<void>>().Data());
99
- m_hDBC = (SQLHDBC)((intptr_t)info[1].As<Napi::External<void>>().Data());
100
- connectTimeout = DEFAULT_CONNECTION_TIMEOUT;
101
- systemNaming = false;
102
- connected = false;
103
- statements = 0;
104
- canHaveMoreResults = 0;
105
-
106
- DEBUG_PRINTF("ODBCConnection::New - Exit\n");
107
- }
108
-
109
- Napi::Value ODBCConnection::ConnectedGetter(const Napi::CallbackInfo &info)
110
- {
111
- return Napi::Boolean::New(info.Env(), connected);
112
- }
113
-
114
- Napi::Value ODBCConnection::ConnectTimeoutGetter(const Napi::CallbackInfo &info)
115
- {
116
- return Napi::Number::New(info.Env(), connectTimeout);
117
- }
118
-
119
- void ODBCConnection::ConnectTimeoutSetter(const Napi::CallbackInfo &info, const Napi::Value &value)
120
- {
121
- if (value.IsNumber()) connectTimeout = value.As<Napi::Number>().Int32Value();
122
- }
123
-
124
- Napi::Value ODBCConnection::SystemNamingGetter(const Napi::CallbackInfo &info)
125
- {
126
- return Napi::Boolean::New(info.Env(), systemNaming);
127
- }
128
-
129
- void ODBCConnection::SystemNamingSetter(const Napi::CallbackInfo &info, const Napi::Value &value)
130
- {
131
- if (value.IsBoolean()) systemNaming = value.As<Napi::Boolean>().Value();
132
- }
133
-
134
- /*
135
- * Open
136
- */
137
- Napi::Value ODBCConnection::Open(const Napi::CallbackInfo &info)
138
- {
139
- DEBUG_PRINTF("ODBCConnection::Open - Entry\n");
140
- Napi::Env env = info.Env();
141
- int len = 0;
142
- const char *errmsg = NULL;
143
-
144
- REQ_STRO_ARG(0, connection);
145
- REQ_FUN_ARG(1, cb);
146
-
147
- uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
148
- MEMCHECK(work_req);
149
-
150
- open_connection_work_data *data = (open_connection_work_data *)calloc(1, sizeof(open_connection_work_data));
151
- MEMCHECK2(data, errmsg);
152
-
153
- len = (int)connection.length();
154
- data->connectionLength = len + 1;
155
- GETCPPSTR2(data->connection, connection, len, errmsg);
156
-
157
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
158
- data->conn = this;
159
- data->env = env;
160
- work_req->data = data;
161
-
162
- uv_queue_work(uv_default_loop(), work_req, UV_Open, (uv_after_work_cb)UV_AfterOpen);
163
- this->Ref();
164
-
165
- exit:
166
- DEBUG_PRINTF("ODBCConnection::Open - Exit\n");
167
- if (errmsg)
168
- {
169
- free(work_req);
170
- free(data);
171
- Napi::Error::New(env, errmsg).ThrowAsJavaScriptException();
172
- return env.Undefined();
173
- }
174
- return env.Undefined();
175
- }
176
-
177
- void ODBCConnection::UV_Open(uv_work_t *req)
178
- {
179
- DEBUG_PRINTF("ODBCConnection::UV_Open - Entry\n");
180
- open_connection_work_data *data = (open_connection_work_data *)(req->data);
181
- ODBCConnection *self = data->conn->self();
182
- SetConnectionAttributes(self);
183
-
184
- int ret = SQLDriverConnect(self->m_hDBC, NULL, (SQLTCHAR *)data->connection,
185
- data->connectionLength, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
186
-
187
- if (SQL_SUCCEEDED(ret))
188
- {
189
- SQLHSTMT hStmt;
190
- ret = SQLAllocHandle(SQL_HANDLE_STMT, self->m_hDBC, &hStmt);
191
- ret = SQLGetFunctions(self->m_hDBC, SQL_API_SQLMORERESULTS, &self->canHaveMoreResults);
192
- if (!SQL_SUCCEEDED(ret)) self->canHaveMoreResults = 0;
193
- ret = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
194
- }
195
- data->result = ret;
196
- DEBUG_PRINTF("ODBCConnection::UV_Open - Exit\n");
197
- }
198
-
199
- void ODBCConnection::UV_AfterOpen(uv_work_t *req, int status)
200
- {
201
- DEBUG_PRINTF("ODBCConnection::UV_AfterOpen - Entry\n");
202
- open_connection_work_data *data = (open_connection_work_data *)(req->data);
203
- Napi::Env env(data->env);
204
- Napi::HandleScope scope(env);
205
-
206
- if (data->result)
207
- {
208
- Napi::Value objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->self()->m_hDBC);
209
- data->conn->Unref();
210
- data->cb->Call({objError});
211
- }
212
- else
213
- {
214
- data->conn->self()->connected = true;
215
- data->conn->Unref();
216
- data->cb->Call({env.Null()});
217
- }
218
- PropagateCallbackException(env);
219
-
220
- delete data->cb;
221
- FREE(data->connection);
222
- FREE(data);
223
- FREE(req);
224
- DEBUG_PRINTF("ODBCConnection::UV_AfterOpen - Exit\n");
225
- }
226
-
227
- void ODBCConnection::SetConnectionAttributes(ODBCConnection *conn)
228
- {
229
- SQLUINTEGER timeOut = conn->connectTimeout;
230
- if (timeOut > 32767) timeOut = DEFAULT_CONNECTION_TIMEOUT;
231
- if (timeOut > 0)
232
- {
233
- SQLSetConnectAttr(conn->m_hDBC, SQL_ATTR_LOGIN_TIMEOUT,
234
- (SQLPOINTER)(intptr_t)timeOut, sizeof(timeOut));
235
- }
236
- #if !defined(__MVS__)
237
- if (conn->systemNaming)
238
- {
239
- SQLSetConnectAttr(conn->m_hDBC, SQL_ATTR_DBC_SYS_NAMING,
240
- (SQLPOINTER)SQL_TRUE, SQL_IS_INTEGER);
241
- }
242
- #endif
243
- }
244
-
245
- /*
246
- * OpenSync
247
- */
248
- Napi::Value ODBCConnection::OpenSync(const Napi::CallbackInfo &info)
249
- {
250
- DEBUG_PRINTF("ODBCConnection::OpenSync - Entry\n");
251
- Napi::Env env = info.Env();
252
-
253
- REQ_STRO_ARG(0, connection);
254
- int connectionLength = (int)connection.length();
255
-
256
- if (connectionLength <= 0)
257
- {
258
- Napi::TypeError::New(env, "Connection String must be a non-empty string").ThrowAsJavaScriptException();
259
- return env.Undefined();
260
- }
261
-
262
- void *connectionString = NULL;
263
- GETCPPSTR(connectionString, connection, connectionLength);
264
-
265
- SetConnectionAttributes(this);
266
-
267
- SQLRETURN ret = SQLDriverConnect(m_hDBC, NULL, (SQLTCHAR *)connectionString,
268
- connectionLength + 1, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
269
-
270
- if (!SQL_SUCCEEDED(ret))
271
- {
272
- Napi::Value objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC);
273
- FREE(connectionString);
274
- napi_throw(env, objError);
275
- return env.Undefined();
276
- }
277
-
278
- SQLHSTMT hStmt;
279
- SQLAllocHandle(SQL_HANDLE_STMT, m_hDBC, &hStmt);
280
- ret = SQLGetFunctions(m_hDBC, SQL_API_SQLMORERESULTS, &canHaveMoreResults);
281
- if (!SQL_SUCCEEDED(ret)) canHaveMoreResults = 0;
282
- SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
283
- self()->connected = true;
284
-
285
- FREE(connectionString);
286
- DEBUG_PRINTF("ODBCConnection::OpenSync - Exit\n");
287
- return Napi::Boolean::New(env, true);
288
- }
289
-
290
- /*
291
- * Close
292
- */
293
- Napi::Value ODBCConnection::Close(const Napi::CallbackInfo &info)
294
- {
295
- DEBUG_PRINTF("ODBCConnection::Close\n");
296
- Napi::Env env = info.Env();
297
- REQ_FUN_ARG(0, cb);
298
-
299
- uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
300
- MEMCHECK(work_req);
301
- close_connection_work_data *data = (close_connection_work_data *)(calloc(1, sizeof(close_connection_work_data)));
302
- if (!data) free(work_req);
303
- MEMCHECK(data);
304
-
305
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
306
- data->conn = this;
307
- data->env = env;
308
- work_req->data = data;
309
-
310
- uv_queue_work(uv_default_loop(), work_req, UV_Close, (uv_after_work_cb)UV_AfterClose);
311
- this->Ref();
312
- return env.Undefined();
313
- }
314
-
315
- void ODBCConnection::UV_Close(uv_work_t *req)
316
- {
317
- close_connection_work_data *data = (close_connection_work_data *)(req->data);
318
- data->conn->Free();
319
- data->conn->connected = false;
320
- data->result = 0;
321
- }
322
-
323
- void ODBCConnection::UV_AfterClose(uv_work_t *req, int status)
324
- {
325
- close_connection_work_data *data = (close_connection_work_data *)(req->data);
326
- Napi::Env env(data->env);
327
- Napi::HandleScope scope(env);
328
-
329
- if (data->result)
330
- data->cb->Call({Napi::Error::New(env, "Error closing database").Value()});
331
- else
332
- data->cb->Call({env.Null()});
333
- PropagateCallbackException(env);
334
-
335
- data->conn->Unref();
336
- delete data->cb;
337
- free(data);
338
- free(req);
339
- }
340
-
341
- /*
342
- * CloseSync
343
- */
344
- Napi::Value ODBCConnection::CloseSync(const Napi::CallbackInfo &info)
345
- {
346
- Napi::Env env = info.Env();
347
- this->Free();
348
- this->connected = false;
349
- return Napi::Boolean::New(env, true);
350
- }
351
-
352
- /*
353
- * CreateDbSync
354
- */
355
- Napi::Value ODBCConnection::CreateDbSync(const Napi::CallbackInfo &info)
356
- {
357
- Napi::Env env = info.Env();
358
- #ifdef __MVS__
359
- return Napi::Boolean::New(env, false);
360
- #else
361
- const char *errmsg = NULL;
362
- int dbNameLength = 0, codeSetLength = 0, modeLength = 0;
363
- void *databaseNameString = NULL, *codeSetString = NULL, *modeString = NULL;
364
- SQLRETURN ret = SQL_SUCCESS;
365
- bool err = false;
366
- Napi::Value objError;
367
-
368
- REQ_ARGS(3);
369
- REQ_STRO_ARG(0, dbName);
370
- dbNameLength = (int)dbName.length();
371
- if (dbNameLength <= 0)
372
- {
373
- Napi::TypeError::New(env, "Database name must be a String.").ThrowAsJavaScriptException();
374
- return env.Undefined();
375
- }
376
-
377
- REQ_STRO_OR_NULL_ARG(1, codeSet);
378
- codeSetLength = (int)codeSet.length();
379
- REQ_STRO_OR_NULL_ARG(2, mode);
380
- modeLength = (int)mode.length();
381
-
382
- GETCPPSTR2(databaseNameString, dbName, dbNameLength, errmsg);
383
- if (!info[1].IsNull()) { GETCPPSTR2(codeSetString, codeSet, codeSetLength, errmsg); }
384
- if (!info[2].IsNull()) { GETCPPSTR2(modeString, mode, modeLength, errmsg); }
385
-
386
- ret = SQLCreateDb(m_hDBC, (SQLTCHAR *)databaseNameString, dbNameLength + 1,
387
- (SQLTCHAR *)codeSetString, codeSetLength + 1,
388
- (SQLTCHAR *)modeString, modeLength + 1);
389
- if (!SQL_SUCCEEDED(ret)) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
390
- else
391
- {
392
- ret = SQLDisconnect(m_hDBC);
393
- if (!SQL_SUCCEEDED(ret)) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
394
- ret = SQLFreeHandle(SQL_HANDLE_DBC, m_hDBC);
395
- if (!SQL_SUCCEEDED(ret) && !err) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
396
- }
397
-
398
- exit:
399
- FREE(databaseNameString); FREE(codeSetString); FREE(modeString);
400
- if (errmsg) { Napi::Error::New(env, errmsg).ThrowAsJavaScriptException(); return env.Undefined(); }
401
- if (err) { napi_throw(env, objError); return env.Undefined(); }
402
- return Napi::Boolean::New(env, true);
403
- #endif
404
- }
405
-
406
- /*
407
- * DropDbSync
408
- */
409
- Napi::Value ODBCConnection::DropDbSync(const Napi::CallbackInfo &info)
410
- {
411
- Napi::Env env = info.Env();
412
- #ifdef __MVS__
413
- return Napi::Boolean::New(env, false);
414
- #else
415
- REQ_STRO_ARG(0, dbName);
416
- int dbNameLength = (int)dbName.length();
417
- if (dbNameLength <= 0) { Napi::TypeError::New(env, "Database name must be a string.").ThrowAsJavaScriptException(); return env.Undefined(); }
418
- void *databaseNameString = NULL;
419
- GETCPPSTR(databaseNameString, dbName, dbNameLength);
420
-
421
- SQLRETURN ret = SQLDropDb(m_hDBC, (SQLTCHAR *)databaseNameString, dbNameLength + 1);
422
- bool err = false; Napi::Value objError;
423
- if (!SQL_SUCCEEDED(ret)) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
424
- else
425
- {
426
- ret = SQLDisconnect(m_hDBC);
427
- if (!SQL_SUCCEEDED(ret)) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
428
- ret = SQLFreeHandle(SQL_HANDLE_DBC, m_hDBC);
429
- if (!SQL_SUCCEEDED(ret) && !err) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
430
- }
431
- FREE(databaseNameString);
432
- if (err) { napi_throw(env, objError); return env.Undefined(); }
433
- return Napi::Boolean::New(env, true);
434
- #endif
435
- }
436
-
437
- /*
438
- * CreateStatementSync
439
- */
440
- Napi::Value ODBCConnection::CreateStatementSync(const Napi::CallbackInfo &info)
441
- {
442
- Napi::Env env = info.Env();
443
- SQLHSTMT hSTMT;
444
- SQLAllocHandle(SQL_HANDLE_STMT, m_hDBC, &hSTMT);
445
-
446
- Napi::Value params[3] = {
447
- Napi::External<void>::New(env, (void *)(intptr_t)m_hENV),
448
- Napi::External<void>::New(env, (void *)(intptr_t)m_hDBC),
449
- Napi::External<void>::New(env, (void *)(intptr_t)hSTMT)
450
- };
451
- return ODBCStatement::constructor.New({params[0], params[1], params[2]});
452
- }
453
-
454
- /*
455
- * CreateStatement
456
- */
457
- Napi::Value ODBCConnection::CreateStatement(const Napi::CallbackInfo &info)
458
- {
459
- Napi::Env env = info.Env();
460
- REQ_FUN_ARG(0, cb);
461
-
462
- uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
463
- MEMCHECK(work_req);
464
- create_statement_work_data *data = (create_statement_work_data *)(calloc(1, sizeof(create_statement_work_data)));
465
- if (!data) free(work_req);
466
- MEMCHECK(data);
467
-
468
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
469
- data->conn = this;
470
- data->env = env;
471
- work_req->data = data;
472
-
473
- uv_queue_work(uv_default_loop(), work_req, UV_CreateStatement, (uv_after_work_cb)UV_AfterCreateStatement);
474
- this->Ref();
475
- return env.Undefined();
476
- }
477
-
478
- void ODBCConnection::UV_CreateStatement(uv_work_t *req)
479
- {
480
- create_statement_work_data *data = (create_statement_work_data *)(req->data);
481
- SQLAllocHandle(SQL_HANDLE_STMT, data->conn->m_hDBC, &data->hSTMT);
482
- }
483
-
484
- void ODBCConnection::UV_AfterCreateStatement(uv_work_t *req, int status)
485
- {
486
- create_statement_work_data *data = (create_statement_work_data *)(req->data);
487
- Napi::Env env(data->env);
488
- Napi::HandleScope scope(env);
489
-
490
- Napi::Value args[3] = {
491
- Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hENV),
492
- Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hDBC),
493
- Napi::External<void>::New(env, (void *)(intptr_t)data->hSTMT)
494
- };
495
- Napi::Object js_result = ODBCStatement::constructor.New({args[0], args[1], args[2]});
496
- data->cb->Call({env.Null(), js_result});
497
- PropagateCallbackException(env);
498
-
499
- data->conn->Unref();
500
- delete data->cb;
501
- free(data);
502
- free(req);
503
- }
504
-
505
- /*
506
- * Query
507
- */
508
- Napi::Value ODBCConnection::Query(const Napi::CallbackInfo &info)
509
- {
510
- DEBUG_PRINTF("ODBCConnection::Query - Entry\n");
511
- Napi::Env env = info.Env();
512
- Napi::Function cb;
513
- int len = 0;
514
- const char *errmsg = NULL;
515
- uv_work_t *work_req = NULL;
516
-
517
- query_work_data *data = (query_work_data *)calloc(1, sizeof(query_work_data));
518
- MEMCHECK2(data, errmsg);
519
- data->sql = NULL;
520
- data->params = NULL;
521
- data->paramCount = 0;
522
- data->noResultObject = false;
523
- data->arraySize = 0;
524
-
525
- if (info.Length() == 3)
526
- {
527
- if (!info[0].IsString()) { free(data); Napi::TypeError::New(env, "Argument 0 must be a String.").ThrowAsJavaScriptException(); return env.Undefined(); }
528
- if (!info[1].IsArray()) { free(data); Napi::TypeError::New(env, "Argument 1 must be an Array.").ThrowAsJavaScriptException(); return env.Undefined(); }
529
- if (!info[2].IsFunction()) { free(data); Napi::TypeError::New(env, "Argument 2 must be a Function.").ThrowAsJavaScriptException(); return env.Undefined(); }
530
-
531
- std::string sql = info[0].As<Napi::String>().Utf8Value();
532
- len = (int)sql.length();
533
- GETCPPSTR2(data->sql, sql, len, errmsg);
534
- data->params = ODBC::GetParametersFromArray(env, info[1].As<Napi::Array>(), &data->paramCount);
535
- cb = info[2].As<Napi::Function>();
536
- }
537
- else if (info.Length() == 2)
538
- {
539
- if (!info[1].IsFunction()) { free(data); Napi::TypeError::New(env, "Argument 1 must be a Function.").ThrowAsJavaScriptException(); return env.Undefined(); }
540
- cb = info[1].As<Napi::Function>();
541
-
542
- if (info[0].IsString())
543
- {
544
- std::string sql2 = info[0].As<Napi::String>().Utf8Value();
545
- len = (int)sql2.length();
546
- GETCPPSTR2(data->sql, sql2, len, errmsg);
547
- data->paramCount = 0;
548
- }
549
- else if (info[0].IsObject())
550
- {
551
- Napi::Object obj = info[0].As<Napi::Object>();
552
-
553
- if (obj.Has("sql") && obj.Get("sql").IsString())
554
- {
555
- std::string sql3 = obj.Get("sql").As<Napi::String>().Utf8Value();
556
- len = (int)sql3.length();
557
- GETCPPSTR2(data->sql, sql3, len, errmsg);
558
- }
559
- if (obj.Has("params") && obj.Get("params").IsArray())
560
- {
561
- data->params = ODBC::GetParametersFromArray(env, obj.Get("params").As<Napi::Array>(), &data->paramCount);
562
- }
563
- if (obj.Has("noResults") && obj.Get("noResults").IsBoolean())
564
- {
565
- data->noResultObject = obj.Get("noResults").As<Napi::Boolean>().Value();
566
- }
567
- if (obj.Has("ArraySize") && obj.Get("ArraySize").IsNumber())
568
- {
569
- data->arraySize = obj.Get("ArraySize").As<Napi::Number>().Int32Value();
570
- }
571
- }
572
- else
573
- {
574
- free(data);
575
- Napi::TypeError::New(env, "Argument 0 must be a String or an Object.").ThrowAsJavaScriptException();
576
- return env.Undefined();
577
- }
578
- }
579
- else
580
- {
581
- free(data);
582
- Napi::TypeError::New(env, "Requires either 2 or 3 Arguments.").ThrowAsJavaScriptException();
583
- return env.Undefined();
584
- }
585
-
586
- if (len <= 0) { free(data); Napi::TypeError::New(env, "SQL statement is missing.").ThrowAsJavaScriptException(); return env.Undefined(); }
587
-
588
- data->sqlLen = len;
589
- data->sqlSize = (len + 1) * sizeof(UNICHAR);
590
-
591
- work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
592
- MEMCHECK2(work_req, errmsg);
593
-
594
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
595
- data->conn = this;
596
- data->env = env;
597
- work_req->data = data;
598
-
599
- uv_queue_work(uv_default_loop(), work_req, UV_Query, (uv_after_work_cb)UV_AfterQuery);
600
- this->Ref();
601
-
602
- exit:
603
- if (errmsg)
604
- {
605
- if (data) { free(data->sql); free(data); }
606
- free(work_req);
607
- Napi::Error::New(env, errmsg).ThrowAsJavaScriptException();
608
- return env.Undefined();
609
- }
610
- return env.Undefined();
611
- }
612
-
613
- void ODBCConnection::UV_Query(uv_work_t *req)
614
- {
615
- query_work_data *data = (query_work_data *)(req->data);
616
- SQLRETURN ret;
617
-
618
- SQLAllocHandle(SQL_HANDLE_STMT, data->conn->m_hDBC, &data->hSTMT);
619
-
620
- if (!data->paramCount)
621
- {
622
- ret = SQLExecDirect(data->hSTMT, (SQLTCHAR *)data->sql, data->sqlLen);
623
- }
624
- else
625
- {
626
- ret = SQLPrepare(data->hSTMT, (SQLTCHAR *)data->sql, data->sqlLen);
627
- if (SQL_SUCCEEDED(ret))
628
- {
629
- if (data->arraySize > 0)
630
- {
631
- SQLSetStmtAttr(data->hSTMT, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0);
632
- SQLSetStmtAttr(data->hSTMT, SQL_ATTR_PARAMSET_SIZE,
633
- reinterpret_cast<SQLPOINTER>(static_cast<intptr_t>(data->arraySize)), 0);
634
- }
635
- ret = ODBC::BindParameters(data->hSTMT, data->params, data->paramCount);
636
- if (SQL_SUCCEEDED(ret))
637
- {
638
- ret = SQLExecute(data->hSTMT);
639
- if (ret == SQL_NEED_DATA)
640
- ret = ODBC::PutDataLoop(data->hSTMT, data->params, data->paramCount);
641
- }
642
- }
643
- }
644
- data->result = ret;
645
- }
646
-
647
- void ODBCConnection::UV_AfterQuery(uv_work_t *req, int status)
648
- {
649
- query_work_data *data = (query_work_data *)(req->data);
650
- Napi::Env env(data->env);
651
- Napi::HandleScope scope(env);
652
-
653
- Napi::Array sp_result = Napi::Array::New(env);
654
- int outParamCount = 0;
655
-
656
- if (SQL_SUCCEEDED(data->result))
657
- {
658
- for (int i = 0; i < data->paramCount; i++)
659
- {
660
- if (data->params[i].paramtype % 2 == 0)
661
- {
662
- sp_result.Set(outParamCount, ODBC::GetOutputParameter(env, &data->params[i]));
663
- outParamCount++;
664
- }
665
- }
666
- }
667
-
668
- if (data->result == SQL_NO_DATA_FOUND) data->result = SQL_SUCCESS;
669
-
670
- if ((data->result >= SQL_SUCCESS) && (data->noResultObject))
671
- {
672
- SQLFreeHandle(SQL_HANDLE_STMT, data->hSTMT);
673
- data->hSTMT = (SQLHSTMT)NULL;
674
-
675
- if (outParamCount)
676
- data->cb->Call({env.Null(), sp_result});
677
- else
678
- data->cb->Call({env.Null(), env.Null()});
679
- }
680
- else
681
- {
682
- if (data->result != SQL_SUCCESS)
683
- {
684
- Napi::Value err = ODBC::GetSQLError(env, SQL_HANDLE_STMT, data->hSTMT, (char *)"[ibm_db] SQL_ERROR");
685
- SQLFreeHandle(SQL_HANDLE_STMT, data->hSTMT);
686
- data->hSTMT = (SQLHSTMT)NULL;
687
- data->cb->Call({err, env.Null(), outParamCount ? (Napi::Value)sp_result : env.Null()});
688
- }
689
- else
690
- {
691
- bool *canFreeHandle = new bool(true);
692
- Napi::Value js_args[4] = {
693
- Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hENV),
694
- Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hDBC),
695
- Napi::External<void>::New(env, (void *)(intptr_t)data->hSTMT),
696
- Napi::External<void>::New(env, (void *)canFreeHandle)
697
- };
698
- Napi::Object js_result = ODBCResult::constructor.New({js_args[0], js_args[1], js_args[2], js_args[3]});
699
- data->cb->Call({env.Null(), js_result, outParamCount ? (Napi::Value)sp_result : env.Null()});
700
- }
701
- }
702
- PropagateCallbackException(env);
703
-
704
- data->conn->Unref();
705
- delete data->cb;
706
- if (data->paramCount) { FREE_PARAMS(data->params, data->paramCount); }
707
- FREE(data->sql); FREE(data->catalog); FREE(data->schema);
708
- FREE(data->table); FREE(data->type); FREE(data->column);
709
- FREE(data); FREE(req);
710
- }
711
-
712
- /*
713
- * QuerySync
714
- */
715
- Napi::Value ODBCConnection::QuerySync(const Napi::CallbackInfo &info)
716
- {
717
- DEBUG_PRINTF("ODBCConnection::QuerySync - Entry\n");
718
- Napi::Env env = info.Env();
719
- void *sql = NULL;
720
- Parameter *params = NULL;
721
- SQLRETURN ret;
722
- SQLHSTMT hSTMT;
723
- int paramCount = 0, outParamCount = 0;
724
- Napi::Array sp_result = Napi::Array::New(env);
725
- bool noResultObject = false;
726
- int32_t arraySize = 0;
727
- int len = 0;
728
-
729
- if (info.Length() == 2)
730
- {
731
- if (!info[0].IsString()) { Napi::TypeError::New(env, "Argument 0 must be a String.").ThrowAsJavaScriptException(); return env.Undefined(); }
732
- if (!info[1].IsArray()) { Napi::TypeError::New(env, "Argument 1 must be an Array.").ThrowAsJavaScriptException(); return env.Undefined(); }
733
- std::string sql1 = info[0].As<Napi::String>().Utf8Value();
734
- len = (int)sql1.length();
735
- GETCPPSTR(sql, sql1, len);
736
- params = ODBC::GetParametersFromArray(env, info[1].As<Napi::Array>(), &paramCount);
737
- }
738
- else if (info.Length() == 1)
739
- {
740
- if (info[0].IsString())
741
- {
742
- std::string sql2 = info[0].As<Napi::String>().Utf8Value();
743
- len = (int)sql2.length();
744
- GETCPPSTR(sql, sql2, len);
745
- }
746
- else if (info[0].IsObject())
747
- {
748
- Napi::Object obj = info[0].As<Napi::Object>();
749
- if (obj.Has("sql") && obj.Get("sql").IsString()) {
750
- std::string sql3 = obj.Get("sql").As<Napi::String>().Utf8Value();
751
- len = (int)sql3.length();
752
- GETCPPSTR(sql, sql3, len);
753
- }
754
- if (obj.Has("params") && obj.Get("params").IsArray())
755
- params = ODBC::GetParametersFromArray(env, obj.Get("params").As<Napi::Array>(), &paramCount);
756
- if (obj.Has("noResults") && obj.Get("noResults").IsBoolean())
757
- noResultObject = obj.Get("noResults").As<Napi::Boolean>().Value();
758
- if (obj.Has("ArraySize") && obj.Get("ArraySize").IsNumber())
759
- arraySize = obj.Get("ArraySize").As<Napi::Number>().Int32Value();
760
- }
761
- else
762
- {
763
- Napi::TypeError::New(env, "Argument 0 must be a String or an Object.").ThrowAsJavaScriptException();
764
- return env.Undefined();
765
- }
766
- }
767
- else
768
- {
769
- Napi::TypeError::New(env, "Requires 1 or 2 Arguments.").ThrowAsJavaScriptException();
770
- return env.Undefined();
771
- }
772
-
773
- if (len <= 0) { Napi::TypeError::New(env, "SQL statement is missing.").ThrowAsJavaScriptException(); return env.Undefined(); }
774
-
775
- ret = SQLAllocHandle(SQL_HANDLE_STMT, m_hDBC, &hSTMT);
776
- if (!SQL_SUCCEEDED(ret)) { /* fall through */ }
777
- else if (!paramCount)
778
- {
779
- ret = SQLExecDirect(hSTMT, (SQLTCHAR *)sql, len);
780
- }
781
- else
782
- {
783
- ret = SQLPrepare(hSTMT, (SQLTCHAR *)sql, len);
784
- if (SQL_SUCCEEDED(ret))
785
- {
786
- if (arraySize > 0) {
787
- SQLSetStmtAttr(hSTMT, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0);
788
- SQLSetStmtAttr(hSTMT, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast<SQLPOINTER>(static_cast<intptr_t>(arraySize)), 0);
789
- }
790
- ret = ODBC::BindParameters(hSTMT, params, paramCount);
791
- if (SQL_SUCCEEDED(ret))
792
- {
793
- ret = SQLExecute(hSTMT);
794
- if (ret == SQL_NEED_DATA) ret = ODBC::PutDataLoop(hSTMT, params, paramCount);
795
- if (SQL_SUCCEEDED(ret))
796
- {
797
- for (int i = 0; i < paramCount; i++)
798
- {
799
- if (params[i].paramtype % 2 == 0)
800
- {
801
- sp_result.Set(outParamCount, ODBC::GetOutputParameter(env, &params[i]));
802
- outParamCount++;
803
- }
804
- }
805
- }
806
- }
807
- }
808
- }
809
-
810
- FREE(sql);
811
- FREE_PARAMS(params, paramCount);
812
-
813
- if (ret == SQL_NO_DATA_FOUND) ret = SQL_SUCCESS;
814
-
815
- if (ret != SQL_SUCCESS)
816
- {
817
- Napi::Value err = ODBC::GetSQLError(env, SQL_HANDLE_STMT, hSTMT, (char *)"[node-ibm_db] Error in ODBCConnection::QuerySync while executing query.");
818
- SQLFreeHandle(SQL_HANDLE_STMT, hSTMT);
819
- napi_throw(env, err);
820
- return env.Undefined();
821
- }
822
- else if (noResultObject)
823
- {
824
- SQLFreeHandle(SQL_HANDLE_STMT, hSTMT);
825
- if (outParamCount) {
826
- Napi::Array resultset = Napi::Array::New(env);
827
- resultset.Set((uint32_t)0, env.Null());
828
- resultset.Set((uint32_t)1, sp_result);
829
- return resultset;
830
- }
831
- return env.Null();
832
- }
833
- else
834
- {
835
- bool *canFreeHandle = new bool(true);
836
- Napi::Value result[4] = {
837
- Napi::External<void>::New(env, (void *)(intptr_t)m_hENV),
838
- Napi::External<void>::New(env, (void *)(intptr_t)m_hDBC),
839
- Napi::External<void>::New(env, (void *)(intptr_t)hSTMT),
840
- Napi::External<void>::New(env, (void *)canFreeHandle)
841
- };
842
- Napi::Object js_result = ODBCResult::constructor.New({result[0], result[1], result[2], result[3]});
843
-
844
- if (outParamCount) {
845
- Napi::Array resultset = Napi::Array::New(env);
846
- resultset.Set((uint32_t)0, js_result);
847
- resultset.Set((uint32_t)1, sp_result);
848
- return resultset;
849
- }
850
- return js_result;
851
- }
852
- }
853
-
854
- /*
855
- * Tables
856
- */
857
- Napi::Value ODBCConnection::Tables(const Napi::CallbackInfo &info)
858
- {
859
- Napi::Env env = info.Env();
860
- int len = 0;
861
- const char *errmsg = NULL;
862
- uv_work_t *work_req = NULL;
863
- query_work_data *data = NULL;
864
-
865
- REQ_STRO_OR_NULL_ARG(0, catalog);
866
- REQ_STRO_OR_NULL_ARG(1, schema);
867
- REQ_STRO_OR_NULL_ARG(2, table);
868
- REQ_STRO_OR_NULL_ARG(3, type);
869
- REQ_FUN_ARG(4, cb);
870
-
871
- work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
872
- MEMCHECK2(work_req, errmsg);
873
- data = (query_work_data *)calloc(1, sizeof(query_work_data));
874
- MEMCHECK2(data, errmsg);
875
-
876
- data->sql = NULL; data->catalog = NULL; data->schema = NULL;
877
- data->table = NULL; data->type = NULL; data->column = NULL;
878
-
879
- len = (int)catalog.length(); GETCPPSTR2(data->catalog, catalog, len, errmsg);
880
- len = (int)schema.length(); GETCPPSTR2(data->schema, schema, len, errmsg);
881
- len = (int)table.length(); GETCPPSTR2(data->table, table, len, errmsg);
882
- len = (int)type.length(); GETCPPSTR2(data->type, type, len, errmsg);
883
-
884
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
885
- data->conn = this;
886
- data->env = env;
887
- work_req->data = data;
888
-
889
- uv_queue_work(uv_default_loop(), work_req, UV_Tables, (uv_after_work_cb)UV_AfterQuery);
890
- this->Ref();
891
-
892
- exit:
893
- if (errmsg)
894
- {
895
- if (data) { FREE(data->catalog); FREE(data->schema); FREE(data->table); FREE(data->type); free(data); }
896
- free(work_req);
897
- Napi::Error::New(env, errmsg).ThrowAsJavaScriptException();
898
- return env.Undefined();
899
- }
900
- return env.Undefined();
901
- }
902
-
903
- void ODBCConnection::UV_Tables(uv_work_t *req)
904
- {
905
- query_work_data *data = (query_work_data *)(req->data);
906
- SQLAllocHandle(SQL_HANDLE_STMT, data->conn->m_hDBC, &data->hSTMT);
907
-
908
- SQLRETURN ret = SQLTables(data->hSTMT,
909
- #ifdef __MVS__
910
- NULL, 0,
911
- #else
912
- (SQLTCHAR *)data->catalog, SQL_NTS,
913
- #endif
914
- (SQLTCHAR *)data->schema, SQL_NTS,
915
- (SQLTCHAR *)data->table, SQL_NTS,
916
- (SQLTCHAR *)data->type, SQL_NTS);
917
-
918
- data->result = ret;
919
- FREE(data->catalog); FREE(data->schema); FREE(data->table); FREE(data->type);
920
- }
921
-
922
- /*
923
- * Columns
924
- */
925
- Napi::Value ODBCConnection::Columns(const Napi::CallbackInfo &info)
926
- {
927
- Napi::Env env = info.Env();
928
- int len = 0;
929
- const char *errmsg = NULL;
930
- uv_work_t *work_req = NULL;
931
- query_work_data *data = NULL;
932
-
933
- REQ_STRO_OR_NULL_ARG(0, catalog);
934
- REQ_STRO_OR_NULL_ARG(1, schema);
935
- REQ_STRO_OR_NULL_ARG(2, table);
936
- REQ_STRO_OR_NULL_ARG(3, column);
937
- REQ_FUN_ARG(4, cb);
938
-
939
- work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
940
- MEMCHECK(work_req);
941
- data = (query_work_data *)calloc(1, sizeof(query_work_data));
942
- MEMCHECK2(data, errmsg);
943
-
944
- data->sql = NULL; data->catalog = NULL; data->schema = NULL;
945
- data->table = NULL; data->type = NULL; data->column = NULL;
946
-
947
- len = (int)catalog.length(); GETCPPSTR2(data->catalog, catalog, len, errmsg);
948
- len = (int)schema.length(); GETCPPSTR2(data->schema, schema, len, errmsg);
949
- len = (int)table.length(); GETCPPSTR2(data->table, table, len, errmsg);
950
- len = (int)column.length(); GETCPPSTR2(data->column, column, len, errmsg);
951
-
952
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
953
- data->conn = this;
954
- data->env = env;
955
- work_req->data = data;
956
-
957
- uv_queue_work(uv_default_loop(), work_req, UV_Columns, (uv_after_work_cb)UV_AfterQuery);
958
- this->Ref();
959
-
960
- exit:
961
- if (errmsg)
962
- {
963
- if (data) { FREE(data->catalog); FREE(data->schema); FREE(data->table); FREE(data->column); free(data); }
964
- free(work_req);
965
- Napi::Error::New(env, errmsg).ThrowAsJavaScriptException();
966
- return env.Undefined();
967
- }
968
- return env.Undefined();
969
- }
970
-
971
- void ODBCConnection::UV_Columns(uv_work_t *req)
972
- {
973
- query_work_data *data = (query_work_data *)(req->data);
974
- SQLAllocHandle(SQL_HANDLE_STMT, data->conn->m_hDBC, &data->hSTMT);
975
-
976
- SQLRETURN ret = SQLColumns(data->hSTMT,
977
- #ifdef __MVS__
978
- NULL, 0,
979
- #else
980
- (SQLTCHAR *)data->catalog, SQL_NTS,
981
- #endif
982
- (SQLTCHAR *)data->schema, SQL_NTS,
983
- (SQLTCHAR *)data->table, SQL_NTS,
984
- (SQLTCHAR *)data->column, SQL_NTS);
985
-
986
- data->result = ret;
987
- FREE(data->catalog); FREE(data->schema); FREE(data->table); FREE(data->column);
988
- }
989
-
990
- /*
991
- * BeginTransactionSync
992
- */
993
- Napi::Value ODBCConnection::BeginTransactionSync(const Napi::CallbackInfo &info)
994
- {
995
- Napi::Env env = info.Env();
996
- SQLRETURN ret = SQLSetConnectAttr(m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_NTS);
997
- if (!SQL_SUCCEEDED(ret))
998
- {
999
- napi_throw(env, ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC));
1000
- return Napi::Boolean::New(env, false);
1001
- }
1002
- return Napi::Boolean::New(env, true);
1003
- }
1004
-
1005
- /*
1006
- * BeginTransaction
1007
- */
1008
- Napi::Value ODBCConnection::BeginTransaction(const Napi::CallbackInfo &info)
1009
- {
1010
- Napi::Env env = info.Env();
1011
- REQ_FUN_ARG(0, cb);
1012
-
1013
- uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1014
- MEMCHECK(work_req);
1015
- query_work_data *data = (query_work_data *)calloc(1, sizeof(query_work_data));
1016
- if (!data) free(work_req);
1017
- MEMCHECK(data);
1018
-
1019
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1020
- data->conn = this;
1021
- data->env = env;
1022
- work_req->data = data;
1023
-
1024
- uv_queue_work(uv_default_loop(), work_req, UV_BeginTransaction, (uv_after_work_cb)UV_AfterBeginTransaction);
1025
- return env.Undefined();
1026
- }
1027
-
1028
- void ODBCConnection::UV_BeginTransaction(uv_work_t *req)
1029
- {
1030
- query_work_data *data = (query_work_data *)(req->data);
1031
- data->result = SQLSetConnectAttr(data->conn->self()->m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_NTS);
1032
- }
1033
-
1034
- void ODBCConnection::UV_AfterBeginTransaction(uv_work_t *req, int status)
1035
- {
1036
- open_connection_work_data *data = (open_connection_work_data *)(req->data);
1037
- Napi::Env env(data->env);
1038
- Napi::HandleScope scope(env);
1039
-
1040
- if (!SQL_SUCCEEDED(data->result))
1041
- data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->self()->m_hDBC)});
1042
- else
1043
- data->cb->Call({env.Null()});
1044
- PropagateCallbackException(env);
1045
-
1046
- delete data->cb;
1047
- free(data);
1048
- free(req);
1049
- }
1050
-
1051
- /*
1052
- * EndTransactionSync
1053
- */
1054
- Napi::Value ODBCConnection::EndTransactionSync(const Napi::CallbackInfo &info)
1055
- {
1056
- Napi::Env env = info.Env();
1057
- REQ_BOOL_ARG(0, rollback);
1058
-
1059
- SQLSMALLINT completionType = rollback ? SQL_ROLLBACK : SQL_COMMIT;
1060
- bool error = false;
1061
- Napi::Value objError;
1062
-
1063
- SQLRETURN ret = SQLEndTran(SQL_HANDLE_DBC, m_hDBC, completionType);
1064
- if (!SQL_SUCCEEDED(ret)) { error = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC); }
1065
-
1066
- ret = SQLSetConnectAttr(m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS);
1067
- if (!SQL_SUCCEEDED(ret) && !error) { error = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC); }
1068
-
1069
- if (error)
1070
- {
1071
- napi_throw(env, objError);
1072
- return Napi::Boolean::New(env, false);
1073
- }
1074
- return Napi::Boolean::New(env, true);
1075
- }
1076
-
1077
- /*
1078
- * EndTransaction
1079
- */
1080
- Napi::Value ODBCConnection::EndTransaction(const Napi::CallbackInfo &info)
1081
- {
1082
- Napi::Env env = info.Env();
1083
- REQ_BOOL_ARG(0, rollback);
1084
- REQ_FUN_ARG(1, cb);
1085
-
1086
- uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1087
- MEMCHECK(work_req);
1088
- query_work_data *data = (query_work_data *)calloc(1, sizeof(query_work_data));
1089
- if (!data) free(work_req);
1090
- MEMCHECK(data);
1091
-
1092
- data->completionType = rollback ? SQL_ROLLBACK : SQL_COMMIT;
1093
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1094
- data->conn = this;
1095
- data->env = env;
1096
- work_req->data = data;
1097
-
1098
- uv_queue_work(uv_default_loop(), work_req, UV_EndTransaction, (uv_after_work_cb)UV_AfterEndTransaction);
1099
- return env.Undefined();
1100
- }
1101
-
1102
- void ODBCConnection::UV_EndTransaction(uv_work_t *req)
1103
- {
1104
- query_work_data *data = (query_work_data *)(req->data);
1105
- SQLRETURN ret = SQLEndTran(SQL_HANDLE_DBC, data->conn->m_hDBC, data->completionType);
1106
- data->result = ret;
1107
- ret = SQLSetConnectAttr(data->conn->m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS);
1108
- if (!SQL_SUCCEEDED(ret) && SQL_SUCCEEDED(data->result)) data->result = ret;
1109
- }
1110
-
1111
- void ODBCConnection::UV_AfterEndTransaction(uv_work_t *req, int status)
1112
- {
1113
- open_connection_work_data *data = (open_connection_work_data *)(req->data);
1114
- Napi::Env env(data->env);
1115
- Napi::HandleScope scope(env);
1116
-
1117
- if (!SQL_SUCCEEDED(data->result))
1118
- data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->self()->m_hDBC)});
1119
- else
1120
- data->cb->Call({env.Null()});
1121
- PropagateCallbackException(env);
1122
-
1123
- delete data->cb;
1124
- free(data);
1125
- free(req);
1126
- }
1127
-
1128
- /*
1129
- * SetIsolationLevel
1130
- */
1131
- Napi::Value ODBCConnection::SetIsolationLevel(const Napi::CallbackInfo &info)
1132
- {
1133
- Napi::Env env = info.Env();
1134
- SQLUINTEGER isolationLevel = SQL_TXN_READ_COMMITTED;
1135
-
1136
- if (info.Length() > 0 && info[0].IsNumber())
1137
- isolationLevel = info[0].As<Napi::Number>().Uint32Value();
1138
- else if (info.Length() > 0)
1139
- {
1140
- Napi::TypeError::New(env, "Argument #0 must be an integer.").ThrowAsJavaScriptException();
1141
- return env.Undefined();
1142
- }
1143
-
1144
- SQLRETURN ret = SQLSetConnectAttr(m_hDBC, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)(intptr_t)isolationLevel, SQL_NTS);
1145
-
1146
- if (!SQL_SUCCEEDED(ret))
1147
- {
1148
- napi_throw(env, ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC));
1149
- return Napi::Boolean::New(env, false);
1150
- }
1151
- return Napi::Boolean::New(env, true);
1152
- }
1153
-
1154
- /*
1155
- * GetInfoSync
1156
- */
1157
- Napi::Value ODBCConnection::GetInfoSync(const Napi::CallbackInfo &info)
1158
- {
1159
- Napi::Env env = info.Env();
1160
- REQ_ARGS(2);
1161
- REQ_INT_ARG(0, infotype);
1162
- REQ_INT_ARG(1, infolen);
1163
-
1164
- SQLPOINTER rgbInfo = malloc(infolen);
1165
- MEMCHECK(rgbInfo);
1166
- SQLSMALLINT cbInfo = 0;
1167
- SQLRETURN ret = SQLGetInfo(m_hDBC, infotype, rgbInfo, infolen, &cbInfo);
1168
-
1169
- if (!SQL_SUCCEEDED(ret))
1170
- {
1171
- free(rgbInfo);
1172
- napi_throw(env, ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC));
1173
- return Napi::Boolean::New(env, false);
1174
- }
1175
-
1176
- Napi::Value value = getInfoValue(env, (SQLUSMALLINT)infotype, rgbInfo);
1177
- free(rgbInfo);
1178
- return value;
1179
- }
1180
-
1181
- /*
1182
- * GetInfo
1183
- */
1184
- Napi::Value ODBCConnection::GetInfo(const Napi::CallbackInfo &info)
1185
- {
1186
- Napi::Env env = info.Env();
1187
- REQ_ARGS(3);
1188
- REQ_INT_ARG(0, infotype);
1189
- REQ_INT_ARG(1, infolen);
1190
- REQ_FUN_ARG(2, cb);
1191
-
1192
- uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1193
- MEMCHECK(work_req);
1194
- getinfo_work_data *data = (getinfo_work_data *)calloc(1, sizeof(getinfo_work_data));
1195
- if (!data) free(work_req);
1196
- MEMCHECK(data);
1197
-
1198
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1199
- data->conn = this;
1200
- data->infoType = infotype;
1201
- data->buffLen = infolen;
1202
- data->env = env;
1203
- work_req->data = data;
1204
-
1205
- uv_queue_work(uv_default_loop(), work_req, UV_GetInfo, (uv_after_work_cb)UV_AfterGetInfo);
1206
- this->Ref();
1207
- return env.Undefined();
1208
- }
1209
-
1210
- void ODBCConnection::UV_GetInfo(uv_work_t *req)
1211
- {
1212
- getinfo_work_data *data = (getinfo_work_data *)(req->data);
1213
- SQLSMALLINT valueLen = 0;
1214
- data->buffer = malloc(data->buffLen);
1215
- if (!data->buffer) { data->rc = SQL_ERROR; return; }
1216
- data->rc = SQLGetInfo(data->conn->m_hDBC, data->infoType, data->buffer, data->buffLen, &valueLen);
1217
- data->valueLen = valueLen;
1218
- }
1219
-
1220
- void ODBCConnection::UV_AfterGetInfo(uv_work_t *req, int status)
1221
- {
1222
- getinfo_work_data *data = (getinfo_work_data *)(req->data);
1223
- Napi::Env env(data->env);
1224
- Napi::HandleScope scope(env);
1225
-
1226
- if (data->rc != SQL_SUCCESS)
1227
- data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->m_hDBC, (char *)"[node-ibm_db] SQL_ERROR"), env.Null()});
1228
- else
1229
- data->cb->Call({env.Null(), getInfoValue(env, data->infoType, data->buffer)});
1230
- PropagateCallbackException(env);
1231
-
1232
- data->conn->Unref();
1233
- delete data->cb;
1234
- free(data->buffer);
1235
- free(data);
1236
- free(req);
1237
- }
1238
-
1239
- /*
1240
- * GetTypeInfoSync
1241
- */
1242
- Napi::Value ODBCConnection::GetTypeInfoSync(const Napi::CallbackInfo &info)
1243
- {
1244
- Napi::Env env = info.Env();
1245
- REQ_ARGS(1);
1246
- REQ_INT_ARG(0, dataType);
1247
-
1248
- SQLHSTMT hSTMT;
1249
- SQLAllocHandle(SQL_HANDLE_STMT, m_hDBC, &hSTMT);
1250
- SQLRETURN ret = SQLGetTypeInfo(hSTMT, (SQLSMALLINT)dataType);
1251
-
1252
- if (!SQL_SUCCEEDED(ret))
1253
- {
1254
- Napi::Value err = ODBC::GetSQLError(env, SQL_HANDLE_STMT, hSTMT);
1255
- SQLFreeHandle(SQL_HANDLE_STMT, hSTMT);
1256
- napi_throw(env, err);
1257
- return Napi::Boolean::New(env, false);
1258
- }
1259
-
1260
- bool *canFreeHandle = new bool(true);
1261
- Napi::Value args[4] = {
1262
- Napi::External<void>::New(env, (void *)(intptr_t)m_hENV),
1263
- Napi::External<void>::New(env, (void *)(intptr_t)m_hDBC),
1264
- Napi::External<void>::New(env, (void *)(intptr_t)hSTMT),
1265
- Napi::External<void>::New(env, (void *)canFreeHandle)
1266
- };
1267
- return ODBCResult::constructor.New({args[0], args[1], args[2], args[3]});
1268
- }
1269
-
1270
- Napi::Value ODBCConnection::GetTypeInfo(const Napi::CallbackInfo &info)
1271
- {
1272
- Napi::Env env = info.Env();
1273
- REQ_ARGS(2);
1274
- REQ_INT_ARG(0, dataType);
1275
- REQ_FUN_ARG(1, cb);
1276
-
1277
- uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1278
- MEMCHECK(work_req);
1279
- gettypeinfo_work_data *data = (gettypeinfo_work_data *)calloc(1, sizeof(gettypeinfo_work_data));
1280
- if (!data) free(work_req);
1281
- MEMCHECK(data);
1282
-
1283
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1284
- data->conn = this;
1285
- data->dataType = (SQLSMALLINT)dataType;
1286
- data->env = env;
1287
- work_req->data = data;
1288
-
1289
- uv_queue_work(uv_default_loop(), work_req, UV_GetTypeInfo, (uv_after_work_cb)UV_AfterGetTypeInfo);
1290
- this->Ref();
1291
- return env.Undefined();
1292
- }
1293
-
1294
- void ODBCConnection::UV_GetTypeInfo(uv_work_t *req)
1295
- {
1296
- gettypeinfo_work_data *data = (gettypeinfo_work_data *)(req->data);
1297
- SQLAllocHandle(SQL_HANDLE_STMT, data->conn->m_hDBC, &data->hSTMT);
1298
- data->result = SQLGetTypeInfo(data->hSTMT, data->dataType);
1299
- }
1300
-
1301
- void ODBCConnection::UV_AfterGetTypeInfo(uv_work_t *req, int status)
1302
- {
1303
- gettypeinfo_work_data *data = (gettypeinfo_work_data *)(req->data);
1304
- Napi::Env env(data->env);
1305
- Napi::HandleScope scope(env);
1306
-
1307
- if (!SQL_SUCCEEDED(data->result))
1308
- {
1309
- data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_STMT, data->hSTMT), env.Null()});
1310
- SQLFreeHandle(SQL_HANDLE_STMT, data->hSTMT);
1311
- }
1312
- else
1313
- {
1314
- bool *canFreeHandle = new bool(true);
1315
- Napi::Value args[4] = {
1316
- Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hENV),
1317
- Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hDBC),
1318
- Napi::External<void>::New(env, (void *)(intptr_t)data->hSTMT),
1319
- Napi::External<void>::New(env, (void *)canFreeHandle)
1320
- };
1321
- Napi::Object js_result = ODBCResult::constructor.New({args[0], args[1], args[2], args[3]});
1322
- data->cb->Call({env.Null(), js_result});
1323
- }
1324
- PropagateCallbackException(env);
1325
-
1326
- data->conn->Unref();
1327
- delete data->cb;
1328
- free(data);
1329
- free(req);
1330
- }
1331
-
1332
- /*
1333
- * GetFunctionsSync
1334
- */
1335
- Napi::Value ODBCConnection::GetFunctionsSync(const Napi::CallbackInfo &info)
1336
- {
1337
- Napi::Env env = info.Env();
1338
- REQ_ARGS(1);
1339
- REQ_UINT_ARG(0, functionId);
1340
-
1341
- SQLUSMALLINT funcId = (SQLUSMALLINT)functionId;
1342
- SQLUSMALLINT supportedPtr = 0;
1343
- SQLUSMALLINT supportedArr[100] = {0};
1344
- SQLRETURN ret;
1345
-
1346
- if (funcId)
1347
- ret = SQLGetFunctions(m_hDBC, funcId, &supportedPtr);
1348
- else
1349
- ret = SQLGetFunctions(m_hDBC, funcId, supportedArr);
1350
-
1351
- if (!SQL_SUCCEEDED(ret))
1352
- {
1353
- napi_throw(env, ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC));
1354
- return Napi::Boolean::New(env, false);
1355
- }
1356
-
1357
- if (funcId)
1358
- return Napi::Number::New(env, supportedPtr);
1359
-
1360
- Napi::Array value = Napi::Array::New(env, 100);
1361
- for (uint32_t i = 0; i < 100; i++)
1362
- value.Set(i, Napi::Number::New(env, supportedArr[i]));
1363
- return value;
1364
- }
1365
-
1366
- Napi::Value ODBCConnection::GetFunctions(const Napi::CallbackInfo &info)
1367
- {
1368
- Napi::Env env = info.Env();
1369
- REQ_ARGS(2);
1370
- REQ_UINT_ARG(0, functionId);
1371
- REQ_FUN_ARG(1, cb);
1372
-
1373
- uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1374
- MEMCHECK(work_req);
1375
- getfunctions_work_data *data = (getfunctions_work_data *)calloc(1, sizeof(getfunctions_work_data));
1376
- if (!data) free(work_req);
1377
- MEMCHECK(data);
1378
-
1379
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1380
- data->conn = this;
1381
- data->functionId = (SQLUSMALLINT)functionId;
1382
- data->env = env;
1383
- work_req->data = data;
1384
-
1385
- uv_queue_work(uv_default_loop(), work_req, UV_GetFunctions, (uv_after_work_cb)UV_AfterGetFunctions);
1386
- this->Ref();
1387
- return env.Undefined();
1388
- }
1389
-
1390
- void ODBCConnection::UV_GetFunctions(uv_work_t *req)
1391
- {
1392
- getfunctions_work_data *data = (getfunctions_work_data *)(req->data);
1393
-
1394
- if (data->functionId)
1395
- data->result = SQLGetFunctions(data->conn->m_hDBC, data->functionId, &data->supportedPtr);
1396
- else
1397
- data->result = SQLGetFunctions(data->conn->m_hDBC, data->functionId, data->supportedArr);
1398
- }
1399
-
1400
- void ODBCConnection::UV_AfterGetFunctions(uv_work_t *req, int status)
1401
- {
1402
- getfunctions_work_data *data = (getfunctions_work_data *)(req->data);
1403
- Napi::Env env(data->env);
1404
- Napi::HandleScope scope(env);
1405
-
1406
- if (!SQL_SUCCEEDED(data->result))
1407
- data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->m_hDBC), env.Null()});
1408
- else
1409
- {
1410
- if (data->functionId)
1411
- data->cb->Call({env.Null(), Napi::Number::New(env, data->supportedPtr)});
1412
- else
1413
- {
1414
- Napi::Array value = Napi::Array::New(env, 100);
1415
- for (uint32_t i = 0; i < 100; i++)
1416
- value.Set(i, Napi::Number::New(env, data->supportedArr[i]));
1417
- data->cb->Call({env.Null(), value});
1418
- }
1419
- }
1420
- PropagateCallbackException(env);
1421
-
1422
- data->conn->Unref();
1423
- delete data->cb;
1424
- free(data);
1425
- free(req);
1426
- }
1427
-
1428
- /*
1429
- * SetAttrSync
1430
- */
1431
- Napi::Value ODBCConnection::SetAttrSync(const Napi::CallbackInfo &info)
1432
- {
1433
- Napi::Env env = info.Env();
1434
- REQ_ARGS(2);
1435
- REQ_INT_ARG(0, attr);
1436
-
1437
- SQLPOINTER valuePtr = NULL;
1438
- SQLINTEGER stringLength = SQL_IS_INTEGER;
1439
-
1440
- if (info[1].IsNumber())
1441
- valuePtr = reinterpret_cast<SQLPOINTER>(static_cast<intptr_t>(info[1].As<Napi::Number>().Int32Value()));
1442
- else if (info[1].IsNull())
1443
- valuePtr = (SQLPOINTER)0;
1444
- else if (info[1].IsString())
1445
- {
1446
- std::string value = info[1].As<Napi::String>().Utf8Value();
1447
- stringLength = (SQLINTEGER)value.length();
1448
- GETCPPSTR(valuePtr, value, stringLength);
1449
- }
1450
- else
1451
- {
1452
- Napi::TypeError::New(env, "Unsupported Connection Attribute Value.").ThrowAsJavaScriptException();
1453
- return env.Undefined();
1454
- }
1455
-
1456
- SQLRETURN ret = SQLSetConnectAttr(m_hDBC, attr, valuePtr, stringLength);
1457
- if (stringLength != SQL_IS_INTEGER)
1458
- FREE(valuePtr);
1459
-
1460
- if (!SQL_SUCCEEDED(ret))
1461
- {
1462
- napi_throw(env, ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC, (char *)"[node-ibm_db] Error in ODBCConnection::SetAttrSync"));
1463
- return Napi::Boolean::New(env, false);
1464
- }
1465
- return Napi::Boolean::New(env, true);
1466
- }
1467
-
1468
- Napi::Value ODBCConnection::SetAttr(const Napi::CallbackInfo &info)
1469
- {
1470
- Napi::Env env = info.Env();
1471
- REQ_ARGS(3);
1472
- REQ_INT_ARG(0, attr);
1473
- REQ_FUN_ARG(2, cb);
1474
-
1475
- SQLPOINTER valuePtr = NULL;
1476
- SQLINTEGER stringLength = SQL_IS_INTEGER;
1477
-
1478
- if (info[1].IsNumber())
1479
- valuePtr = reinterpret_cast<SQLPOINTER>(static_cast<intptr_t>(info[1].As<Napi::Number>().Int32Value()));
1480
- else if (info[1].IsNull())
1481
- valuePtr = (SQLPOINTER)0;
1482
- else if (info[1].IsString())
1483
- {
1484
- std::string value = info[1].As<Napi::String>().Utf8Value();
1485
- stringLength = (SQLINTEGER)value.length();
1486
- GETCPPSTR(valuePtr, value, stringLength);
1487
- }
1488
- else
1489
- {
1490
- Napi::TypeError::New(env, "Unsupported Connection Attribute Value.").ThrowAsJavaScriptException();
1491
- return env.Undefined();
1492
- }
1493
-
1494
- uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1495
- MEMCHECK(work_req);
1496
- setattr_work_data *data = (setattr_work_data *)calloc(1, sizeof(setattr_work_data));
1497
- if (!data) free(work_req);
1498
- MEMCHECK(data);
1499
-
1500
- data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1501
- data->conn = this;
1502
- data->attr = attr;
1503
- data->valuePtr = valuePtr;
1504
- data->stringLength = stringLength;
1505
- data->env = env;
1506
- work_req->data = data;
1507
-
1508
- uv_queue_work(uv_default_loop(), work_req, UV_SetAttr, (uv_after_work_cb)UV_AfterSetAttr);
1509
- this->Ref();
1510
- return env.Undefined();
1511
- }
1512
-
1513
- void ODBCConnection::UV_SetAttr(uv_work_t *req)
1514
- {
1515
- setattr_work_data *data = (setattr_work_data *)(req->data);
1516
- data->result = SQLSetConnectAttr(data->conn->m_hDBC, data->attr, data->valuePtr, data->stringLength);
1517
- }
1518
-
1519
- void ODBCConnection::UV_AfterSetAttr(uv_work_t *req, int status)
1520
- {
1521
- setattr_work_data *data = (setattr_work_data *)(req->data);
1522
- Napi::Env env(data->env);
1523
- Napi::HandleScope scope(env);
1524
-
1525
- if (!SQL_SUCCEEDED(data->result))
1526
- data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->m_hDBC)});
1527
- else
1528
- data->cb->Call({env.Null(), Napi::Boolean::New(env, true)});
1529
- PropagateCallbackException(env);
1530
-
1531
- if (data->stringLength != SQL_IS_INTEGER)
1532
- FREE(data->valuePtr);
1533
-
1534
- data->conn->Unref();
1535
- delete data->cb;
1536
- free(data);
1537
- free(req);
1538
- }
1539
-
1540
- /*
1541
- * getInfoValue helper
1542
- */
1543
- Napi::Value getInfoValue(Napi::Env env, SQLUSMALLINT fInfoType, SQLPOINTER info)
1544
- {
1545
- if (info == NULL) return env.Null();
1546
-
1547
- switch ((unsigned int)fInfoType)
1548
- {
1549
- case SQL_DATA_SOURCE_NAME: case SQL_DRIVER_NAME: case SQL_DRIVER_VER:
1550
- #if !defined(__MVS__)
1551
- case SQL_DRIVER_BLDLEVEL: case SQL_DB2_DRIVER_VER:
1552
- #endif
1553
- case SQL_ODBC_VER: case SQL_ROW_UPDATES: case SQL_SERVER_NAME:
1554
- case SQL_SEARCH_PATTERN_ESCAPE: case SQL_DATABASE_NAME: case SQL_DBMS_NAME:
1555
- case SQL_XOPEN_CLI_YEAR: case SQL_DBMS_VER: case SQL_DBMS_FUNCTIONLVL:
1556
- case SQL_ACCESSIBLE_TABLES: case SQL_ACCESSIBLE_PROCEDURES:
1557
- case SQL_DATA_SOURCE_READ_ONLY: case SQL_EXPRESSIONS_IN_ORDERBY:
1558
- case SQL_IDENTIFIER_QUOTE_CHAR: case SQL_MULT_RESULT_SETS:
1559
- case SQL_MULTIPLE_ACTIVE_TXN: case SQL_OUTER_JOINS: case SQL_SCHEMA_TERM:
1560
- case SQL_PROCEDURE_TERM: case SQL_TABLE_TERM: case SQL_USER_NAME:
1561
- case SQL_PROCEDURES: case SQL_INTEGRITY: case SQL_DRIVER_ODBC_VER:
1562
- case SQL_COLUMN_ALIAS: case SQL_KEYWORDS: case SQL_ORDER_BY_COLUMNS_IN_SELECT:
1563
- case SQL_SPECIAL_CHARACTERS: case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
1564
- case SQL_NEED_LONG_DATA_LEN: case SQL_LIKE_ESCAPE_CLAUSE:
1565
- case SQL_CATALOG_NAME: case SQL_CATALOG_NAME_SEPARATOR: case SQL_CATALOG_TERM:
1566
- case SQL_COLLATION_SEQ: case SQL_DESCRIBE_PARAMETER:
1567
- return Napi::String::New(env, (char *)info);
1568
-
1569
- case SQL_MAX_DRIVER_CONNECTIONS: case SQL_ACTIVE_ENVIRONMENTS:
1570
- case SQL_MAX_CONCURRENT_ACTIVITIES: case SQL_ODBC_API_CONFORMANCE:
1571
- case SQL_ODBC_SAG_CLI_CONFORMANCE: case SQL_ODBC_SQL_CONFORMANCE:
1572
- case SQL_CONCAT_NULL_BEHAVIOR: case SQL_CURSOR_COMMIT_BEHAVIOR:
1573
- case SQL_CURSOR_ROLLBACK_BEHAVIOR: case SQL_IDENTIFIER_CASE:
1574
- case SQL_MAX_COLUMN_NAME_LEN: case SQL_MAX_CURSOR_NAME_LEN:
1575
- case SQL_MAX_SCHEMA_NAME_LEN:
1576
- #if !defined(__MVS__)
1577
- case SQL_MAX_MODULE_NAME_LEN:
1578
- #endif
1579
- case SQL_MAX_PROCEDURE_NAME_LEN: case SQL_MAX_TABLE_NAME_LEN:
1580
- case SQL_TXN_CAPABLE: case SQL_CORRELATION_NAME: case SQL_NON_NULLABLE_COLUMNS:
1581
- case SQL_FILE_USAGE: case SQL_NULL_COLLATION: case SQL_GROUP_BY:
1582
- case SQL_QUOTED_IDENTIFIER_CASE: case SQL_MAX_COLUMNS_IN_GROUP_BY:
1583
- case SQL_MAX_COLUMNS_IN_INDEX: case SQL_MAX_COLUMNS_IN_ORDER_BY:
1584
- case SQL_MAX_COLUMNS_IN_SELECT: case SQL_MAX_COLUMNS_IN_TABLE:
1585
- case SQL_MAX_TABLES_IN_SELECT: case SQL_MAX_USER_NAME_LEN:
1586
- case SQL_CATALOG_LOCATION: case SQL_MAX_CATALOG_NAME_LEN:
1587
- case SQL_MAX_IDENTIFIER_LEN:
1588
- return Napi::Number::New(env, *((SQLSMALLINT *)info));
1589
-
1590
- case SQL_DRIVER_HDBC: case SQL_DRIVER_HENV: case SQL_DRIVER_HSTMT:
1591
- case SQL_DRIVER_HDESC: case SQL_DRIVER_HLIB: case SQL_MAX_ROW_SIZE:
1592
- case SQL_ASYNC_MODE: case SQL_MAX_STATEMENT_LEN: case SQL_MAX_CHAR_LITERAL_LEN:
1593
- case SQL_MAX_INDEX_SIZE: case SQL_MAX_BINARY_LITERAL_LEN:
1594
- case SQL_CURSOR_SENSITIVITY: case SQL_DEFAULT_TXN_ISOLATION:
1595
- case SQL_MAX_ASYNC_CONCURRENT_STATEMENTS: case SQL_ODBC_INTERFACE_CONFORMANCE:
1596
- case SQL_PARAM_ARRAY_ROW_COUNTS: case SQL_PARAM_ARRAY_SELECTS:
1597
- case SQL_DTC_TRANSITION_COST:
1598
- #if !defined(__MVS__)
1599
- case SQL_DATABASE_CODEPAGE: case SQL_APPLICATION_CODEPAGE:
1600
- case SQL_CONNECT_CODEPAGE: case SQL_DB2_DRIVER_TYPE:
1601
- #endif
1602
- return Napi::Number::New(env, *((SQLINTEGER *)info));
1603
-
1604
- #if !defined(__MVS__)
1605
- case SQL_INPUT_CHAR_CONVFACTOR: case SQL_OUTPUT_CHAR_CONVFACTOR:
1606
- return Napi::Number::New(env, *((double *)info));
1607
- #endif
1608
-
1609
- default:
1610
- return Napi::Number::New(env, *((SQLINTEGER *)info));
1611
- }
1612
- }
1
+ /*
2
+ Copyright (c) 2013, Dan VerWeire <dverweire@gmail.com>
3
+ Copyright (c) 2010, Lee Smith<notwink@gmail.com>
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+ */
17
+
18
+ #include <string.h>
19
+ #include <time.h>
20
+ #include <uv.h>
21
+
22
+ #include "odbc.h"
23
+ #include "odbc_connection.h"
24
+ #include "odbc_result.h"
25
+ #include "odbc_statement.h"
26
+
27
+ Napi::FunctionReference ODBCConnection::constructor;
28
+
29
+ Napi::Object ODBCConnection::Init(Napi::Env env, Napi::Object exports)
30
+ {
31
+ DEBUG_PRINTF("ODBCConnection::Init\n");
32
+
33
+ Napi::Function func = DefineClass(env, "ODBCConnection", {
34
+ InstanceMethod("open", &ODBCConnection::Open, NAPI_METHOD_ATTR),
35
+ InstanceMethod("openSync", &ODBCConnection::OpenSync, NAPI_METHOD_ATTR),
36
+ InstanceMethod("close", &ODBCConnection::Close, NAPI_METHOD_ATTR),
37
+ InstanceMethod("closeSync", &ODBCConnection::CloseSync, NAPI_METHOD_ATTR),
38
+ InstanceMethod("createDbSync", &ODBCConnection::CreateDbSync, NAPI_METHOD_ATTR),
39
+ InstanceMethod("dropDbSync", &ODBCConnection::DropDbSync, NAPI_METHOD_ATTR),
40
+ InstanceMethod("createStatement", &ODBCConnection::CreateStatement, NAPI_METHOD_ATTR),
41
+ InstanceMethod("createStatementSync", &ODBCConnection::CreateStatementSync, NAPI_METHOD_ATTR),
42
+ InstanceMethod("query", &ODBCConnection::Query, NAPI_METHOD_ATTR),
43
+ InstanceMethod("querySync", &ODBCConnection::QuerySync, NAPI_METHOD_ATTR),
44
+ InstanceMethod("beginTransaction", &ODBCConnection::BeginTransaction, NAPI_METHOD_ATTR),
45
+ InstanceMethod("beginTransactionSync", &ODBCConnection::BeginTransactionSync, NAPI_METHOD_ATTR),
46
+ InstanceMethod("endTransaction", &ODBCConnection::EndTransaction, NAPI_METHOD_ATTR),
47
+ InstanceMethod("endTransactionSync", &ODBCConnection::EndTransactionSync, NAPI_METHOD_ATTR),
48
+ InstanceMethod("setIsolationLevel", &ODBCConnection::SetIsolationLevel, NAPI_METHOD_ATTR),
49
+ InstanceMethod("getInfo", &ODBCConnection::GetInfo, NAPI_METHOD_ATTR),
50
+ InstanceMethod("getInfoSync", &ODBCConnection::GetInfoSync, NAPI_METHOD_ATTR),
51
+ InstanceMethod("getTypeInfo", &ODBCConnection::GetTypeInfo, NAPI_METHOD_ATTR),
52
+ InstanceMethod("getTypeInfoSync", &ODBCConnection::GetTypeInfoSync, NAPI_METHOD_ATTR),
53
+ InstanceMethod("getFunctions", &ODBCConnection::GetFunctions, NAPI_METHOD_ATTR),
54
+ InstanceMethod("getFunctionsSync", &ODBCConnection::GetFunctionsSync, NAPI_METHOD_ATTR),
55
+ InstanceMethod("setAttr", &ODBCConnection::SetAttr, NAPI_METHOD_ATTR),
56
+ InstanceMethod("setAttrSync", &ODBCConnection::SetAttrSync, NAPI_METHOD_ATTR),
57
+ InstanceMethod("columns", &ODBCConnection::Columns, NAPI_METHOD_ATTR),
58
+ InstanceMethod("tables", &ODBCConnection::Tables, NAPI_METHOD_ATTR),
59
+ InstanceMethod("cancel", &ODBCConnection::Cancel, NAPI_METHOD_ATTR),
60
+ InstanceMethod("cancelSync", &ODBCConnection::CancelSync, NAPI_METHOD_ATTR),
61
+ InstanceAccessor("connected", &ODBCConnection::ConnectedGetter, nullptr, napi_enumerable),
62
+ InstanceAccessor("connectTimeout", &ODBCConnection::ConnectTimeoutGetter, &ODBCConnection::ConnectTimeoutSetter, napi_enumerable),
63
+ InstanceAccessor("systemNaming", &ODBCConnection::SystemNamingGetter, &ODBCConnection::SystemNamingSetter, napi_enumerable),
64
+ });
65
+
66
+ constructor = Napi::Persistent(func);
67
+ constructor.SuppressDestruct();
68
+ exports.Set("ODBCConnection", func);
69
+ return exports;
70
+ }
71
+
72
+ ODBCConnection::~ODBCConnection()
73
+ {
74
+ DEBUG_PRINTF("ODBCConnection::~ODBCConnection\n");
75
+ this->Free();
76
+ }
77
+
78
+ void ODBCConnection::Free()
79
+ {
80
+ DEBUG_PRINTF("ODBCConnection::Free m_hDBC = %i \n", m_hDBC);
81
+ if (m_hDBC)
82
+ {
83
+ SQLDisconnect(m_hDBC);
84
+ SQLFreeHandle(SQL_HANDLE_DBC, m_hDBC);
85
+ m_hDBC = (SQLHDBC)NULL;
86
+ }
87
+ }
88
+
89
+ ODBCConnection::ODBCConnection(const Napi::CallbackInfo &info) : Napi::ObjectWrap<ODBCConnection>(info)
90
+ {
91
+ Napi::Env env = info.Env();
92
+ DEBUG_PRINTF("ODBCConnection::New - Entry\n");
93
+
94
+ if (info.Length() < 2 || !info[0].IsExternal() || !info[1].IsExternal())
95
+ {
96
+ Napi::TypeError::New(env, "ODBCConnection::New requires 2 external arguments").ThrowAsJavaScriptException();
97
+ return;
98
+ }
99
+
100
+ m_hENV = (SQLHENV)((intptr_t)info[0].As<Napi::External<void>>().Data());
101
+ m_hDBC = (SQLHDBC)((intptr_t)info[1].As<Napi::External<void>>().Data());
102
+ connectTimeout = DEFAULT_CONNECTION_TIMEOUT;
103
+ systemNaming = false;
104
+ connected = false;
105
+ statements = 0;
106
+ canHaveMoreResults = 0;
107
+
108
+ DEBUG_PRINTF("ODBCConnection::New - Exit\n");
109
+ }
110
+
111
+ Napi::Value ODBCConnection::ConnectedGetter(const Napi::CallbackInfo &info)
112
+ {
113
+ return Napi::Boolean::New(info.Env(), connected);
114
+ }
115
+
116
+ Napi::Value ODBCConnection::ConnectTimeoutGetter(const Napi::CallbackInfo &info)
117
+ {
118
+ return Napi::Number::New(info.Env(), connectTimeout);
119
+ }
120
+
121
+ void ODBCConnection::ConnectTimeoutSetter(const Napi::CallbackInfo &info, const Napi::Value &value)
122
+ {
123
+ if (value.IsNumber()) connectTimeout = value.As<Napi::Number>().Int32Value();
124
+ }
125
+
126
+ Napi::Value ODBCConnection::SystemNamingGetter(const Napi::CallbackInfo &info)
127
+ {
128
+ return Napi::Boolean::New(info.Env(), systemNaming);
129
+ }
130
+
131
+ void ODBCConnection::SystemNamingSetter(const Napi::CallbackInfo &info, const Napi::Value &value)
132
+ {
133
+ if (value.IsBoolean()) systemNaming = value.As<Napi::Boolean>().Value();
134
+ }
135
+
136
+ /*
137
+ * Open
138
+ */
139
+ Napi::Value ODBCConnection::Open(const Napi::CallbackInfo &info)
140
+ {
141
+ DEBUG_PRINTF("ODBCConnection::Open - Entry\n");
142
+ Napi::Env env = info.Env();
143
+ int len = 0;
144
+ const char *errmsg = NULL;
145
+
146
+ REQ_STRO_ARG(0, connection);
147
+ REQ_FUN_ARG(1, cb);
148
+
149
+ uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
150
+ MEMCHECK(work_req);
151
+
152
+ open_connection_work_data *data = (open_connection_work_data *)calloc(1, sizeof(open_connection_work_data));
153
+ MEMCHECK2(data, errmsg);
154
+
155
+ len = (int)connection.length();
156
+ data->connectionLength = len + 1;
157
+ GETCPPSTR2(data->connection, connection, len, errmsg);
158
+
159
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
160
+ data->conn = this;
161
+ data->env = env;
162
+ work_req->data = data;
163
+
164
+ uv_queue_work(uv_default_loop(), work_req, UV_Open, (uv_after_work_cb)UV_AfterOpen);
165
+ this->Ref();
166
+
167
+ exit:
168
+ DEBUG_PRINTF("ODBCConnection::Open - Exit\n");
169
+ if (errmsg)
170
+ {
171
+ free(work_req);
172
+ free(data);
173
+ Napi::Error::New(env, errmsg).ThrowAsJavaScriptException();
174
+ return env.Undefined();
175
+ }
176
+ return env.Undefined();
177
+ }
178
+
179
+ void ODBCConnection::UV_Open(uv_work_t *req)
180
+ {
181
+ DEBUG_PRINTF("ODBCConnection::UV_Open - Entry\n");
182
+ open_connection_work_data *data = (open_connection_work_data *)(req->data);
183
+ ODBCConnection *self = data->conn->self();
184
+ SetConnectionAttributes(self);
185
+
186
+ int ret = SQLDriverConnect(self->m_hDBC, NULL, (SQLTCHAR *)data->connection,
187
+ data->connectionLength, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
188
+
189
+ if (SQL_SUCCEEDED(ret))
190
+ {
191
+ SQLHSTMT hStmt;
192
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, self->m_hDBC, &hStmt);
193
+ ret = SQLGetFunctions(self->m_hDBC, SQL_API_SQLMORERESULTS, &self->canHaveMoreResults);
194
+ if (!SQL_SUCCEEDED(ret)) self->canHaveMoreResults = 0;
195
+ ret = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
196
+ }
197
+ data->result = ret;
198
+ DEBUG_PRINTF("ODBCConnection::UV_Open - Exit\n");
199
+ }
200
+
201
+ void ODBCConnection::UV_AfterOpen(uv_work_t *req, int status)
202
+ {
203
+ DEBUG_PRINTF("ODBCConnection::UV_AfterOpen - Entry\n");
204
+ open_connection_work_data *data = (open_connection_work_data *)(req->data);
205
+ Napi::Env env(data->env);
206
+ Napi::HandleScope scope(env);
207
+
208
+ if (data->result)
209
+ {
210
+ Napi::Value objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->self()->m_hDBC);
211
+ data->conn->Unref();
212
+ data->cb->Call({objError});
213
+ }
214
+ else
215
+ {
216
+ data->conn->self()->connected = true;
217
+ data->conn->Unref();
218
+ data->cb->Call({env.Null()});
219
+ }
220
+ PropagateCallbackException(env);
221
+
222
+ delete data->cb;
223
+ FREE(data->connection);
224
+ FREE(data);
225
+ FREE(req);
226
+ DEBUG_PRINTF("ODBCConnection::UV_AfterOpen - Exit\n");
227
+ }
228
+
229
+ void ODBCConnection::SetConnectionAttributes(ODBCConnection *conn)
230
+ {
231
+ SQLUINTEGER timeOut = conn->connectTimeout;
232
+ if (timeOut > 32767) timeOut = DEFAULT_CONNECTION_TIMEOUT;
233
+ if (timeOut > 0)
234
+ {
235
+ SQLSetConnectAttr(conn->m_hDBC, SQL_ATTR_LOGIN_TIMEOUT,
236
+ (SQLPOINTER)(intptr_t)timeOut, sizeof(timeOut));
237
+ }
238
+ #if !defined(__MVS__)
239
+ if (conn->systemNaming)
240
+ {
241
+ SQLSetConnectAttr(conn->m_hDBC, SQL_ATTR_DBC_SYS_NAMING,
242
+ (SQLPOINTER)SQL_TRUE, SQL_IS_INTEGER);
243
+ }
244
+ #endif
245
+ }
246
+
247
+ /*
248
+ * OpenSync
249
+ */
250
+ Napi::Value ODBCConnection::OpenSync(const Napi::CallbackInfo &info)
251
+ {
252
+ DEBUG_PRINTF("ODBCConnection::OpenSync - Entry\n");
253
+ Napi::Env env = info.Env();
254
+
255
+ REQ_STRO_ARG(0, connection);
256
+ int connectionLength = (int)connection.length();
257
+
258
+ if (connectionLength <= 0)
259
+ {
260
+ Napi::TypeError::New(env, "Connection String must be a non-empty string").ThrowAsJavaScriptException();
261
+ return env.Undefined();
262
+ }
263
+
264
+ void *connectionString = NULL;
265
+ GETCPPSTR(connectionString, connection, connectionLength);
266
+
267
+ SetConnectionAttributes(this);
268
+
269
+ SQLRETURN ret = SQLDriverConnect(m_hDBC, NULL, (SQLTCHAR *)connectionString,
270
+ connectionLength + 1, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
271
+
272
+ if (!SQL_SUCCEEDED(ret))
273
+ {
274
+ Napi::Value objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC);
275
+ FREE(connectionString);
276
+ napi_throw(env, objError);
277
+ return env.Undefined();
278
+ }
279
+
280
+ SQLHSTMT hStmt;
281
+ SQLAllocHandle(SQL_HANDLE_STMT, m_hDBC, &hStmt);
282
+ ret = SQLGetFunctions(m_hDBC, SQL_API_SQLMORERESULTS, &canHaveMoreResults);
283
+ if (!SQL_SUCCEEDED(ret)) canHaveMoreResults = 0;
284
+ SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
285
+ self()->connected = true;
286
+
287
+ FREE(connectionString);
288
+ DEBUG_PRINTF("ODBCConnection::OpenSync - Exit\n");
289
+ return Napi::Boolean::New(env, true);
290
+ }
291
+
292
+ /*
293
+ * Close
294
+ */
295
+ Napi::Value ODBCConnection::Close(const Napi::CallbackInfo &info)
296
+ {
297
+ DEBUG_PRINTF("ODBCConnection::Close\n");
298
+ Napi::Env env = info.Env();
299
+ REQ_FUN_ARG(0, cb);
300
+
301
+ uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
302
+ MEMCHECK(work_req);
303
+ close_connection_work_data *data = (close_connection_work_data *)(calloc(1, sizeof(close_connection_work_data)));
304
+ if (!data) free(work_req);
305
+ MEMCHECK(data);
306
+
307
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
308
+ data->conn = this;
309
+ data->env = env;
310
+ work_req->data = data;
311
+
312
+ uv_queue_work(uv_default_loop(), work_req, UV_Close, (uv_after_work_cb)UV_AfterClose);
313
+ this->Ref();
314
+ return env.Undefined();
315
+ }
316
+
317
+ void ODBCConnection::UV_Close(uv_work_t *req)
318
+ {
319
+ close_connection_work_data *data = (close_connection_work_data *)(req->data);
320
+ data->conn->Free();
321
+ data->conn->connected = false;
322
+ data->result = 0;
323
+ }
324
+
325
+ void ODBCConnection::UV_AfterClose(uv_work_t *req, int status)
326
+ {
327
+ close_connection_work_data *data = (close_connection_work_data *)(req->data);
328
+ Napi::Env env(data->env);
329
+ Napi::HandleScope scope(env);
330
+
331
+ if (data->result)
332
+ data->cb->Call({Napi::Error::New(env, "Error closing database").Value()});
333
+ else
334
+ data->cb->Call({env.Null()});
335
+ PropagateCallbackException(env);
336
+
337
+ data->conn->Unref();
338
+ delete data->cb;
339
+ free(data);
340
+ free(req);
341
+ }
342
+
343
+ /*
344
+ * CloseSync
345
+ */
346
+ Napi::Value ODBCConnection::CloseSync(const Napi::CallbackInfo &info)
347
+ {
348
+ Napi::Env env = info.Env();
349
+ this->Free();
350
+ this->connected = false;
351
+ return Napi::Boolean::New(env, true);
352
+ }
353
+
354
+ /*
355
+ * CreateDbSync
356
+ */
357
+ Napi::Value ODBCConnection::CreateDbSync(const Napi::CallbackInfo &info)
358
+ {
359
+ Napi::Env env = info.Env();
360
+ #ifdef __MVS__
361
+ return Napi::Boolean::New(env, false);
362
+ #else
363
+ const char *errmsg = NULL;
364
+ int dbNameLength = 0, codeSetLength = 0, modeLength = 0;
365
+ void *databaseNameString = NULL, *codeSetString = NULL, *modeString = NULL;
366
+ SQLRETURN ret = SQL_SUCCESS;
367
+ bool err = false;
368
+ Napi::Value objError;
369
+
370
+ REQ_ARGS(3);
371
+ REQ_STRO_ARG(0, dbName);
372
+ dbNameLength = (int)dbName.length();
373
+ if (dbNameLength <= 0)
374
+ {
375
+ Napi::TypeError::New(env, "Database name must be a String.").ThrowAsJavaScriptException();
376
+ return env.Undefined();
377
+ }
378
+
379
+ REQ_STRO_OR_NULL_ARG(1, codeSet);
380
+ codeSetLength = (int)codeSet.length();
381
+ REQ_STRO_OR_NULL_ARG(2, mode);
382
+ modeLength = (int)mode.length();
383
+
384
+ GETCPPSTR2(databaseNameString, dbName, dbNameLength, errmsg);
385
+ if (!info[1].IsNull()) { GETCPPSTR2(codeSetString, codeSet, codeSetLength, errmsg); }
386
+ if (!info[2].IsNull()) { GETCPPSTR2(modeString, mode, modeLength, errmsg); }
387
+
388
+ ret = SQLCreateDb(m_hDBC, (SQLTCHAR *)databaseNameString, dbNameLength + 1,
389
+ (SQLTCHAR *)codeSetString, codeSetLength + 1,
390
+ (SQLTCHAR *)modeString, modeLength + 1);
391
+ if (!SQL_SUCCEEDED(ret)) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
392
+ else
393
+ {
394
+ ret = SQLDisconnect(m_hDBC);
395
+ if (!SQL_SUCCEEDED(ret)) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
396
+ ret = SQLFreeHandle(SQL_HANDLE_DBC, m_hDBC);
397
+ if (!SQL_SUCCEEDED(ret) && !err) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
398
+ }
399
+
400
+ exit:
401
+ FREE(databaseNameString); FREE(codeSetString); FREE(modeString);
402
+ if (errmsg) { Napi::Error::New(env, errmsg).ThrowAsJavaScriptException(); return env.Undefined(); }
403
+ if (err) { napi_throw(env, objError); return env.Undefined(); }
404
+ return Napi::Boolean::New(env, true);
405
+ #endif
406
+ }
407
+
408
+ /*
409
+ * DropDbSync
410
+ */
411
+ Napi::Value ODBCConnection::DropDbSync(const Napi::CallbackInfo &info)
412
+ {
413
+ Napi::Env env = info.Env();
414
+ #ifdef __MVS__
415
+ return Napi::Boolean::New(env, false);
416
+ #else
417
+ REQ_STRO_ARG(0, dbName);
418
+ int dbNameLength = (int)dbName.length();
419
+ if (dbNameLength <= 0) { Napi::TypeError::New(env, "Database name must be a string.").ThrowAsJavaScriptException(); return env.Undefined(); }
420
+ void *databaseNameString = NULL;
421
+ GETCPPSTR(databaseNameString, dbName, dbNameLength);
422
+
423
+ SQLRETURN ret = SQLDropDb(m_hDBC, (SQLTCHAR *)databaseNameString, dbNameLength + 1);
424
+ bool err = false; Napi::Value objError;
425
+ if (!SQL_SUCCEEDED(ret)) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
426
+ else
427
+ {
428
+ ret = SQLDisconnect(m_hDBC);
429
+ if (!SQL_SUCCEEDED(ret)) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
430
+ ret = SQLFreeHandle(SQL_HANDLE_DBC, m_hDBC);
431
+ if (!SQL_SUCCEEDED(ret) && !err) { err = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, self()->m_hDBC); }
432
+ }
433
+ FREE(databaseNameString);
434
+ if (err) { napi_throw(env, objError); return env.Undefined(); }
435
+ return Napi::Boolean::New(env, true);
436
+ #endif
437
+ }
438
+
439
+ /*
440
+ * CreateStatementSync
441
+ */
442
+ Napi::Value ODBCConnection::CreateStatementSync(const Napi::CallbackInfo &info)
443
+ {
444
+ Napi::Env env = info.Env();
445
+ SQLHSTMT hSTMT;
446
+ SQLAllocHandle(SQL_HANDLE_STMT, m_hDBC, &hSTMT);
447
+
448
+ Napi::Value params[3] = {
449
+ Napi::External<void>::New(env, (void *)(intptr_t)m_hENV),
450
+ Napi::External<void>::New(env, (void *)(intptr_t)m_hDBC),
451
+ Napi::External<void>::New(env, (void *)(intptr_t)hSTMT)
452
+ };
453
+ return ODBCStatement::constructor.New({params[0], params[1], params[2]});
454
+ }
455
+
456
+ /*
457
+ * CreateStatement
458
+ */
459
+ Napi::Value ODBCConnection::CreateStatement(const Napi::CallbackInfo &info)
460
+ {
461
+ Napi::Env env = info.Env();
462
+ REQ_FUN_ARG(0, cb);
463
+
464
+ uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
465
+ MEMCHECK(work_req);
466
+ create_statement_work_data *data = (create_statement_work_data *)(calloc(1, sizeof(create_statement_work_data)));
467
+ if (!data) free(work_req);
468
+ MEMCHECK(data);
469
+
470
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
471
+ data->conn = this;
472
+ data->env = env;
473
+ work_req->data = data;
474
+
475
+ uv_queue_work(uv_default_loop(), work_req, UV_CreateStatement, (uv_after_work_cb)UV_AfterCreateStatement);
476
+ this->Ref();
477
+ return env.Undefined();
478
+ }
479
+
480
+ void ODBCConnection::UV_CreateStatement(uv_work_t *req)
481
+ {
482
+ create_statement_work_data *data = (create_statement_work_data *)(req->data);
483
+ SQLAllocHandle(SQL_HANDLE_STMT, data->conn->m_hDBC, &data->hSTMT);
484
+ }
485
+
486
+ void ODBCConnection::UV_AfterCreateStatement(uv_work_t *req, int status)
487
+ {
488
+ create_statement_work_data *data = (create_statement_work_data *)(req->data);
489
+ Napi::Env env(data->env);
490
+ Napi::HandleScope scope(env);
491
+
492
+ Napi::Value args[3] = {
493
+ Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hENV),
494
+ Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hDBC),
495
+ Napi::External<void>::New(env, (void *)(intptr_t)data->hSTMT)
496
+ };
497
+ Napi::Object js_result = ODBCStatement::constructor.New({args[0], args[1], args[2]});
498
+ data->cb->Call({env.Null(), js_result});
499
+ PropagateCallbackException(env);
500
+
501
+ data->conn->Unref();
502
+ delete data->cb;
503
+ free(data);
504
+ free(req);
505
+ }
506
+
507
+ /*
508
+ * Query
509
+ */
510
+ Napi::Value ODBCConnection::Query(const Napi::CallbackInfo &info)
511
+ {
512
+ DEBUG_PRINTF("ODBCConnection::Query - Entry\n");
513
+ Napi::Env env = info.Env();
514
+ Napi::Function cb;
515
+ int len = 0;
516
+ const char *errmsg = NULL;
517
+ uv_work_t *work_req = NULL;
518
+
519
+ query_work_data *data = (query_work_data *)calloc(1, sizeof(query_work_data));
520
+ MEMCHECK2(data, errmsg);
521
+ data->sql = NULL;
522
+ data->params = NULL;
523
+ data->paramCount = 0;
524
+ data->noResultObject = false;
525
+ data->arraySize = 0;
526
+
527
+ if (info.Length() == 3)
528
+ {
529
+ if (!info[0].IsString()) { free(data); Napi::TypeError::New(env, "Argument 0 must be a String.").ThrowAsJavaScriptException(); return env.Undefined(); }
530
+ if (!info[1].IsArray()) { free(data); Napi::TypeError::New(env, "Argument 1 must be an Array.").ThrowAsJavaScriptException(); return env.Undefined(); }
531
+ if (!info[2].IsFunction()) { free(data); Napi::TypeError::New(env, "Argument 2 must be a Function.").ThrowAsJavaScriptException(); return env.Undefined(); }
532
+
533
+ std::string sql = info[0].As<Napi::String>().Utf8Value();
534
+ len = (int)sql.length();
535
+ GETCPPSTR2(data->sql, sql, len, errmsg);
536
+ data->params = ODBC::GetParametersFromArray(env, info[1].As<Napi::Array>(), &data->paramCount);
537
+ if (env.IsExceptionPending()) { FREE_PARAMS(data->params, data->paramCount); free(data->sql); free(data); return env.Undefined(); }
538
+ cb = info[2].As<Napi::Function>();
539
+ }
540
+ else if (info.Length() == 2)
541
+ {
542
+ if (!info[1].IsFunction()) { free(data); Napi::TypeError::New(env, "Argument 1 must be a Function.").ThrowAsJavaScriptException(); return env.Undefined(); }
543
+ cb = info[1].As<Napi::Function>();
544
+
545
+ if (info[0].IsString())
546
+ {
547
+ std::string sql2 = info[0].As<Napi::String>().Utf8Value();
548
+ len = (int)sql2.length();
549
+ GETCPPSTR2(data->sql, sql2, len, errmsg);
550
+ data->paramCount = 0;
551
+ }
552
+ else if (info[0].IsObject())
553
+ {
554
+ Napi::Object obj = info[0].As<Napi::Object>();
555
+
556
+ if (obj.Has("sql") && obj.Get("sql").IsString())
557
+ {
558
+ std::string sql3 = obj.Get("sql").As<Napi::String>().Utf8Value();
559
+ len = (int)sql3.length();
560
+ GETCPPSTR2(data->sql, sql3, len, errmsg);
561
+ }
562
+ if (obj.Has("params") && obj.Get("params").IsArray())
563
+ {
564
+ data->params = ODBC::GetParametersFromArray(env, obj.Get("params").As<Napi::Array>(), &data->paramCount);
565
+ if (env.IsExceptionPending()) { FREE_PARAMS(data->params, data->paramCount); free(data->sql); free(data); return env.Undefined(); }
566
+ }
567
+ if (obj.Has("noResults") && obj.Get("noResults").IsBoolean())
568
+ {
569
+ data->noResultObject = obj.Get("noResults").As<Napi::Boolean>().Value();
570
+ }
571
+ if (obj.Has("ArraySize") && obj.Get("ArraySize").IsNumber())
572
+ {
573
+ data->arraySize = obj.Get("ArraySize").As<Napi::Number>().Int32Value();
574
+ }
575
+ }
576
+ else
577
+ {
578
+ free(data);
579
+ Napi::TypeError::New(env, "Argument 0 must be a String or an Object.").ThrowAsJavaScriptException();
580
+ return env.Undefined();
581
+ }
582
+ }
583
+ else
584
+ {
585
+ free(data);
586
+ Napi::TypeError::New(env, "Requires either 2 or 3 Arguments.").ThrowAsJavaScriptException();
587
+ return env.Undefined();
588
+ }
589
+
590
+ if (len <= 0) { free(data); Napi::TypeError::New(env, "SQL statement is missing.").ThrowAsJavaScriptException(); return env.Undefined(); }
591
+
592
+ data->sqlLen = len;
593
+ data->sqlSize = (len + 1) * sizeof(UNICHAR);
594
+
595
+ work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
596
+ MEMCHECK2(work_req, errmsg);
597
+
598
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
599
+ data->conn = this;
600
+ data->env = env;
601
+ work_req->data = data;
602
+
603
+ uv_queue_work(uv_default_loop(), work_req, UV_Query, (uv_after_work_cb)UV_AfterQuery);
604
+ this->Ref();
605
+
606
+ exit:
607
+ if (errmsg)
608
+ {
609
+ if (data) { free(data->sql); free(data); }
610
+ free(work_req);
611
+ Napi::Error::New(env, errmsg).ThrowAsJavaScriptException();
612
+ return env.Undefined();
613
+ }
614
+ return env.Undefined();
615
+ }
616
+
617
+ void ODBCConnection::UV_Query(uv_work_t *req)
618
+ {
619
+ query_work_data *data = (query_work_data *)(req->data);
620
+ SQLRETURN ret;
621
+
622
+ SQLAllocHandle(SQL_HANDLE_STMT, data->conn->m_hDBC, &data->hSTMT);
623
+
624
+ if (!data->paramCount)
625
+ {
626
+ ret = SQLExecDirect(data->hSTMT, (SQLTCHAR *)data->sql, data->sqlLen);
627
+ }
628
+ else
629
+ {
630
+ ret = SQLPrepare(data->hSTMT, (SQLTCHAR *)data->sql, data->sqlLen);
631
+ if (SQL_SUCCEEDED(ret))
632
+ {
633
+ if (data->arraySize > 0)
634
+ {
635
+ SQLSetStmtAttr(data->hSTMT, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0);
636
+ SQLSetStmtAttr(data->hSTMT, SQL_ATTR_PARAMSET_SIZE,
637
+ reinterpret_cast<SQLPOINTER>(static_cast<intptr_t>(data->arraySize)), 0);
638
+ }
639
+ ret = ODBC::BindParameters(data->hSTMT, data->params, data->paramCount);
640
+ if (SQL_SUCCEEDED(ret))
641
+ {
642
+ ret = SQLExecute(data->hSTMT);
643
+ if (ret == SQL_NEED_DATA)
644
+ ret = ODBC::PutDataLoop(data->hSTMT, data->params, data->paramCount);
645
+ }
646
+ }
647
+ }
648
+ data->result = ret;
649
+ }
650
+
651
+ void ODBCConnection::UV_AfterQuery(uv_work_t *req, int status)
652
+ {
653
+ query_work_data *data = (query_work_data *)(req->data);
654
+ Napi::Env env(data->env);
655
+ Napi::HandleScope scope(env);
656
+
657
+ Napi::Array sp_result = Napi::Array::New(env);
658
+ int outParamCount = 0;
659
+
660
+ if (SQL_SUCCEEDED(data->result))
661
+ {
662
+ for (int i = 0; i < data->paramCount; i++)
663
+ {
664
+ if (data->params[i].paramtype % 2 == 0)
665
+ {
666
+ sp_result.Set(outParamCount, ODBC::GetOutputParameter(env, &data->params[i]));
667
+ outParamCount++;
668
+ }
669
+ }
670
+ }
671
+
672
+ if (data->result == SQL_NO_DATA_FOUND) data->result = SQL_SUCCESS;
673
+
674
+ if ((data->result >= SQL_SUCCESS) && (data->noResultObject))
675
+ {
676
+ SQLFreeHandle(SQL_HANDLE_STMT, data->hSTMT);
677
+ data->hSTMT = (SQLHSTMT)NULL;
678
+
679
+ if (outParamCount)
680
+ data->cb->Call({env.Null(), sp_result});
681
+ else
682
+ data->cb->Call({env.Null(), env.Null()});
683
+ }
684
+ else
685
+ {
686
+ if (data->result != SQL_SUCCESS)
687
+ {
688
+ Napi::Value err = ODBC::GetSQLError(env, SQL_HANDLE_STMT, data->hSTMT, (char *)"[ibm_db] SQL_ERROR");
689
+ SQLFreeHandle(SQL_HANDLE_STMT, data->hSTMT);
690
+ data->hSTMT = (SQLHSTMT)NULL;
691
+ data->cb->Call({err, env.Null(), outParamCount ? (Napi::Value)sp_result : env.Null()});
692
+ }
693
+ else
694
+ {
695
+ bool *canFreeHandle = new bool(true);
696
+ Napi::Value js_args[4] = {
697
+ Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hENV),
698
+ Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hDBC),
699
+ Napi::External<void>::New(env, (void *)(intptr_t)data->hSTMT),
700
+ Napi::External<void>::New(env, (void *)canFreeHandle)
701
+ };
702
+ Napi::Object js_result = ODBCResult::constructor.New({js_args[0], js_args[1], js_args[2], js_args[3]});
703
+ data->cb->Call({env.Null(), js_result, outParamCount ? (Napi::Value)sp_result : env.Null()});
704
+ }
705
+ }
706
+ PropagateCallbackException(env);
707
+
708
+ data->conn->Unref();
709
+ delete data->cb;
710
+ if (data->paramCount) { FREE_PARAMS(data->params, data->paramCount); }
711
+ FREE(data->sql); FREE(data->catalog); FREE(data->schema);
712
+ FREE(data->table); FREE(data->type); FREE(data->column);
713
+ FREE(data); FREE(req);
714
+ }
715
+
716
+ /*
717
+ * QuerySync
718
+ */
719
+ Napi::Value ODBCConnection::QuerySync(const Napi::CallbackInfo &info)
720
+ {
721
+ DEBUG_PRINTF("ODBCConnection::QuerySync - Entry\n");
722
+ Napi::Env env = info.Env();
723
+ void *sql = NULL;
724
+ Parameter *params = NULL;
725
+ SQLRETURN ret;
726
+ SQLHSTMT hSTMT;
727
+ int paramCount = 0, outParamCount = 0;
728
+ Napi::Array sp_result = Napi::Array::New(env);
729
+ bool noResultObject = false;
730
+ int32_t arraySize = 0;
731
+ int len = 0;
732
+
733
+ if (info.Length() == 2)
734
+ {
735
+ if (!info[0].IsString()) { Napi::TypeError::New(env, "Argument 0 must be a String.").ThrowAsJavaScriptException(); return env.Undefined(); }
736
+ if (!info[1].IsArray()) { Napi::TypeError::New(env, "Argument 1 must be an Array.").ThrowAsJavaScriptException(); return env.Undefined(); }
737
+ std::string sql1 = info[0].As<Napi::String>().Utf8Value();
738
+ len = (int)sql1.length();
739
+ GETCPPSTR(sql, sql1, len);
740
+ params = ODBC::GetParametersFromArray(env, info[1].As<Napi::Array>(), &paramCount);
741
+ if (env.IsExceptionPending()) { FREE_PARAMS(params, paramCount); free(sql); return env.Undefined(); }
742
+ }
743
+ else if (info.Length() == 1)
744
+ {
745
+ if (info[0].IsString())
746
+ {
747
+ std::string sql2 = info[0].As<Napi::String>().Utf8Value();
748
+ len = (int)sql2.length();
749
+ GETCPPSTR(sql, sql2, len);
750
+ }
751
+ else if (info[0].IsObject())
752
+ {
753
+ Napi::Object obj = info[0].As<Napi::Object>();
754
+ if (obj.Has("sql") && obj.Get("sql").IsString()) {
755
+ std::string sql3 = obj.Get("sql").As<Napi::String>().Utf8Value();
756
+ len = (int)sql3.length();
757
+ GETCPPSTR(sql, sql3, len);
758
+ }
759
+ if (obj.Has("params") && obj.Get("params").IsArray())
760
+ {
761
+ params = ODBC::GetParametersFromArray(env, obj.Get("params").As<Napi::Array>(), &paramCount);
762
+ if (env.IsExceptionPending()) { FREE_PARAMS(params, paramCount); free(sql); return env.Undefined(); }
763
+ }
764
+ if (obj.Has("noResults") && obj.Get("noResults").IsBoolean())
765
+ noResultObject = obj.Get("noResults").As<Napi::Boolean>().Value();
766
+ if (obj.Has("ArraySize") && obj.Get("ArraySize").IsNumber())
767
+ arraySize = obj.Get("ArraySize").As<Napi::Number>().Int32Value();
768
+ }
769
+ else
770
+ {
771
+ Napi::TypeError::New(env, "Argument 0 must be a String or an Object.").ThrowAsJavaScriptException();
772
+ return env.Undefined();
773
+ }
774
+ }
775
+ else
776
+ {
777
+ Napi::TypeError::New(env, "Requires 1 or 2 Arguments.").ThrowAsJavaScriptException();
778
+ return env.Undefined();
779
+ }
780
+
781
+ if (len <= 0) { Napi::TypeError::New(env, "SQL statement is missing.").ThrowAsJavaScriptException(); return env.Undefined(); }
782
+
783
+ ret = SQLAllocHandle(SQL_HANDLE_STMT, m_hDBC, &hSTMT);
784
+ if (!SQL_SUCCEEDED(ret)) { /* fall through */ }
785
+ else if (!paramCount)
786
+ {
787
+ ret = SQLExecDirect(hSTMT, (SQLTCHAR *)sql, len);
788
+ }
789
+ else
790
+ {
791
+ ret = SQLPrepare(hSTMT, (SQLTCHAR *)sql, len);
792
+ if (SQL_SUCCEEDED(ret))
793
+ {
794
+ if (arraySize > 0) {
795
+ SQLSetStmtAttr(hSTMT, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0);
796
+ SQLSetStmtAttr(hSTMT, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast<SQLPOINTER>(static_cast<intptr_t>(arraySize)), 0);
797
+ }
798
+ ret = ODBC::BindParameters(hSTMT, params, paramCount);
799
+ if (SQL_SUCCEEDED(ret))
800
+ {
801
+ ret = SQLExecute(hSTMT);
802
+ if (ret == SQL_NEED_DATA) ret = ODBC::PutDataLoop(hSTMT, params, paramCount);
803
+ if (SQL_SUCCEEDED(ret))
804
+ {
805
+ for (int i = 0; i < paramCount; i++)
806
+ {
807
+ if (params[i].paramtype % 2 == 0)
808
+ {
809
+ sp_result.Set(outParamCount, ODBC::GetOutputParameter(env, &params[i]));
810
+ outParamCount++;
811
+ }
812
+ }
813
+ }
814
+ }
815
+ }
816
+ }
817
+
818
+ FREE(sql);
819
+ FREE_PARAMS(params, paramCount);
820
+
821
+ if (ret == SQL_NO_DATA_FOUND) ret = SQL_SUCCESS;
822
+
823
+ if (ret != SQL_SUCCESS)
824
+ {
825
+ Napi::Value err = ODBC::GetSQLError(env, SQL_HANDLE_STMT, hSTMT, (char *)"[node-ibm_db] Error in ODBCConnection::QuerySync while executing query.");
826
+ SQLFreeHandle(SQL_HANDLE_STMT, hSTMT);
827
+ napi_throw(env, err);
828
+ return env.Undefined();
829
+ }
830
+ else if (noResultObject)
831
+ {
832
+ SQLFreeHandle(SQL_HANDLE_STMT, hSTMT);
833
+ if (outParamCount) {
834
+ Napi::Array resultset = Napi::Array::New(env);
835
+ resultset.Set((uint32_t)0, env.Null());
836
+ resultset.Set((uint32_t)1, sp_result);
837
+ return resultset;
838
+ }
839
+ return env.Null();
840
+ }
841
+ else
842
+ {
843
+ bool *canFreeHandle = new bool(true);
844
+ Napi::Value result[4] = {
845
+ Napi::External<void>::New(env, (void *)(intptr_t)m_hENV),
846
+ Napi::External<void>::New(env, (void *)(intptr_t)m_hDBC),
847
+ Napi::External<void>::New(env, (void *)(intptr_t)hSTMT),
848
+ Napi::External<void>::New(env, (void *)canFreeHandle)
849
+ };
850
+ Napi::Object js_result = ODBCResult::constructor.New({result[0], result[1], result[2], result[3]});
851
+
852
+ if (outParamCount) {
853
+ Napi::Array resultset = Napi::Array::New(env);
854
+ resultset.Set((uint32_t)0, js_result);
855
+ resultset.Set((uint32_t)1, sp_result);
856
+ return resultset;
857
+ }
858
+ return js_result;
859
+ }
860
+ }
861
+
862
+ /*
863
+ * Tables
864
+ */
865
+ Napi::Value ODBCConnection::Tables(const Napi::CallbackInfo &info)
866
+ {
867
+ Napi::Env env = info.Env();
868
+ int len = 0;
869
+ const char *errmsg = NULL;
870
+ uv_work_t *work_req = NULL;
871
+ query_work_data *data = NULL;
872
+
873
+ REQ_STRO_OR_NULL_ARG(0, catalog);
874
+ REQ_STRO_OR_NULL_ARG(1, schema);
875
+ REQ_STRO_OR_NULL_ARG(2, table);
876
+ REQ_STRO_OR_NULL_ARG(3, type);
877
+ REQ_FUN_ARG(4, cb);
878
+
879
+ work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
880
+ MEMCHECK2(work_req, errmsg);
881
+ data = (query_work_data *)calloc(1, sizeof(query_work_data));
882
+ MEMCHECK2(data, errmsg);
883
+
884
+ data->sql = NULL; data->catalog = NULL; data->schema = NULL;
885
+ data->table = NULL; data->type = NULL; data->column = NULL;
886
+
887
+ len = (int)catalog.length(); GETCPPSTR2(data->catalog, catalog, len, errmsg);
888
+ len = (int)schema.length(); GETCPPSTR2(data->schema, schema, len, errmsg);
889
+ len = (int)table.length(); GETCPPSTR2(data->table, table, len, errmsg);
890
+ len = (int)type.length(); GETCPPSTR2(data->type, type, len, errmsg);
891
+
892
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
893
+ data->conn = this;
894
+ data->env = env;
895
+ work_req->data = data;
896
+
897
+ uv_queue_work(uv_default_loop(), work_req, UV_Tables, (uv_after_work_cb)UV_AfterQuery);
898
+ this->Ref();
899
+
900
+ exit:
901
+ if (errmsg)
902
+ {
903
+ if (data) { FREE(data->catalog); FREE(data->schema); FREE(data->table); FREE(data->type); free(data); }
904
+ free(work_req);
905
+ Napi::Error::New(env, errmsg).ThrowAsJavaScriptException();
906
+ return env.Undefined();
907
+ }
908
+ return env.Undefined();
909
+ }
910
+
911
+ void ODBCConnection::UV_Tables(uv_work_t *req)
912
+ {
913
+ query_work_data *data = (query_work_data *)(req->data);
914
+ SQLAllocHandle(SQL_HANDLE_STMT, data->conn->m_hDBC, &data->hSTMT);
915
+
916
+ SQLRETURN ret = SQLTables(data->hSTMT,
917
+ #ifdef __MVS__
918
+ NULL, 0,
919
+ #else
920
+ (SQLTCHAR *)data->catalog, SQL_NTS,
921
+ #endif
922
+ (SQLTCHAR *)data->schema, SQL_NTS,
923
+ (SQLTCHAR *)data->table, SQL_NTS,
924
+ (SQLTCHAR *)data->type, SQL_NTS);
925
+
926
+ data->result = ret;
927
+ FREE(data->catalog); FREE(data->schema); FREE(data->table); FREE(data->type);
928
+ }
929
+
930
+ /*
931
+ * Columns
932
+ */
933
+ Napi::Value ODBCConnection::Columns(const Napi::CallbackInfo &info)
934
+ {
935
+ Napi::Env env = info.Env();
936
+ int len = 0;
937
+ const char *errmsg = NULL;
938
+ uv_work_t *work_req = NULL;
939
+ query_work_data *data = NULL;
940
+
941
+ REQ_STRO_OR_NULL_ARG(0, catalog);
942
+ REQ_STRO_OR_NULL_ARG(1, schema);
943
+ REQ_STRO_OR_NULL_ARG(2, table);
944
+ REQ_STRO_OR_NULL_ARG(3, column);
945
+ REQ_FUN_ARG(4, cb);
946
+
947
+ work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
948
+ MEMCHECK(work_req);
949
+ data = (query_work_data *)calloc(1, sizeof(query_work_data));
950
+ MEMCHECK2(data, errmsg);
951
+
952
+ data->sql = NULL; data->catalog = NULL; data->schema = NULL;
953
+ data->table = NULL; data->type = NULL; data->column = NULL;
954
+
955
+ len = (int)catalog.length(); GETCPPSTR2(data->catalog, catalog, len, errmsg);
956
+ len = (int)schema.length(); GETCPPSTR2(data->schema, schema, len, errmsg);
957
+ len = (int)table.length(); GETCPPSTR2(data->table, table, len, errmsg);
958
+ len = (int)column.length(); GETCPPSTR2(data->column, column, len, errmsg);
959
+
960
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
961
+ data->conn = this;
962
+ data->env = env;
963
+ work_req->data = data;
964
+
965
+ uv_queue_work(uv_default_loop(), work_req, UV_Columns, (uv_after_work_cb)UV_AfterQuery);
966
+ this->Ref();
967
+
968
+ exit:
969
+ if (errmsg)
970
+ {
971
+ if (data) { FREE(data->catalog); FREE(data->schema); FREE(data->table); FREE(data->column); free(data); }
972
+ free(work_req);
973
+ Napi::Error::New(env, errmsg).ThrowAsJavaScriptException();
974
+ return env.Undefined();
975
+ }
976
+ return env.Undefined();
977
+ }
978
+
979
+ void ODBCConnection::UV_Columns(uv_work_t *req)
980
+ {
981
+ query_work_data *data = (query_work_data *)(req->data);
982
+ SQLAllocHandle(SQL_HANDLE_STMT, data->conn->m_hDBC, &data->hSTMT);
983
+
984
+ SQLRETURN ret = SQLColumns(data->hSTMT,
985
+ #ifdef __MVS__
986
+ NULL, 0,
987
+ #else
988
+ (SQLTCHAR *)data->catalog, SQL_NTS,
989
+ #endif
990
+ (SQLTCHAR *)data->schema, SQL_NTS,
991
+ (SQLTCHAR *)data->table, SQL_NTS,
992
+ (SQLTCHAR *)data->column, SQL_NTS);
993
+
994
+ data->result = ret;
995
+ FREE(data->catalog); FREE(data->schema); FREE(data->table); FREE(data->column);
996
+ }
997
+
998
+ /*
999
+ * BeginTransactionSync
1000
+ */
1001
+ Napi::Value ODBCConnection::BeginTransactionSync(const Napi::CallbackInfo &info)
1002
+ {
1003
+ Napi::Env env = info.Env();
1004
+ SQLRETURN ret = SQLSetConnectAttr(m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_NTS);
1005
+ if (!SQL_SUCCEEDED(ret))
1006
+ {
1007
+ napi_throw(env, ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC));
1008
+ return Napi::Boolean::New(env, false);
1009
+ }
1010
+ return Napi::Boolean::New(env, true);
1011
+ }
1012
+
1013
+ /*
1014
+ * BeginTransaction
1015
+ */
1016
+ Napi::Value ODBCConnection::BeginTransaction(const Napi::CallbackInfo &info)
1017
+ {
1018
+ Napi::Env env = info.Env();
1019
+ REQ_FUN_ARG(0, cb);
1020
+
1021
+ uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1022
+ MEMCHECK(work_req);
1023
+ query_work_data *data = (query_work_data *)calloc(1, sizeof(query_work_data));
1024
+ if (!data) free(work_req);
1025
+ MEMCHECK(data);
1026
+
1027
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1028
+ data->conn = this;
1029
+ data->env = env;
1030
+ work_req->data = data;
1031
+
1032
+ uv_queue_work(uv_default_loop(), work_req, UV_BeginTransaction, (uv_after_work_cb)UV_AfterBeginTransaction);
1033
+ return env.Undefined();
1034
+ }
1035
+
1036
+ void ODBCConnection::UV_BeginTransaction(uv_work_t *req)
1037
+ {
1038
+ query_work_data *data = (query_work_data *)(req->data);
1039
+ data->result = SQLSetConnectAttr(data->conn->self()->m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_NTS);
1040
+ }
1041
+
1042
+ void ODBCConnection::UV_AfterBeginTransaction(uv_work_t *req, int status)
1043
+ {
1044
+ open_connection_work_data *data = (open_connection_work_data *)(req->data);
1045
+ Napi::Env env(data->env);
1046
+ Napi::HandleScope scope(env);
1047
+
1048
+ if (!SQL_SUCCEEDED(data->result))
1049
+ data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->self()->m_hDBC)});
1050
+ else
1051
+ data->cb->Call({env.Null()});
1052
+ PropagateCallbackException(env);
1053
+
1054
+ delete data->cb;
1055
+ free(data);
1056
+ free(req);
1057
+ }
1058
+
1059
+ /*
1060
+ * EndTransactionSync
1061
+ */
1062
+ Napi::Value ODBCConnection::EndTransactionSync(const Napi::CallbackInfo &info)
1063
+ {
1064
+ Napi::Env env = info.Env();
1065
+ REQ_BOOL_ARG(0, rollback);
1066
+
1067
+ SQLSMALLINT completionType = rollback ? SQL_ROLLBACK : SQL_COMMIT;
1068
+ bool error = false;
1069
+ Napi::Value objError;
1070
+
1071
+ SQLRETURN ret = SQLEndTran(SQL_HANDLE_DBC, m_hDBC, completionType);
1072
+ if (!SQL_SUCCEEDED(ret)) { error = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC); }
1073
+
1074
+ ret = SQLSetConnectAttr(m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS);
1075
+ if (!SQL_SUCCEEDED(ret) && !error) { error = true; objError = ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC); }
1076
+
1077
+ if (error)
1078
+ {
1079
+ napi_throw(env, objError);
1080
+ return Napi::Boolean::New(env, false);
1081
+ }
1082
+ return Napi::Boolean::New(env, true);
1083
+ }
1084
+
1085
+ /*
1086
+ * EndTransaction
1087
+ */
1088
+ Napi::Value ODBCConnection::EndTransaction(const Napi::CallbackInfo &info)
1089
+ {
1090
+ Napi::Env env = info.Env();
1091
+ REQ_BOOL_ARG(0, rollback);
1092
+ REQ_FUN_ARG(1, cb);
1093
+
1094
+ uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1095
+ MEMCHECK(work_req);
1096
+ query_work_data *data = (query_work_data *)calloc(1, sizeof(query_work_data));
1097
+ if (!data) free(work_req);
1098
+ MEMCHECK(data);
1099
+
1100
+ data->completionType = rollback ? SQL_ROLLBACK : SQL_COMMIT;
1101
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1102
+ data->conn = this;
1103
+ data->env = env;
1104
+ work_req->data = data;
1105
+
1106
+ uv_queue_work(uv_default_loop(), work_req, UV_EndTransaction, (uv_after_work_cb)UV_AfterEndTransaction);
1107
+ return env.Undefined();
1108
+ }
1109
+
1110
+ void ODBCConnection::UV_EndTransaction(uv_work_t *req)
1111
+ {
1112
+ query_work_data *data = (query_work_data *)(req->data);
1113
+ SQLRETURN ret = SQLEndTran(SQL_HANDLE_DBC, data->conn->m_hDBC, data->completionType);
1114
+ data->result = ret;
1115
+ ret = SQLSetConnectAttr(data->conn->m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS);
1116
+ if (!SQL_SUCCEEDED(ret) && SQL_SUCCEEDED(data->result)) data->result = ret;
1117
+ }
1118
+
1119
+ void ODBCConnection::UV_AfterEndTransaction(uv_work_t *req, int status)
1120
+ {
1121
+ open_connection_work_data *data = (open_connection_work_data *)(req->data);
1122
+ Napi::Env env(data->env);
1123
+ Napi::HandleScope scope(env);
1124
+
1125
+ if (!SQL_SUCCEEDED(data->result))
1126
+ data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->self()->m_hDBC)});
1127
+ else
1128
+ data->cb->Call({env.Null()});
1129
+ PropagateCallbackException(env);
1130
+
1131
+ delete data->cb;
1132
+ free(data);
1133
+ free(req);
1134
+ }
1135
+
1136
+ /*
1137
+ * SetIsolationLevel
1138
+ */
1139
+ Napi::Value ODBCConnection::SetIsolationLevel(const Napi::CallbackInfo &info)
1140
+ {
1141
+ Napi::Env env = info.Env();
1142
+ SQLUINTEGER isolationLevel = SQL_TXN_READ_COMMITTED;
1143
+
1144
+ if (info.Length() > 0 && info[0].IsNumber())
1145
+ isolationLevel = info[0].As<Napi::Number>().Uint32Value();
1146
+ else if (info.Length() > 0)
1147
+ {
1148
+ Napi::TypeError::New(env, "Argument #0 must be an integer.").ThrowAsJavaScriptException();
1149
+ return env.Undefined();
1150
+ }
1151
+
1152
+ SQLRETURN ret = SQLSetConnectAttr(m_hDBC, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)(intptr_t)isolationLevel, SQL_NTS);
1153
+
1154
+ if (!SQL_SUCCEEDED(ret))
1155
+ {
1156
+ napi_throw(env, ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC));
1157
+ return Napi::Boolean::New(env, false);
1158
+ }
1159
+ return Napi::Boolean::New(env, true);
1160
+ }
1161
+
1162
+ /*
1163
+ * GetInfoSync
1164
+ */
1165
+ Napi::Value ODBCConnection::GetInfoSync(const Napi::CallbackInfo &info)
1166
+ {
1167
+ Napi::Env env = info.Env();
1168
+ REQ_ARGS(2);
1169
+ REQ_INT_ARG(0, infotype);
1170
+ REQ_INT_ARG(1, infolen);
1171
+
1172
+ SQLPOINTER rgbInfo = malloc(infolen);
1173
+ MEMCHECK(rgbInfo);
1174
+ SQLSMALLINT cbInfo = 0;
1175
+ SQLRETURN ret = SQLGetInfo(m_hDBC, infotype, rgbInfo, infolen, &cbInfo);
1176
+
1177
+ if (!SQL_SUCCEEDED(ret))
1178
+ {
1179
+ free(rgbInfo);
1180
+ napi_throw(env, ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC));
1181
+ return Napi::Boolean::New(env, false);
1182
+ }
1183
+
1184
+ Napi::Value value = getInfoValue(env, (SQLUSMALLINT)infotype, rgbInfo);
1185
+ free(rgbInfo);
1186
+ return value;
1187
+ }
1188
+
1189
+ /*
1190
+ * GetInfo
1191
+ */
1192
+ Napi::Value ODBCConnection::GetInfo(const Napi::CallbackInfo &info)
1193
+ {
1194
+ Napi::Env env = info.Env();
1195
+ REQ_ARGS(3);
1196
+ REQ_INT_ARG(0, infotype);
1197
+ REQ_INT_ARG(1, infolen);
1198
+ REQ_FUN_ARG(2, cb);
1199
+
1200
+ uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1201
+ MEMCHECK(work_req);
1202
+ getinfo_work_data *data = (getinfo_work_data *)calloc(1, sizeof(getinfo_work_data));
1203
+ if (!data) free(work_req);
1204
+ MEMCHECK(data);
1205
+
1206
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1207
+ data->conn = this;
1208
+ data->infoType = infotype;
1209
+ data->buffLen = infolen;
1210
+ data->env = env;
1211
+ work_req->data = data;
1212
+
1213
+ uv_queue_work(uv_default_loop(), work_req, UV_GetInfo, (uv_after_work_cb)UV_AfterGetInfo);
1214
+ this->Ref();
1215
+ return env.Undefined();
1216
+ }
1217
+
1218
+ void ODBCConnection::UV_GetInfo(uv_work_t *req)
1219
+ {
1220
+ getinfo_work_data *data = (getinfo_work_data *)(req->data);
1221
+ SQLSMALLINT valueLen = 0;
1222
+ data->buffer = malloc(data->buffLen);
1223
+ if (!data->buffer) { data->rc = SQL_ERROR; return; }
1224
+ data->rc = SQLGetInfo(data->conn->m_hDBC, data->infoType, data->buffer, data->buffLen, &valueLen);
1225
+ data->valueLen = valueLen;
1226
+ }
1227
+
1228
+ void ODBCConnection::UV_AfterGetInfo(uv_work_t *req, int status)
1229
+ {
1230
+ getinfo_work_data *data = (getinfo_work_data *)(req->data);
1231
+ Napi::Env env(data->env);
1232
+ Napi::HandleScope scope(env);
1233
+
1234
+ if (data->rc != SQL_SUCCESS)
1235
+ data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->m_hDBC, (char *)"[node-ibm_db] SQL_ERROR"), env.Null()});
1236
+ else
1237
+ data->cb->Call({env.Null(), getInfoValue(env, data->infoType, data->buffer)});
1238
+ PropagateCallbackException(env);
1239
+
1240
+ data->conn->Unref();
1241
+ delete data->cb;
1242
+ free(data->buffer);
1243
+ free(data);
1244
+ free(req);
1245
+ }
1246
+
1247
+ /*
1248
+ * GetTypeInfoSync
1249
+ */
1250
+ Napi::Value ODBCConnection::GetTypeInfoSync(const Napi::CallbackInfo &info)
1251
+ {
1252
+ Napi::Env env = info.Env();
1253
+ REQ_ARGS(1);
1254
+ REQ_INT_ARG(0, dataType);
1255
+
1256
+ SQLHSTMT hSTMT;
1257
+ SQLAllocHandle(SQL_HANDLE_STMT, m_hDBC, &hSTMT);
1258
+ SQLRETURN ret = SQLGetTypeInfo(hSTMT, (SQLSMALLINT)dataType);
1259
+
1260
+ if (!SQL_SUCCEEDED(ret))
1261
+ {
1262
+ Napi::Value err = ODBC::GetSQLError(env, SQL_HANDLE_STMT, hSTMT);
1263
+ SQLFreeHandle(SQL_HANDLE_STMT, hSTMT);
1264
+ napi_throw(env, err);
1265
+ return Napi::Boolean::New(env, false);
1266
+ }
1267
+
1268
+ bool *canFreeHandle = new bool(true);
1269
+ Napi::Value args[4] = {
1270
+ Napi::External<void>::New(env, (void *)(intptr_t)m_hENV),
1271
+ Napi::External<void>::New(env, (void *)(intptr_t)m_hDBC),
1272
+ Napi::External<void>::New(env, (void *)(intptr_t)hSTMT),
1273
+ Napi::External<void>::New(env, (void *)canFreeHandle)
1274
+ };
1275
+ return ODBCResult::constructor.New({args[0], args[1], args[2], args[3]});
1276
+ }
1277
+
1278
+ Napi::Value ODBCConnection::GetTypeInfo(const Napi::CallbackInfo &info)
1279
+ {
1280
+ Napi::Env env = info.Env();
1281
+ REQ_ARGS(2);
1282
+ REQ_INT_ARG(0, dataType);
1283
+ REQ_FUN_ARG(1, cb);
1284
+
1285
+ uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1286
+ MEMCHECK(work_req);
1287
+ gettypeinfo_work_data *data = (gettypeinfo_work_data *)calloc(1, sizeof(gettypeinfo_work_data));
1288
+ if (!data) free(work_req);
1289
+ MEMCHECK(data);
1290
+
1291
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1292
+ data->conn = this;
1293
+ data->dataType = (SQLSMALLINT)dataType;
1294
+ data->env = env;
1295
+ work_req->data = data;
1296
+
1297
+ uv_queue_work(uv_default_loop(), work_req, UV_GetTypeInfo, (uv_after_work_cb)UV_AfterGetTypeInfo);
1298
+ this->Ref();
1299
+ return env.Undefined();
1300
+ }
1301
+
1302
+ void ODBCConnection::UV_GetTypeInfo(uv_work_t *req)
1303
+ {
1304
+ gettypeinfo_work_data *data = (gettypeinfo_work_data *)(req->data);
1305
+ SQLAllocHandle(SQL_HANDLE_STMT, data->conn->m_hDBC, &data->hSTMT);
1306
+ data->result = SQLGetTypeInfo(data->hSTMT, data->dataType);
1307
+ }
1308
+
1309
+ void ODBCConnection::UV_AfterGetTypeInfo(uv_work_t *req, int status)
1310
+ {
1311
+ gettypeinfo_work_data *data = (gettypeinfo_work_data *)(req->data);
1312
+ Napi::Env env(data->env);
1313
+ Napi::HandleScope scope(env);
1314
+
1315
+ if (!SQL_SUCCEEDED(data->result))
1316
+ {
1317
+ data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_STMT, data->hSTMT), env.Null()});
1318
+ SQLFreeHandle(SQL_HANDLE_STMT, data->hSTMT);
1319
+ }
1320
+ else
1321
+ {
1322
+ bool *canFreeHandle = new bool(true);
1323
+ Napi::Value args[4] = {
1324
+ Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hENV),
1325
+ Napi::External<void>::New(env, (void *)(intptr_t)data->conn->m_hDBC),
1326
+ Napi::External<void>::New(env, (void *)(intptr_t)data->hSTMT),
1327
+ Napi::External<void>::New(env, (void *)canFreeHandle)
1328
+ };
1329
+ Napi::Object js_result = ODBCResult::constructor.New({args[0], args[1], args[2], args[3]});
1330
+ data->cb->Call({env.Null(), js_result});
1331
+ }
1332
+ PropagateCallbackException(env);
1333
+
1334
+ data->conn->Unref();
1335
+ delete data->cb;
1336
+ free(data);
1337
+ free(req);
1338
+ }
1339
+
1340
+ /*
1341
+ * GetFunctionsSync
1342
+ */
1343
+ Napi::Value ODBCConnection::GetFunctionsSync(const Napi::CallbackInfo &info)
1344
+ {
1345
+ Napi::Env env = info.Env();
1346
+ REQ_ARGS(1);
1347
+ REQ_UINT_ARG(0, functionId);
1348
+
1349
+ SQLUSMALLINT funcId = (SQLUSMALLINT)functionId;
1350
+ SQLUSMALLINT supportedPtr = 0;
1351
+ SQLUSMALLINT supportedArr[100] = {0};
1352
+ SQLRETURN ret;
1353
+
1354
+ if (funcId)
1355
+ ret = SQLGetFunctions(m_hDBC, funcId, &supportedPtr);
1356
+ else
1357
+ ret = SQLGetFunctions(m_hDBC, funcId, supportedArr);
1358
+
1359
+ if (!SQL_SUCCEEDED(ret))
1360
+ {
1361
+ napi_throw(env, ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC));
1362
+ return Napi::Boolean::New(env, false);
1363
+ }
1364
+
1365
+ if (funcId)
1366
+ return Napi::Number::New(env, supportedPtr);
1367
+
1368
+ Napi::Array value = Napi::Array::New(env, 100);
1369
+ for (uint32_t i = 0; i < 100; i++)
1370
+ value.Set(i, Napi::Number::New(env, supportedArr[i]));
1371
+ return value;
1372
+ }
1373
+
1374
+ Napi::Value ODBCConnection::GetFunctions(const Napi::CallbackInfo &info)
1375
+ {
1376
+ Napi::Env env = info.Env();
1377
+ REQ_ARGS(2);
1378
+ REQ_UINT_ARG(0, functionId);
1379
+ REQ_FUN_ARG(1, cb);
1380
+
1381
+ uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1382
+ MEMCHECK(work_req);
1383
+ getfunctions_work_data *data = (getfunctions_work_data *)calloc(1, sizeof(getfunctions_work_data));
1384
+ if (!data) free(work_req);
1385
+ MEMCHECK(data);
1386
+
1387
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1388
+ data->conn = this;
1389
+ data->functionId = (SQLUSMALLINT)functionId;
1390
+ data->env = env;
1391
+ work_req->data = data;
1392
+
1393
+ uv_queue_work(uv_default_loop(), work_req, UV_GetFunctions, (uv_after_work_cb)UV_AfterGetFunctions);
1394
+ this->Ref();
1395
+ return env.Undefined();
1396
+ }
1397
+
1398
+ void ODBCConnection::UV_GetFunctions(uv_work_t *req)
1399
+ {
1400
+ getfunctions_work_data *data = (getfunctions_work_data *)(req->data);
1401
+
1402
+ if (data->functionId)
1403
+ data->result = SQLGetFunctions(data->conn->m_hDBC, data->functionId, &data->supportedPtr);
1404
+ else
1405
+ data->result = SQLGetFunctions(data->conn->m_hDBC, data->functionId, data->supportedArr);
1406
+ }
1407
+
1408
+ void ODBCConnection::UV_AfterGetFunctions(uv_work_t *req, int status)
1409
+ {
1410
+ getfunctions_work_data *data = (getfunctions_work_data *)(req->data);
1411
+ Napi::Env env(data->env);
1412
+ Napi::HandleScope scope(env);
1413
+
1414
+ if (!SQL_SUCCEEDED(data->result))
1415
+ data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->m_hDBC), env.Null()});
1416
+ else
1417
+ {
1418
+ if (data->functionId)
1419
+ data->cb->Call({env.Null(), Napi::Number::New(env, data->supportedPtr)});
1420
+ else
1421
+ {
1422
+ Napi::Array value = Napi::Array::New(env, 100);
1423
+ for (uint32_t i = 0; i < 100; i++)
1424
+ value.Set(i, Napi::Number::New(env, data->supportedArr[i]));
1425
+ data->cb->Call({env.Null(), value});
1426
+ }
1427
+ }
1428
+ PropagateCallbackException(env);
1429
+
1430
+ data->conn->Unref();
1431
+ delete data->cb;
1432
+ free(data);
1433
+ free(req);
1434
+ }
1435
+
1436
+ /*
1437
+ * SetAttrSync
1438
+ */
1439
+ Napi::Value ODBCConnection::SetAttrSync(const Napi::CallbackInfo &info)
1440
+ {
1441
+ Napi::Env env = info.Env();
1442
+ REQ_ARGS(2);
1443
+ REQ_INT_ARG(0, attr);
1444
+
1445
+ SQLPOINTER valuePtr = NULL;
1446
+ SQLINTEGER stringLength = SQL_IS_INTEGER;
1447
+
1448
+ if (info[1].IsNumber())
1449
+ valuePtr = reinterpret_cast<SQLPOINTER>(static_cast<intptr_t>(info[1].As<Napi::Number>().Int32Value()));
1450
+ else if (info[1].IsNull())
1451
+ valuePtr = (SQLPOINTER)0;
1452
+ else if (info[1].IsString())
1453
+ {
1454
+ std::string value = info[1].As<Napi::String>().Utf8Value();
1455
+ stringLength = (SQLINTEGER)value.length();
1456
+ GETCPPSTR(valuePtr, value, stringLength);
1457
+ }
1458
+ else
1459
+ {
1460
+ Napi::TypeError::New(env, "Unsupported Connection Attribute Value.").ThrowAsJavaScriptException();
1461
+ return env.Undefined();
1462
+ }
1463
+
1464
+ SQLRETURN ret = SQLSetConnectAttr(m_hDBC, attr, valuePtr, stringLength);
1465
+ if (stringLength != SQL_IS_INTEGER)
1466
+ FREE(valuePtr);
1467
+
1468
+ if (!SQL_SUCCEEDED(ret))
1469
+ {
1470
+ napi_throw(env, ODBC::GetSQLError(env, SQL_HANDLE_DBC, m_hDBC, (char *)"[node-ibm_db] Error in ODBCConnection::SetAttrSync"));
1471
+ return Napi::Boolean::New(env, false);
1472
+ }
1473
+ return Napi::Boolean::New(env, true);
1474
+ }
1475
+
1476
+ Napi::Value ODBCConnection::SetAttr(const Napi::CallbackInfo &info)
1477
+ {
1478
+ Napi::Env env = info.Env();
1479
+ REQ_ARGS(3);
1480
+ REQ_INT_ARG(0, attr);
1481
+ REQ_FUN_ARG(2, cb);
1482
+
1483
+ SQLPOINTER valuePtr = NULL;
1484
+ SQLINTEGER stringLength = SQL_IS_INTEGER;
1485
+
1486
+ if (info[1].IsNumber())
1487
+ valuePtr = reinterpret_cast<SQLPOINTER>(static_cast<intptr_t>(info[1].As<Napi::Number>().Int32Value()));
1488
+ else if (info[1].IsNull())
1489
+ valuePtr = (SQLPOINTER)0;
1490
+ else if (info[1].IsString())
1491
+ {
1492
+ std::string value = info[1].As<Napi::String>().Utf8Value();
1493
+ stringLength = (SQLINTEGER)value.length();
1494
+ GETCPPSTR(valuePtr, value, stringLength);
1495
+ }
1496
+ else
1497
+ {
1498
+ Napi::TypeError::New(env, "Unsupported Connection Attribute Value.").ThrowAsJavaScriptException();
1499
+ return env.Undefined();
1500
+ }
1501
+
1502
+ uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1503
+ MEMCHECK(work_req);
1504
+ setattr_work_data *data = (setattr_work_data *)calloc(1, sizeof(setattr_work_data));
1505
+ if (!data) free(work_req);
1506
+ MEMCHECK(data);
1507
+
1508
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1509
+ data->conn = this;
1510
+ data->attr = attr;
1511
+ data->valuePtr = valuePtr;
1512
+ data->stringLength = stringLength;
1513
+ data->env = env;
1514
+ work_req->data = data;
1515
+
1516
+ uv_queue_work(uv_default_loop(), work_req, UV_SetAttr, (uv_after_work_cb)UV_AfterSetAttr);
1517
+ this->Ref();
1518
+ return env.Undefined();
1519
+ }
1520
+
1521
+ void ODBCConnection::UV_SetAttr(uv_work_t *req)
1522
+ {
1523
+ setattr_work_data *data = (setattr_work_data *)(req->data);
1524
+ data->result = SQLSetConnectAttr(data->conn->m_hDBC, data->attr, data->valuePtr, data->stringLength);
1525
+ }
1526
+
1527
+ void ODBCConnection::UV_AfterSetAttr(uv_work_t *req, int status)
1528
+ {
1529
+ setattr_work_data *data = (setattr_work_data *)(req->data);
1530
+ Napi::Env env(data->env);
1531
+ Napi::HandleScope scope(env);
1532
+
1533
+ if (!SQL_SUCCEEDED(data->result))
1534
+ data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_DBC, data->conn->m_hDBC)});
1535
+ else
1536
+ data->cb->Call({env.Null(), Napi::Boolean::New(env, true)});
1537
+ PropagateCallbackException(env);
1538
+
1539
+ if (data->stringLength != SQL_IS_INTEGER)
1540
+ FREE(data->valuePtr);
1541
+
1542
+ data->conn->Unref();
1543
+ delete data->cb;
1544
+ free(data);
1545
+ free(req);
1546
+ }
1547
+
1548
+ /*
1549
+ * getInfoValue helper
1550
+ */
1551
+ Napi::Value getInfoValue(Napi::Env env, SQLUSMALLINT fInfoType, SQLPOINTER info)
1552
+ {
1553
+ if (info == NULL) return env.Null();
1554
+
1555
+ switch ((unsigned int)fInfoType)
1556
+ {
1557
+ case SQL_DATA_SOURCE_NAME: case SQL_DRIVER_NAME: case SQL_DRIVER_VER:
1558
+ #if !defined(__MVS__)
1559
+ case SQL_DRIVER_BLDLEVEL: case SQL_DB2_DRIVER_VER:
1560
+ #endif
1561
+ case SQL_ODBC_VER: case SQL_ROW_UPDATES: case SQL_SERVER_NAME:
1562
+ case SQL_SEARCH_PATTERN_ESCAPE: case SQL_DATABASE_NAME: case SQL_DBMS_NAME:
1563
+ case SQL_XOPEN_CLI_YEAR: case SQL_DBMS_VER: case SQL_DBMS_FUNCTIONLVL:
1564
+ case SQL_ACCESSIBLE_TABLES: case SQL_ACCESSIBLE_PROCEDURES:
1565
+ case SQL_DATA_SOURCE_READ_ONLY: case SQL_EXPRESSIONS_IN_ORDERBY:
1566
+ case SQL_IDENTIFIER_QUOTE_CHAR: case SQL_MULT_RESULT_SETS:
1567
+ case SQL_MULTIPLE_ACTIVE_TXN: case SQL_OUTER_JOINS: case SQL_SCHEMA_TERM:
1568
+ case SQL_PROCEDURE_TERM: case SQL_TABLE_TERM: case SQL_USER_NAME:
1569
+ case SQL_PROCEDURES: case SQL_INTEGRITY: case SQL_DRIVER_ODBC_VER:
1570
+ case SQL_COLUMN_ALIAS: case SQL_KEYWORDS: case SQL_ORDER_BY_COLUMNS_IN_SELECT:
1571
+ case SQL_SPECIAL_CHARACTERS: case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
1572
+ case SQL_NEED_LONG_DATA_LEN: case SQL_LIKE_ESCAPE_CLAUSE:
1573
+ case SQL_CATALOG_NAME: case SQL_CATALOG_NAME_SEPARATOR: case SQL_CATALOG_TERM:
1574
+ case SQL_COLLATION_SEQ: case SQL_DESCRIBE_PARAMETER:
1575
+ return Napi::String::New(env, (char *)info);
1576
+
1577
+ case SQL_MAX_DRIVER_CONNECTIONS: case SQL_ACTIVE_ENVIRONMENTS:
1578
+ case SQL_MAX_CONCURRENT_ACTIVITIES: case SQL_ODBC_API_CONFORMANCE:
1579
+ case SQL_ODBC_SAG_CLI_CONFORMANCE: case SQL_ODBC_SQL_CONFORMANCE:
1580
+ case SQL_CONCAT_NULL_BEHAVIOR: case SQL_CURSOR_COMMIT_BEHAVIOR:
1581
+ case SQL_CURSOR_ROLLBACK_BEHAVIOR: case SQL_IDENTIFIER_CASE:
1582
+ case SQL_MAX_COLUMN_NAME_LEN: case SQL_MAX_CURSOR_NAME_LEN:
1583
+ case SQL_MAX_SCHEMA_NAME_LEN:
1584
+ #if !defined(__MVS__)
1585
+ case SQL_MAX_MODULE_NAME_LEN:
1586
+ #endif
1587
+ case SQL_MAX_PROCEDURE_NAME_LEN: case SQL_MAX_TABLE_NAME_LEN:
1588
+ case SQL_TXN_CAPABLE: case SQL_CORRELATION_NAME: case SQL_NON_NULLABLE_COLUMNS:
1589
+ case SQL_FILE_USAGE: case SQL_NULL_COLLATION: case SQL_GROUP_BY:
1590
+ case SQL_QUOTED_IDENTIFIER_CASE: case SQL_MAX_COLUMNS_IN_GROUP_BY:
1591
+ case SQL_MAX_COLUMNS_IN_INDEX: case SQL_MAX_COLUMNS_IN_ORDER_BY:
1592
+ case SQL_MAX_COLUMNS_IN_SELECT: case SQL_MAX_COLUMNS_IN_TABLE:
1593
+ case SQL_MAX_TABLES_IN_SELECT: case SQL_MAX_USER_NAME_LEN:
1594
+ case SQL_CATALOG_LOCATION: case SQL_MAX_CATALOG_NAME_LEN:
1595
+ case SQL_MAX_IDENTIFIER_LEN:
1596
+ return Napi::Number::New(env, *((SQLSMALLINT *)info));
1597
+
1598
+ case SQL_DRIVER_HDBC: case SQL_DRIVER_HENV: case SQL_DRIVER_HSTMT:
1599
+ case SQL_DRIVER_HDESC: case SQL_DRIVER_HLIB: case SQL_MAX_ROW_SIZE:
1600
+ case SQL_ASYNC_MODE: case SQL_MAX_STATEMENT_LEN: case SQL_MAX_CHAR_LITERAL_LEN:
1601
+ case SQL_MAX_INDEX_SIZE: case SQL_MAX_BINARY_LITERAL_LEN:
1602
+ case SQL_CURSOR_SENSITIVITY: case SQL_DEFAULT_TXN_ISOLATION:
1603
+ case SQL_MAX_ASYNC_CONCURRENT_STATEMENTS: case SQL_ODBC_INTERFACE_CONFORMANCE:
1604
+ case SQL_PARAM_ARRAY_ROW_COUNTS: case SQL_PARAM_ARRAY_SELECTS:
1605
+ case SQL_DTC_TRANSITION_COST:
1606
+ #if !defined(__MVS__)
1607
+ case SQL_DATABASE_CODEPAGE: case SQL_APPLICATION_CODEPAGE:
1608
+ case SQL_CONNECT_CODEPAGE: case SQL_DB2_DRIVER_TYPE:
1609
+ #endif
1610
+ return Napi::Number::New(env, *((SQLINTEGER *)info));
1611
+
1612
+ #if !defined(__MVS__)
1613
+ case SQL_INPUT_CHAR_CONVFACTOR: case SQL_OUTPUT_CHAR_CONVFACTOR:
1614
+ return Napi::Number::New(env, *((double *)info));
1615
+ #endif
1616
+
1617
+ default:
1618
+ return Napi::Number::New(env, *((SQLINTEGER *)info));
1619
+ }
1620
+ }
1621
+
1622
+ /*
1623
+ * Cancel
1624
+ * Calls SQLCancel on a statement handle to cancel an executing SQL statement.
1625
+ * Requires a statement object as the first argument.
1626
+ *
1627
+ * Usage:
1628
+ * cancel(statement, callback) - cancel the specified statement
1629
+ */
1630
+ Napi::Value ODBCConnection::Cancel(const Napi::CallbackInfo &info)
1631
+ {
1632
+ DEBUG_PRINTF("ODBCConnection::Cancel - Entry\n");
1633
+ Napi::Env env = info.Env();
1634
+
1635
+ if (info.Length() < 2 || !info[0].IsObject() || !info[1].IsFunction())
1636
+ {
1637
+ Napi::Error::New(env, "cancel() requires a statement object and a callback function").ThrowAsJavaScriptException();
1638
+ return env.Undefined();
1639
+ }
1640
+
1641
+ Napi::Object stmtObj = info[0].As<Napi::Object>();
1642
+ Napi::Function cb = info[1].As<Napi::Function>();
1643
+
1644
+ if (!stmtObj.CheckTypeTag(&ODBCStatement::type_tag))
1645
+ {
1646
+ Napi::TypeError::New(env, "cancel() requires an ODBCStatement object").ThrowAsJavaScriptException();
1647
+ return env.Undefined();
1648
+ }
1649
+
1650
+ napi_status status;
1651
+ ODBCStatement *stmt = nullptr;
1652
+ status = napi_unwrap(env, stmtObj, reinterpret_cast<void**>(&stmt));
1653
+
1654
+ if (status != napi_ok || !stmt || !stmt->m_hSTMT)
1655
+ {
1656
+ Napi::Error::New(env, "Invalid statement object or statement handle is null").ThrowAsJavaScriptException();
1657
+ return env.Undefined();
1658
+ }
1659
+
1660
+ SQLHSTMT hSTMT = stmt->m_hSTMT;
1661
+
1662
+ uv_work_t *work_req = (uv_work_t *)(calloc(1, sizeof(uv_work_t)));
1663
+ MEMCHECK(work_req);
1664
+ cancel_work_data *data = (cancel_work_data *)calloc(1, sizeof(cancel_work_data));
1665
+ if (!data) free(work_req);
1666
+ MEMCHECK(data);
1667
+
1668
+ data->cb = new Napi::FunctionReference(Napi::Persistent(cb));
1669
+ data->conn = this;
1670
+ data->hSTMT = hSTMT;
1671
+ data->env = env;
1672
+ work_req->data = data;
1673
+
1674
+ uv_queue_work(uv_default_loop(), work_req, UV_Cancel, (uv_after_work_cb)UV_AfterCancel);
1675
+ this->Ref();
1676
+ DEBUG_PRINTF("ODBCConnection::Cancel - Exit\n");
1677
+ return env.Undefined();
1678
+ }
1679
+
1680
+ void ODBCConnection::UV_Cancel(uv_work_t *req)
1681
+ {
1682
+ DEBUG_PRINTF("ODBCConnection::UV_Cancel - Entry\n");
1683
+ cancel_work_data *data = (cancel_work_data *)(req->data);
1684
+ data->result = SQLCancel(data->hSTMT);
1685
+ DEBUG_PRINTF("ODBCConnection::UV_Cancel - Exit, result=%d\n", data->result);
1686
+ }
1687
+
1688
+ void ODBCConnection::UV_AfterCancel(uv_work_t *req, int status)
1689
+ {
1690
+ DEBUG_PRINTF("ODBCConnection::UV_AfterCancel - Entry\n");
1691
+ cancel_work_data *data = (cancel_work_data *)(req->data);
1692
+ Napi::Env env(data->env);
1693
+ Napi::HandleScope scope(env);
1694
+
1695
+ if (!SQL_SUCCEEDED(data->result))
1696
+ {
1697
+ data->cb->Call({ODBC::GetSQLError(env, SQL_HANDLE_STMT, data->hSTMT)});
1698
+ }
1699
+ else
1700
+ {
1701
+ data->cb->Call({env.Null(), Napi::Boolean::New(env, true)});
1702
+ }
1703
+ PropagateCallbackException(env);
1704
+
1705
+ data->conn->Unref();
1706
+ delete data->cb;
1707
+ free(data);
1708
+ free(req);
1709
+ DEBUG_PRINTF("ODBCConnection::UV_AfterCancel - Exit\n");
1710
+ }
1711
+
1712
+ /*
1713
+ * CancelSync
1714
+ * Synchronous version of Cancel. Calls SQLCancel on a statement handle.
1715
+ * Requires a statement object as argument.
1716
+ *
1717
+ * Usage:
1718
+ * cancelSync(statement) - cancel the specified statement
1719
+ */
1720
+ Napi::Value ODBCConnection::CancelSync(const Napi::CallbackInfo &info)
1721
+ {
1722
+ DEBUG_PRINTF("ODBCConnection::CancelSync - Entry\n");
1723
+ Napi::Env env = info.Env();
1724
+
1725
+ if (info.Length() < 1 || !info[0].IsObject())
1726
+ {
1727
+ Napi::Error::New(env, "cancelSync() requires a statement object").ThrowAsJavaScriptException();
1728
+ return Napi::Boolean::New(env, false);
1729
+ }
1730
+
1731
+ Napi::Object stmtObj = info[0].As<Napi::Object>();
1732
+
1733
+ if (!stmtObj.CheckTypeTag(&ODBCStatement::type_tag))
1734
+ {
1735
+ Napi::TypeError::New(env, "cancelSync() requires an ODBCStatement object").ThrowAsJavaScriptException();
1736
+ return Napi::Boolean::New(env, false);
1737
+ }
1738
+
1739
+ napi_status status;
1740
+ ODBCStatement *stmt = nullptr;
1741
+ status = napi_unwrap(env, stmtObj, reinterpret_cast<void**>(&stmt));
1742
+
1743
+ if (status != napi_ok || !stmt || !stmt->m_hSTMT)
1744
+ {
1745
+ Napi::Error::New(env, "Invalid statement object or statement handle is null").ThrowAsJavaScriptException();
1746
+ return Napi::Boolean::New(env, false);
1747
+ }
1748
+
1749
+ SQLHSTMT hSTMT = stmt->m_hSTMT;
1750
+
1751
+ SQLRETURN ret = SQLCancel(hSTMT);
1752
+
1753
+ if (!SQL_SUCCEEDED(ret))
1754
+ {
1755
+ napi_throw(env, ODBC::GetSQLError(env, SQL_HANDLE_STMT, hSTMT,
1756
+ (char *)"[node-ibm_db] Error in ODBCConnection::CancelSync"));
1757
+ return Napi::Boolean::New(env, false);
1758
+ }
1759
+
1760
+ DEBUG_PRINTF("ODBCConnection::CancelSync - Exit\n");
1761
+ return Napi::Boolean::New(env, true);
1762
+ }