embulk-output-sqlserver 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +14 -3
- data/classpath/{embulk-output-jdbc-0.5.0.jar → embulk-output-jdbc-0.5.1.jar} +0 -0
- data/classpath/embulk-output-sqlserver-0.5.1.jar +0 -0
- data/src/main/java/org/embulk/output/SQLServerOutputPlugin.java +22 -4
- data/src/main/java/org/embulk/output/sqlserver/InsertMethod.java +32 -0
- data/src/main/java/org/embulk/output/sqlserver/NativeBatchInsert.java +247 -0
- data/src/main/java/org/embulk/output/sqlserver/SmallDateTimeFormat.java +31 -0
- data/src/main/java/org/embulk/output/sqlserver/nativeclient/NativeClient.java +33 -0
- data/src/main/java/org/embulk/output/sqlserver/nativeclient/NativeClientWrapper.java +442 -0
- data/src/main/java/org/embulk/output/sqlserver/nativeclient/ODBC.java +47 -0
- data/src/test/java/org/embulk/output/sqlserver/SQLServerOutputPluginTest.java +174 -10
- data/src/test/resources/sqlserver/data/test2/test2.csv +2 -0
- data/src/test/resources/sqlserver/data/test3/test3.csv +2 -0
- data/src/test/resources/sqlserver/data/test4/test4.csv +2 -0
- data/src/test/resources/sqlserver/data/test5/test5.csv +2 -0
- data/src/test/resources/sqlserver/yml/test-native-date.yml +26 -0
- data/src/test/resources/sqlserver/yml/test-native-decimal.yml +25 -0
- data/src/test/resources/sqlserver/yml/test-native-integer.yml +24 -0
- data/src/test/resources/sqlserver/yml/test-native-string.yml +25 -0
- data/src/test/resources/sqlserver/yml/test-native.yml +44 -0
- metadata +19 -4
- data/classpath/embulk-output-sqlserver-0.5.0.jar +0 -0
@@ -0,0 +1,442 @@
|
|
1
|
+
package org.embulk.output.sqlserver.nativeclient;
|
2
|
+
|
3
|
+
import java.nio.ByteBuffer;
|
4
|
+
import java.nio.CharBuffer;
|
5
|
+
import java.nio.charset.Charset;
|
6
|
+
import java.sql.SQLException;
|
7
|
+
import java.util.HashMap;
|
8
|
+
import java.util.Map;
|
9
|
+
|
10
|
+
import jnr.ffi.LibraryLoader;
|
11
|
+
import jnr.ffi.Pointer;
|
12
|
+
import jnr.ffi.Runtime;
|
13
|
+
import jnr.ffi.provider.jffi.ArrayMemoryIO;
|
14
|
+
|
15
|
+
import org.embulk.spi.Exec;
|
16
|
+
import org.slf4j.Logger;
|
17
|
+
|
18
|
+
import com.google.common.base.Optional;
|
19
|
+
|
20
|
+
public class NativeClientWrapper
|
21
|
+
{
|
22
|
+
private static ODBC odbc;
|
23
|
+
private static NativeClient client;
|
24
|
+
|
25
|
+
private final Logger logger = Exec.getLogger(getClass());
|
26
|
+
|
27
|
+
private Charset charset;
|
28
|
+
private Charset wideCharset;
|
29
|
+
private Pointer envHandle;
|
30
|
+
private Pointer odbcHandle;
|
31
|
+
|
32
|
+
private Map<Integer, Pointer> boundPointers = new HashMap<Integer, Pointer>();
|
33
|
+
|
34
|
+
public NativeClientWrapper()
|
35
|
+
{
|
36
|
+
synchronized (NativeClientWrapper.class) {
|
37
|
+
if (odbc == null) {
|
38
|
+
logger.info("Loading SQL Server Native Client library (odbc32).");
|
39
|
+
try {
|
40
|
+
odbc = LibraryLoader.create(ODBC.class).failImmediately().load("odbc32");
|
41
|
+
} catch (UnsatisfiedLinkError e) {
|
42
|
+
throw new RuntimeException("odbc32.dll not found.", e);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
if (client == null) {
|
46
|
+
logger.info("Loading SQL Server Native Client library (sqlncli11).");
|
47
|
+
try {
|
48
|
+
client = LibraryLoader.create(NativeClient.class).failImmediately().load("sqlncli11");
|
49
|
+
} catch (UnsatisfiedLinkError e) {
|
50
|
+
throw new RuntimeException("sqlncli11.dll not found.", e);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
charset = Charset.forName("MS932");
|
56
|
+
wideCharset = Charset.forName("UTF-16LE");
|
57
|
+
}
|
58
|
+
|
59
|
+
public void open(String server, int port, Optional<String> instance,
|
60
|
+
String database, Optional<String> user, Optional<String> password,
|
61
|
+
String table)
|
62
|
+
throws SQLException
|
63
|
+
{
|
64
|
+
// environment handle
|
65
|
+
Pointer envHandlePointer = createPointerPointer();
|
66
|
+
checkSQLResult("SQLAllocHandle(SQL_HANDLE_ENV)", odbc.SQLAllocHandle(
|
67
|
+
ODBC.SQL_HANDLE_ENV,
|
68
|
+
null,
|
69
|
+
envHandlePointer));
|
70
|
+
envHandle = envHandlePointer.getPointer(0);
|
71
|
+
|
72
|
+
// set ODBC version
|
73
|
+
checkSQLResult("SQLSetEnvAttr(SQL_ATTR_ODBC_VERSION)", odbc.SQLSetEnvAttr(
|
74
|
+
envHandle,
|
75
|
+
ODBC.SQL_ATTR_ODBC_VERSION,
|
76
|
+
Pointer.wrap(Runtime.getSystemRuntime(), ODBC.SQL_OV_ODBC3),
|
77
|
+
ODBC.SQL_IS_INTEGER));
|
78
|
+
|
79
|
+
// ODBC handle
|
80
|
+
Pointer odbcHandlePointer = createPointerPointer();
|
81
|
+
checkSQLResult("SQLAllocHandle(SQL_HANDLE_DBC)", odbc.SQLAllocHandle(
|
82
|
+
ODBC.SQL_HANDLE_DBC,
|
83
|
+
envHandle,
|
84
|
+
odbcHandlePointer));
|
85
|
+
odbcHandle = odbcHandlePointer.getPointer(0);
|
86
|
+
|
87
|
+
// set BULK COPY mode
|
88
|
+
checkSQLResult("SQLSetConnectAttr(SQL_COPT_SS_BCP)", odbc.SQLSetConnectAttrW(
|
89
|
+
odbcHandle,
|
90
|
+
ODBC.SQL_COPT_SS_BCP,
|
91
|
+
Pointer.wrap(Runtime.getSystemRuntime(), ODBC.SQL_BCP_ON),
|
92
|
+
ODBC.SQL_IS_INTEGER));
|
93
|
+
|
94
|
+
StringBuilder connectionString = new StringBuilder();
|
95
|
+
connectionString.append("Driver={SQL Server Native Client 11.0};");
|
96
|
+
if (instance.isPresent()) {
|
97
|
+
connectionString.append(String.format("Server=%s,%d\\%s;", server, port, instance.get()));
|
98
|
+
} else {
|
99
|
+
connectionString.append(String.format("Server=%s,%d;", server, port));
|
100
|
+
}
|
101
|
+
connectionString.append(String.format("Database=%s;", database));
|
102
|
+
if (user.isPresent()) {
|
103
|
+
connectionString.append(String.format("UID=%s;", user.get()));
|
104
|
+
}
|
105
|
+
if (password.isPresent()) {
|
106
|
+
logger.info("connection string = " + connectionString + "PWD=********;");
|
107
|
+
connectionString.append(String.format("PWD=%s;", password.get()));
|
108
|
+
} else {
|
109
|
+
logger.info("connection string = " + connectionString);
|
110
|
+
}
|
111
|
+
|
112
|
+
checkSQLResult("SQLDriverConnect", odbc.SQLDriverConnectW(
|
113
|
+
odbcHandle,
|
114
|
+
null,
|
115
|
+
toWideChars(connectionString.toString()),
|
116
|
+
ODBC.SQL_NTS,
|
117
|
+
null,
|
118
|
+
ODBC.SQL_NTS,
|
119
|
+
null,
|
120
|
+
ODBC.SQL_DRIVER_NOPROMPT));
|
121
|
+
|
122
|
+
StringBuilder fullTableName = new StringBuilder();
|
123
|
+
fullTableName.append("[");
|
124
|
+
fullTableName.append(database);
|
125
|
+
fullTableName.append("].");
|
126
|
+
fullTableName.append(".[");
|
127
|
+
fullTableName.append(table);
|
128
|
+
fullTableName.append("]");
|
129
|
+
checkBCPResult("bcp_init", client.bcp_initW(
|
130
|
+
odbcHandle,
|
131
|
+
toWideChars(fullTableName.toString()),
|
132
|
+
null,
|
133
|
+
null,
|
134
|
+
NativeClient.DB_IN));
|
135
|
+
}
|
136
|
+
|
137
|
+
public int bindNull(int columnIndex) throws SQLException
|
138
|
+
{
|
139
|
+
Pointer pointer = prepareBuffer(columnIndex, 0);
|
140
|
+
checkBCPResult("bcp_bind", client.bcp_bind(
|
141
|
+
odbcHandle,
|
142
|
+
pointer,
|
143
|
+
0,
|
144
|
+
NativeClient.SQL_NULL_DATA,
|
145
|
+
null,
|
146
|
+
0,
|
147
|
+
NativeClient.SQLCHARACTER,
|
148
|
+
columnIndex));
|
149
|
+
return (int)pointer.size();
|
150
|
+
}
|
151
|
+
|
152
|
+
public int bindValue(int columnIndex, String value) throws SQLException
|
153
|
+
{
|
154
|
+
ByteBuffer bytes = charset.encode(value);
|
155
|
+
Pointer pointer = prepareBuffer(columnIndex, bytes.remaining());
|
156
|
+
pointer.put(0, bytes.array(), 0, bytes.remaining());
|
157
|
+
|
158
|
+
checkBCPResult("bcp_bind", client.bcp_bind(
|
159
|
+
odbcHandle,
|
160
|
+
pointer,
|
161
|
+
0,
|
162
|
+
(int)pointer.size(),
|
163
|
+
null,
|
164
|
+
0,
|
165
|
+
NativeClient.SQLCHARACTER,
|
166
|
+
columnIndex));
|
167
|
+
return (int)pointer.size();
|
168
|
+
}
|
169
|
+
|
170
|
+
public int bindValue(int columnIndex, boolean value) throws SQLException
|
171
|
+
{
|
172
|
+
Pointer pointer = prepareBuffer(columnIndex, 1);
|
173
|
+
pointer.putByte(0, value ? (byte)1 : (byte)0);
|
174
|
+
|
175
|
+
checkBCPResult("bcp_bind", client.bcp_bind(
|
176
|
+
odbcHandle,
|
177
|
+
pointer,
|
178
|
+
0,
|
179
|
+
(int)pointer.size(),
|
180
|
+
null,
|
181
|
+
0,
|
182
|
+
NativeClient.SQLBIT,
|
183
|
+
columnIndex));
|
184
|
+
return (int)pointer.size();
|
185
|
+
}
|
186
|
+
|
187
|
+
public int bindValue(int columnIndex, byte value) throws SQLException
|
188
|
+
{
|
189
|
+
Pointer pointer = prepareBuffer(columnIndex, 1);
|
190
|
+
pointer.putByte(0, value);
|
191
|
+
|
192
|
+
checkBCPResult("bcp_bind", client.bcp_bind(
|
193
|
+
odbcHandle,
|
194
|
+
pointer,
|
195
|
+
0,
|
196
|
+
(int)pointer.size(),
|
197
|
+
null,
|
198
|
+
0,
|
199
|
+
NativeClient.SQLINT1,
|
200
|
+
columnIndex));
|
201
|
+
return (int)pointer.size();
|
202
|
+
}
|
203
|
+
|
204
|
+
public int bindValue(int columnIndex, short value) throws SQLException
|
205
|
+
{
|
206
|
+
Pointer pointer = prepareBuffer(columnIndex, 2);
|
207
|
+
pointer.putShort(0, value);
|
208
|
+
|
209
|
+
checkBCPResult("bcp_bind", client.bcp_bind(
|
210
|
+
odbcHandle,
|
211
|
+
pointer,
|
212
|
+
0,
|
213
|
+
(int)pointer.size(),
|
214
|
+
null,
|
215
|
+
0,
|
216
|
+
NativeClient.SQLINT2,
|
217
|
+
columnIndex));
|
218
|
+
return (int)pointer.size();
|
219
|
+
}
|
220
|
+
|
221
|
+
public int bindValue(int columnIndex, int value) throws SQLException
|
222
|
+
{
|
223
|
+
Pointer pointer = prepareBuffer(columnIndex, 4);
|
224
|
+
pointer.putInt(0, value);
|
225
|
+
|
226
|
+
checkBCPResult("bcp_bind", client.bcp_bind(
|
227
|
+
odbcHandle,
|
228
|
+
pointer,
|
229
|
+
0,
|
230
|
+
(int)pointer.size(),
|
231
|
+
null,
|
232
|
+
0,
|
233
|
+
NativeClient.SQLINT4,
|
234
|
+
columnIndex));
|
235
|
+
return (int)pointer.size();
|
236
|
+
}
|
237
|
+
|
238
|
+
public int bindValue(int columnIndex, long value) throws SQLException
|
239
|
+
{
|
240
|
+
Pointer pointer = prepareBuffer(columnIndex, 8);
|
241
|
+
pointer.putLongLong(0, value);
|
242
|
+
|
243
|
+
checkBCPResult("bcp_bind", client.bcp_bind(
|
244
|
+
odbcHandle,
|
245
|
+
pointer,
|
246
|
+
0,
|
247
|
+
(int)pointer.size(),
|
248
|
+
null,
|
249
|
+
0,
|
250
|
+
NativeClient.SQLINT8,
|
251
|
+
columnIndex));
|
252
|
+
return (int)pointer.size();
|
253
|
+
}
|
254
|
+
|
255
|
+
public int bindValue(int columnIndex, float value) throws SQLException
|
256
|
+
{
|
257
|
+
Pointer pointer = prepareBuffer(columnIndex, 4);
|
258
|
+
pointer.putFloat(0, value);
|
259
|
+
|
260
|
+
checkBCPResult("bcp_bind", client.bcp_bind(
|
261
|
+
odbcHandle,
|
262
|
+
pointer,
|
263
|
+
0,
|
264
|
+
(int)pointer.size(),
|
265
|
+
null,
|
266
|
+
0,
|
267
|
+
NativeClient.SQLFLT4,
|
268
|
+
columnIndex));
|
269
|
+
return (int)pointer.size();
|
270
|
+
}
|
271
|
+
|
272
|
+
public int bindValue(int columnIndex, double value) throws SQLException
|
273
|
+
{
|
274
|
+
Pointer pointer = prepareBuffer(columnIndex, 8);
|
275
|
+
pointer.putDouble(0, value);
|
276
|
+
|
277
|
+
checkBCPResult("bcp_bind", client.bcp_bind(
|
278
|
+
odbcHandle,
|
279
|
+
pointer,
|
280
|
+
0,
|
281
|
+
(int)pointer.size(),
|
282
|
+
null,
|
283
|
+
0,
|
284
|
+
NativeClient.SQLFLT8,
|
285
|
+
columnIndex));
|
286
|
+
return (int)pointer.size();
|
287
|
+
}
|
288
|
+
|
289
|
+
private Pointer prepareBuffer(int columnIndex, int size)
|
290
|
+
{
|
291
|
+
Pointer pointer = boundPointers.get(columnIndex);
|
292
|
+
if (pointer == null || pointer.size() < size) {
|
293
|
+
Runtime runtime = Runtime.getSystemRuntime();
|
294
|
+
pointer = Pointer.wrap(runtime, ByteBuffer.allocateDirect(size).order(runtime.byteOrder()));
|
295
|
+
boundPointers.put(columnIndex, pointer);
|
296
|
+
}
|
297
|
+
return pointer;
|
298
|
+
}
|
299
|
+
|
300
|
+
public void sendRow() throws SQLException
|
301
|
+
{
|
302
|
+
checkBCPResult("bcp_sendrow", client.bcp_sendrow(odbcHandle));
|
303
|
+
}
|
304
|
+
|
305
|
+
public void commit(boolean done) throws SQLException
|
306
|
+
{
|
307
|
+
String operation;
|
308
|
+
int result;
|
309
|
+
if (done) {
|
310
|
+
operation = "bcp_done";
|
311
|
+
result = client.bcp_done(odbcHandle);
|
312
|
+
} else {
|
313
|
+
operation = "bcp_batch";
|
314
|
+
result = client.bcp_batch(odbcHandle);
|
315
|
+
}
|
316
|
+
if (result < 0) {
|
317
|
+
throwException(operation, NativeClient.FAIL);
|
318
|
+
} else {
|
319
|
+
if (result > 0) {
|
320
|
+
logger.info(String.format("SQL Server Native Client : %,d rows have bean loaded.", result));
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
}
|
325
|
+
|
326
|
+
public void close()
|
327
|
+
{
|
328
|
+
if (odbcHandle != null) {
|
329
|
+
odbc.SQLFreeHandle(ODBC.SQL_HANDLE_DBC, odbcHandle);
|
330
|
+
odbcHandle = null;
|
331
|
+
}
|
332
|
+
if (envHandle != null) {
|
333
|
+
odbc.SQLFreeHandle(ODBC.SQL_HANDLE_ENV, envHandle);
|
334
|
+
envHandle = null;
|
335
|
+
}
|
336
|
+
}
|
337
|
+
|
338
|
+
private Pointer createPointerPointer()
|
339
|
+
{
|
340
|
+
return new ArrayMemoryIO(Runtime.getSystemRuntime(), com.kenai.jffi.Type.POINTER.size());
|
341
|
+
}
|
342
|
+
|
343
|
+
private String toString(Pointer wcharPointer, int length)
|
344
|
+
{
|
345
|
+
byte[] bytes = new byte[length * 2];
|
346
|
+
wcharPointer.get(0, bytes, 0, length * 2);
|
347
|
+
CharBuffer chars = wideCharset.decode(ByteBuffer.wrap(bytes));
|
348
|
+
return chars.toString();
|
349
|
+
}
|
350
|
+
|
351
|
+
private Pointer toWideChars(String s)
|
352
|
+
{
|
353
|
+
ByteBuffer bytes = wideCharset.encode(s);
|
354
|
+
Pointer pointer = new ArrayMemoryIO(Runtime.getSystemRuntime(), bytes.remaining() + 2);
|
355
|
+
pointer.put(0, bytes.array(), 0, bytes.remaining());
|
356
|
+
pointer.putShort(bytes.remaining(), (short)0);
|
357
|
+
return pointer;
|
358
|
+
}
|
359
|
+
|
360
|
+
private void checkSQLResult(String operation, short result) throws SQLException
|
361
|
+
{
|
362
|
+
switch (result) {
|
363
|
+
case ODBC.SQL_SUCCESS:
|
364
|
+
break;
|
365
|
+
|
366
|
+
case ODBC.SQL_SUCCESS_WITH_INFO:
|
367
|
+
StringBuilder sqlState = new StringBuilder();
|
368
|
+
StringBuilder sqlMessage = new StringBuilder();
|
369
|
+
if (getErrorMessage(sqlState, sqlMessage)) {
|
370
|
+
logger.info(String.format("SQL Server Native Client : %s : %s", operation, sqlMessage));
|
371
|
+
}
|
372
|
+
break;
|
373
|
+
|
374
|
+
default:
|
375
|
+
throwException(operation, result);
|
376
|
+
}
|
377
|
+
}
|
378
|
+
|
379
|
+
private void checkBCPResult(String operation, short result) throws SQLException
|
380
|
+
{
|
381
|
+
switch (result) {
|
382
|
+
case NativeClient.SUCCEED:
|
383
|
+
break;
|
384
|
+
|
385
|
+
default:
|
386
|
+
throwException(operation, result);
|
387
|
+
}
|
388
|
+
}
|
389
|
+
|
390
|
+
private void throwException(String operation, short result) throws SQLException
|
391
|
+
{
|
392
|
+
String message = String.format("SQL Server Native Client : %s failed : %d.", operation, result);
|
393
|
+
|
394
|
+
if (odbcHandle != null) {
|
395
|
+
StringBuilder sqlState = new StringBuilder();
|
396
|
+
StringBuilder sqlMessage = new StringBuilder();
|
397
|
+
if (getErrorMessage(sqlState, sqlMessage)) {
|
398
|
+
message = String.format("SQL Server Native Client : %s failed (sql state = %s) : %s", operation, sqlState, sqlMessage);
|
399
|
+
}
|
400
|
+
}
|
401
|
+
|
402
|
+
logger.error(message);
|
403
|
+
throw new SQLException(message);
|
404
|
+
}
|
405
|
+
|
406
|
+
private boolean getErrorMessage(StringBuilder sqlState, StringBuilder sqlMessage)
|
407
|
+
{
|
408
|
+
final int sqlStateLength = 5;
|
409
|
+
// (5 (SQL state length) + 1 (terminator length)) * 2 (wchar size)
|
410
|
+
Pointer sqlStatePointer = new ArrayMemoryIO(Runtime.getSystemRuntime(), (sqlStateLength + 1) * 2);
|
411
|
+
Pointer sqlMessagePointer = new ArrayMemoryIO(Runtime.getSystemRuntime(), 512);
|
412
|
+
Pointer lengthPointer = new ArrayMemoryIO(Runtime.getSystemRuntime(), 4);
|
413
|
+
|
414
|
+
for (short record = 1;; record++) {
|
415
|
+
short result = odbc.SQLGetDiagRecW(
|
416
|
+
ODBC.SQL_HANDLE_DBC,
|
417
|
+
odbcHandle,
|
418
|
+
record,
|
419
|
+
sqlStatePointer,
|
420
|
+
null,
|
421
|
+
sqlMessagePointer,
|
422
|
+
(short)(sqlMessagePointer.size() / 2),
|
423
|
+
lengthPointer);
|
424
|
+
|
425
|
+
if (result == ODBC.SQL_SUCCESS) {
|
426
|
+
if (record > 1) {
|
427
|
+
sqlState.append(",");
|
428
|
+
}
|
429
|
+
sqlState.append(toString(sqlStatePointer, sqlStateLength));
|
430
|
+
sqlMessage.append(toString(sqlMessagePointer, lengthPointer.getInt(0)));
|
431
|
+
} else {
|
432
|
+
if (record == 1) {
|
433
|
+
return false;
|
434
|
+
}
|
435
|
+
break;
|
436
|
+
}
|
437
|
+
}
|
438
|
+
|
439
|
+
return true;
|
440
|
+
}
|
441
|
+
|
442
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
package org.embulk.output.sqlserver.nativeclient;
|
2
|
+
|
3
|
+
import jnr.ffi.Pointer;
|
4
|
+
|
5
|
+
|
6
|
+
/**
|
7
|
+
* sqlncli11.dll also has SQLXXX methods, but we should call those methods in odbc32.dll .
|
8
|
+
*/
|
9
|
+
public interface ODBC
|
10
|
+
{
|
11
|
+
static short SQL_SUCCESS = 0;
|
12
|
+
static short SQL_SUCCESS_WITH_INFO = 1;
|
13
|
+
|
14
|
+
static short SQL_HANDLE_ENV = 1;
|
15
|
+
static short SQL_HANDLE_DBC = 2;
|
16
|
+
|
17
|
+
static short SQL_ATTR_ODBC_VERSION = 200;
|
18
|
+
|
19
|
+
static short SQL_COPT_SS_BASE = 1200;
|
20
|
+
static short SQL_COPT_SS_BCP = SQL_COPT_SS_BASE + 19;
|
21
|
+
|
22
|
+
static short SQL_DRIVER_NOPROMPT = 0;
|
23
|
+
|
24
|
+
static long SQL_OV_ODBC3 = 3;
|
25
|
+
static long SQL_BCP_ON = 1;
|
26
|
+
|
27
|
+
static int SQL_IS_INTEGER = -6;
|
28
|
+
static short SQL_NTS = -3;
|
29
|
+
|
30
|
+
|
31
|
+
short SQLAllocHandle(short handleType, Pointer inputHandle, Pointer outputHandle);
|
32
|
+
|
33
|
+
short SQLSetEnvAttr(Pointer environmentHandle, short attribute, Pointer value, int stringLength);
|
34
|
+
|
35
|
+
short SQLSetConnectAttrW(Pointer hdbc, int fAttribute, Pointer rgbValue, int cbValue);
|
36
|
+
|
37
|
+
short SQLDriverConnectW(Pointer hdbc, Pointer hwnd,
|
38
|
+
Pointer szConnStrIn, short cchConnStrIn,
|
39
|
+
Pointer szConnStrOut, short cchConnStrOutMax, Pointer pcchConnStrOut,
|
40
|
+
short fDriverCompletion);
|
41
|
+
|
42
|
+
short SQLFreeHandle(short handleType, Pointer handle);
|
43
|
+
|
44
|
+
short SQLGetDiagRecW(short handleType, Pointer handle, short recNumber,
|
45
|
+
Pointer sqlState, Pointer nativeErrorPtr,
|
46
|
+
Pointer messageText, short bufferLength, Pointer textLengthPtr);
|
47
|
+
}
|