-
Notifications
You must be signed in to change notification settings - Fork 227
Expand file tree
/
Copy pathJDBC20DataHandler.java
More file actions
153 lines (129 loc) · 4.33 KB
/
JDBC20DataHandler.java
File metadata and controls
153 lines (129 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
* Jython Database Specification API 2.0
*
*
* Copyright (c) 2001 brian zimmer <bzimmer@ziclix.com>
*
*/
package com.ziclix.python.sql;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.Array;
import java.sql.Blob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.python.core.Py;
import org.python.core.PyFile;
import org.python.core.PyObject;
import org.python.core.util.StringUtil;
/**
* Support for JDBC 2.x type mappings, including Arrays, CLOBs and BLOBs.
*
* @author brian zimmer
*/
public class JDBC20DataHandler extends FilterDataHandler {
/**
* Handle JDBC 2.0 datatypes.
*/
public JDBC20DataHandler(DataHandler datahandler) {
super(datahandler);
}
/**
* Handle CLOBs and BLOBs.
*
* @param stmt
* @param index
* @param object
* @param type
* @throws SQLException
*/
@SuppressWarnings("fallthrough")
@Override
public void setJDBCObject(PreparedStatement stmt, int index, PyObject object, int type)
throws SQLException {
if (DataHandler.checkNull(stmt, index, object, type)) {
return;
}
switch (type) {
case Types.CLOB:
if (object instanceof PyFile) {
object = ((PyFile) object).read();
}
String clob = (String) object.__tojava__(String.class);
int length = clob.length();
InputStream stream = new ByteArrayInputStream(StringUtil.toBytes(clob));
stream = new BufferedInputStream(stream);
stmt.setBinaryStream(index, stream, length);
// Reader reader = new StringReader(clob);
// reader = new BufferedReader(reader);
// stmt.setCharacterStream(index, reader, length);
break;
case Types.BLOB:
byte[] lob = null;
Object jobject = null;
if (object instanceof PyFile) {
jobject = object.__tojava__(InputStream.class);
} else {
jobject = object.__tojava__(Object.class);
}
// it really is unfortunate that I need to send the length of the stream
if (jobject instanceof InputStream) {
lob = read((InputStream) jobject);
} else if (jobject instanceof byte[]) {
lob = (byte[]) jobject;
}
if (lob != null) {
stmt.setBytes(index, lob);
break;
}
default :
super.setJDBCObject(stmt, index, object, type);
break;
}
}
/**
* Get the object from the result set.
*
* @param set
* @param col
* @param type
* @return a Python object
* @throws SQLException
*/
@Override
public PyObject getPyObject(ResultSet set, int col, int type) throws SQLException {
PyObject obj = Py.None;
switch (type) {
case Types.NUMERIC:
case Types.DECIMAL:
// in JDBC 2.0, use of a scale is deprecated
try {
BigDecimal bd = set.getBigDecimal(col);
obj = (bd == null) ? Py.None : Py.newFloat(bd.doubleValue());
} catch (SQLException e) {
obj = super.getPyObject(set, col, type);
}
break;
case Types.CLOB:
Reader reader = set.getCharacterStream(col);
obj = reader == null ? Py.None : Py.newUnicode(read(reader));
break;
case Types.BLOB:
Blob blob = set.getBlob(col);
obj = blob == null ? Py.None : Py.java2py(read(blob.getBinaryStream()));
break;
case Types.ARRAY:
Array array = set.getArray(col);
obj = array == null ? Py.None : Py.java2py(array.getArray());
break;
default :
return super.getPyObject(set, col, type);
}
return (set.wasNull() || (obj == null)) ? Py.None : obj;
}
}