Skip to content

Commit 523387f

Browse files
author
Mike Pigott
committed
Updating the API to support an optional 'includeMetadata' field.
1 parent 5af1b5b commit 523387f

2 files changed

Lines changed: 96 additions & 21 deletions

File tree

java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrow.java

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@
6868
*/
6969
public class JdbcToArrow {
7070

71+
public static final String SQL_CATALOG_NAME_KEY = "SQL_CATALOG_NAME";
72+
public static final String SQL_TABLE_NAME_KEY = "SQL_TABLE_NAME";
73+
public static final String SQL_COLUMN_NAME_KEY = "SQL_COLUMN_NAME";
74+
public static final String SQL_TYPE_KEY = "SQL_TYPE";
75+
7176
/**
7277
* For the given SQL query, execute and fetch the data from Relational DB and convert it to Arrow objects.
7378
* This method uses the default Calendar instance with default TimeZone and Locale as returned by the JVM.
@@ -89,7 +94,8 @@ public static VectorSchemaRoot sqlToArrow(Connection connection, String query, B
8994
Preconditions.checkArgument(query != null && query.length() > 0, "SQL query can not be null or empty");
9095
Preconditions.checkNotNull(allocator, "Memory allocator object can not be null");
9196

92-
return sqlToArrow(connection, query, allocator, Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.ROOT));
97+
return sqlToArrow(connection, query, allocator,
98+
Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.ROOT), false);
9399
}
94100

95101
/**
@@ -110,13 +116,42 @@ public static VectorSchemaRoot sqlToArrow(
110116
String query,
111117
BaseAllocator allocator,
112118
Calendar calendar) throws SQLException, IOException {
119+
120+
Preconditions.checkNotNull(connection, "JDBC connection object can not be null");
121+
Preconditions.checkArgument(query != null && query.length() > 0, "SQL query can not be null or empty");
122+
Preconditions.checkNotNull(allocator, "Memory allocator object can not be null");
123+
Preconditions.checkNotNull(calendar, "Calendar object can not be null");
124+
125+
return sqlToArrow(connection, query, allocator, calendar, false);
126+
}
127+
128+
/**
129+
* For the given SQL query, execute and fetch the data from Relational DB and convert it to Arrow objects.
130+
*
131+
* @param connection Database connection to be used. This method will not close the passed connection object.
132+
* Since the caller has passed the connection object it's the responsibility of the caller
133+
* to close or return the connection to the pool.
134+
* @param query The DB Query to fetch the data.
135+
* @param allocator Memory allocator
136+
* @param calendar Calendar object to use to handle Date, Time and Timestamp datasets.
137+
* @param includeMetadata Whether to include column information in the schema field metadata.
138+
* @return Arrow Data Objects {@link VectorSchemaRoot}
139+
* @throws SQLException Propagate any SQL Exceptions to the caller after closing any resources opened such as
140+
* ResultSet and Statement objects.
141+
*/
142+
public static VectorSchemaRoot sqlToArrow(
143+
Connection connection,
144+
String query,
145+
BaseAllocator allocator,
146+
Calendar calendar,
147+
boolean includeMetadata) throws SQLException, IOException {
113148
Preconditions.checkNotNull(connection, "JDBC connection object can not be null");
114149
Preconditions.checkArgument(query != null && query.length() > 0, "SQL query can not be null or empty");
115150
Preconditions.checkNotNull(allocator, "Memory allocator object can not be null");
116151
Preconditions.checkNotNull(calendar, "Calendar object can not be null");
117152

118153
try (Statement stmt = connection.createStatement()) {
119-
return sqlToArrow(stmt.executeQuery(query), allocator, calendar);
154+
return sqlToArrow(stmt.executeQuery(query), allocator, calendar, includeMetadata);
120155
}
121156
}
122157

@@ -163,7 +198,7 @@ public static VectorSchemaRoot sqlToArrow(ResultSet resultSet, Calendar calendar
163198
Preconditions.checkNotNull(calendar, "Calendar object can not be null");
164199

165200
RootAllocator rootAllocator = new RootAllocator(Integer.MAX_VALUE);
166-
VectorSchemaRoot root = sqlToArrow(resultSet, rootAllocator, calendar);
201+
VectorSchemaRoot root = sqlToArrow(resultSet, rootAllocator, calendar, false);
167202

168203
return root;
169204
}
@@ -177,14 +212,40 @@ public static VectorSchemaRoot sqlToArrow(ResultSet resultSet, Calendar calendar
177212
* @return Arrow Data Objects {@link VectorSchemaRoot}
178213
* @throws SQLException on error
179214
*/
180-
public static VectorSchemaRoot sqlToArrow(ResultSet resultSet, BaseAllocator allocator, Calendar calendar)
215+
public static VectorSchemaRoot sqlToArrow(
216+
ResultSet resultSet,
217+
BaseAllocator allocator,
218+
Calendar calendar)
219+
throws SQLException, IOException {
220+
Preconditions.checkNotNull(resultSet, "JDBC ResultSet object can not be null");
221+
Preconditions.checkNotNull(allocator, "Memory Allocator object can not be null");
222+
Preconditions.checkNotNull(calendar, "Calendar object can not be null");
223+
224+
return sqlToArrow(resultSet, allocator, calendar, false);
225+
}
226+
227+
/**
228+
* For the given JDBC {@link ResultSet}, fetch the data from Relational DB and convert it to Arrow objects.
229+
*
230+
* @param resultSet ResultSet to use to fetch the data from underlying database
231+
* @param allocator Memory allocator to use.
232+
* @param calendar Calendar instance to use for Date, Time and Timestamp datasets.
233+
* @param metadata Whether to include column information in the schema field metadata.
234+
* @return Arrow Data Objects {@link VectorSchemaRoot}
235+
* @throws SQLException on error
236+
*/
237+
public static VectorSchemaRoot sqlToArrow(
238+
ResultSet resultSet,
239+
BaseAllocator allocator,
240+
Calendar calendar,
241+
boolean includeMetadata)
181242
throws SQLException, IOException {
182243
Preconditions.checkNotNull(resultSet, "JDBC ResultSet object can not be null");
183244
Preconditions.checkNotNull(allocator, "Memory Allocator object can not be null");
184245
Preconditions.checkNotNull(calendar, "Calendar object can not be null");
185246

186247
VectorSchemaRoot root = VectorSchemaRoot.create(
187-
JdbcToArrowUtils.jdbcToArrowSchema(resultSet.getMetaData(), calendar), allocator);
248+
JdbcToArrowUtils.jdbcToArrowSchema(resultSet.getMetaData(), calendar, includeMetadata), allocator);
188249
JdbcToArrowUtils.jdbcToArrowVectors(resultSet, root, calendar);
189250
return root;
190251
}

java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowUtils.java

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@
3636
import java.sql.Types;
3737
import java.util.ArrayList;
3838
import java.util.Calendar;
39+
import java.util.HashMap;
3940
import java.util.List;
41+
import java.util.Map;
4042

4143
import org.apache.arrow.vector.BaseFixedWidthVector;
4244
import org.apache.arrow.vector.BigIntVector;
@@ -124,7 +126,8 @@ public class JdbcToArrowUtils {
124126
* @return {@link Schema}
125127
* @throws SQLException on error
126128
*/
127-
public static Schema jdbcToArrowSchema(ResultSetMetaData rsmd, Calendar calendar) throws SQLException {
129+
public static Schema jdbcToArrowSchema(ResultSetMetaData rsmd, Calendar calendar, boolean includeMetadata)
130+
throws SQLException {
128131

129132
Preconditions.checkNotNull(rsmd, "JDBC ResultSetMetaData object can't be null");
130133
Preconditions.checkNotNull(calendar, "Calendar object can't be null");
@@ -135,35 +138,47 @@ public static Schema jdbcToArrowSchema(ResultSetMetaData rsmd, Calendar calendar
135138
final String columnName = rsmd.getColumnName(i);
136139
final FieldType fieldType;
137140

141+
final Map<String, String> metadata;
142+
if (includeMetadata) {
143+
metadata = new HashMap<String, String>();
144+
metadata.put(JdbcToArrow.SQL_CATALOG_NAME_KEY, rsmd.getCatalogName(i));
145+
metadata.put(JdbcToArrow.SQL_TABLE_NAME_KEY, rsmd.getTableName(i));
146+
metadata.put(JdbcToArrow.SQL_COLUMN_NAME_KEY, columnName);
147+
metadata.put(JdbcToArrow.SQL_TYPE_KEY, rsmd.getColumnTypeName(i));
148+
149+
} else {
150+
metadata = null;
151+
}
152+
138153
switch (rsmd.getColumnType(i)) {
139154
case Types.BOOLEAN:
140155
case Types.BIT:
141-
fieldType = FieldType.nullable(new ArrowType.Bool());
156+
fieldType = new FieldType(true, new ArrowType.Bool(), null, metadata);
142157
break;
143158
case Types.TINYINT:
144-
fieldType = FieldType.nullable(new ArrowType.Int(8, true));
159+
fieldType = new FieldType(true, new ArrowType.Int(8, true), null, metadata);
145160
break;
146161
case Types.SMALLINT:
147-
fieldType = FieldType.nullable(new ArrowType.Int(16, true));
162+
fieldType = new FieldType(true, new ArrowType.Int(16, true), null, metadata);
148163
break;
149164
case Types.INTEGER:
150-
fieldType = FieldType.nullable(new ArrowType.Int(32, true));
165+
fieldType = new FieldType(true, new ArrowType.Int(32, true), null, metadata);
151166
break;
152167
case Types.BIGINT:
153-
fieldType = FieldType.nullable(new ArrowType.Int(64, true));
168+
fieldType = new FieldType(true, new ArrowType.Int(64, true), null, metadata);
154169
break;
155170
case Types.NUMERIC:
156171
case Types.DECIMAL:
157172
int precision = rsmd.getPrecision(i);
158173
int scale = rsmd.getScale(i);
159-
fieldType = FieldType.nullable(new ArrowType.Decimal(precision, scale));
174+
fieldType = new FieldType(true, new ArrowType.Decimal(precision, scale), null, metadata);
160175
break;
161176
case Types.REAL:
162177
case Types.FLOAT:
163-
fieldType = FieldType.nullable(new ArrowType.FloatingPoint(SINGLE));
178+
fieldType = new FieldType(true, new ArrowType.FloatingPoint(SINGLE), null, metadata);
164179
break;
165180
case Types.DOUBLE:
166-
fieldType = FieldType.nullable(new ArrowType.FloatingPoint(DOUBLE));
181+
fieldType = new FieldType(true, new ArrowType.FloatingPoint(DOUBLE), null, metadata);
167182
break;
168183
case Types.CHAR:
169184
case Types.NCHAR:
@@ -172,24 +187,23 @@ public static Schema jdbcToArrowSchema(ResultSetMetaData rsmd, Calendar calendar
172187
case Types.LONGVARCHAR:
173188
case Types.LONGNVARCHAR:
174189
case Types.CLOB:
175-
fieldType = FieldType.nullable(new ArrowType.Utf8());
190+
fieldType = new FieldType(true, new ArrowType.Utf8(), null, metadata);
176191
break;
177192
case Types.DATE:
178-
fieldType = FieldType.nullable(new ArrowType.Date(DateUnit.MILLISECOND));
193+
fieldType = new FieldType(true, new ArrowType.Date(DateUnit.MILLISECOND), null, metadata);
179194
break;
180195
case Types.TIME:
181-
fieldType = FieldType.nullable(new ArrowType.Time(TimeUnit.MILLISECOND, 32));
196+
fieldType = new FieldType(true, new ArrowType.Time(TimeUnit.MILLISECOND, 32), null, metadata);
182197
break;
183198
case Types.TIMESTAMP:
184-
fieldType = FieldType.nullable(new ArrowType.Timestamp(TimeUnit.MILLISECOND, calendar.getTimeZone().getID()));
199+
fieldType = new FieldType(true, new ArrowType.Timestamp(TimeUnit.MILLISECOND, calendar.getTimeZone().getID()),
200+
null, metadata);
185201
break;
186202
case Types.BINARY:
187203
case Types.VARBINARY:
188204
case Types.LONGVARBINARY:
189-
fieldType = FieldType.nullable(new ArrowType.Binary());
190-
break;
191205
case Types.BLOB:
192-
fieldType = FieldType.nullable(new ArrowType.Binary());
206+
fieldType = new FieldType(true, new ArrowType.Binary(), null, metadata);
193207
break;
194208

195209
case Types.ARRAY:

0 commit comments

Comments
 (0)