OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HeavyAIArray.java
Go to the documentation of this file.
1 package ai.heavy.jdbc;
2 
3 import static java.lang.Math.toIntExact;
4 
5 import java.math.BigDecimal;
6 import java.sql.*;
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.Date;
10 import java.util.Map;
11 
12 import ai.heavy.thrift.server.*;
13 
14 public class HeavyAIArray implements java.sql.Array {
15  private TDatumType type;
16  private Object[] elements;
17 
18  public HeavyAIArray(TDatumType type, Object[] elements) throws SQLException {
19  if (elements == null) {
20  throw new SQLException("Elements[] cannot be null");
21  }
22  this.type = type;
23  this.elements = elements;
24  Class<?> elements_class = elements.getClass().getComponentType();
25  switch (type) {
26  case TINYINT:
27  checkClass(elements_class, Byte.class);
28  break;
29  case SMALLINT:
30  checkClass(elements_class, Short.class);
31  break;
32  case INT:
33  checkClass(elements_class, Integer.class);
34  break;
35  case BIGINT:
36  checkClass(elements_class, Long.class);
37  break;
38  case BOOL:
39  checkClass(elements_class, Boolean.class);
40  break;
41  case TIME:
42  checkClass(elements_class, java.sql.Time.class);
43  break;
44  case TIMESTAMP:
45  checkClass(elements_class, java.sql.Timestamp.class);
46  break;
47  case DATE:
48  checkClass(elements_class, java.sql.Date.class);
49  break;
50  case FLOAT:
51  checkClass(elements_class, Float.class);
52  break;
53  case DECIMAL:
54  checkClass(elements_class, BigDecimal.class);
55  break;
56  case DOUBLE:
57  checkClass(elements_class, Double.class);
58  break;
59  case STR:
60  case POINT:
61  case MULTIPOINT:
62  case LINESTRING:
63  case MULTILINESTRING:
64  case POLYGON:
65  case MULTIPOLYGON:
66  checkClass(elements_class, String.class);
67  break;
68  default:
69  throw new AssertionError(type.toString());
70  }
71  }
72 
73  @Override
74  public String getBaseTypeName() throws SQLException {
75  return type.name();
76  }
77 
78  @Override
79  public int getBaseType() throws SQLException {
80  return HeavyAIType.toJava(type);
81  }
82 
83  @Override
84  public Object getArray() throws SQLException {
85  return elements;
86  }
87 
88  @Override
89  public Object getArray(long start, int size) throws SQLException {
90  checkSize(toIntExact(start), size);
91  return Arrays.copyOfRange(elements, toIntExact(start), size);
92  }
93 
94  @Override
95  public ResultSet getResultSet() throws SQLException {
96  return getResultSet(0, elements.length);
97  }
98 
99  @Override
100  public ResultSet getResultSet(long start, int size) throws SQLException {
101  checkSize(toIntExact(start), size);
102 
103  ArrayList<TColumnType> columnTypes = new ArrayList<>(2);
104  TTypeInfo idxType =
105  new TTypeInfo(TDatumType.BIGINT, TEncodingType.NONE, false, false, 0, 0, 0);
106  columnTypes.add(new TColumnType("INDEX", idxType, false, "", false, false, 0));
107  // @NOTE(Max): The problem here is that it's hard to know precision and scale.
108  // But it looks like we don't use those anywhere in ResultSet ???
109  int precision = (type == TDatumType.TIMESTAMP || type == TDatumType.TIME
110  || type == TDatumType.DATE
111  ? 3
112  : 0);
113  TTypeInfo valueType =
114  new TTypeInfo(type, TEncodingType.NONE, true, false, precision, 0, 0);
115  columnTypes.add(new TColumnType("VALUE", valueType, false, "", false, false, 1));
116 
117  Long[] indexes = new Long[size];
118  // indexes in SQL arrays start from 1
119  for (int i = 0; i < size; ++i) {
120  indexes[i] = (long) (i + 1);
121  }
122  TColumnData idxData = new TColumnData(Arrays.asList(indexes), null, null, null);
123  ArrayList<Boolean> idxNulls = new ArrayList<>(size);
124  for (int i = 0; i < size; ++i) {
125  idxNulls.add(Boolean.FALSE);
126  }
127 
128  TColumnData valuesData;
129  Long[] int_values = new Long[size];
130  Double[] real_values = new Double[size];
131  String[] string_values = new String[size];
132  boolean is_real = false, is_string = false;
133  ArrayList<Boolean> valueNulls = new ArrayList<>(size);
134  for (int i = toIntExact(start); i < start + size; ++i) {
135  if (elements[i] == null) {
136  valueNulls.add(true);
137  } else {
138  valueNulls.add(false);
139  switch (type) {
140  case TINYINT:
141  int_values[i] = ((Byte) elements[i]).longValue();
142  break;
143  case SMALLINT:
144  int_values[i] = ((Short) elements[i]).longValue();
145  break;
146  case INT:
147  int_values[i] = ((Integer) elements[i]).longValue();
148  break;
149  case BIGINT:
150  int_values[i] = (Long) elements[i];
151  break;
152  case BOOL:
153  int_values[i] = elements[i] == Boolean.TRUE ? 1l : 0l;
154  break;
155  case TIME:
156  int_values[i] = ((Time) elements[i]).getTime();
157  break;
158  case TIMESTAMP:
159  int_values[i] = ((Timestamp) elements[i]).getTime();
160  break;
161  case DATE:
162  int_values[i] = ((Date) elements[i]).getTime();
163  break;
164  case FLOAT:
165  is_real = true;
166  real_values[i] = ((Float) elements[i]).doubleValue();
167  break;
168  case DECIMAL:
169  is_real = true;
170  real_values[i] = ((BigDecimal) elements[i]).doubleValue();
171  break;
172  case DOUBLE:
173  is_real = true;
174  real_values[i] = (Double) elements[i];
175  break;
176  case STR:
177  case POINT:
178  case MULTIPOINT:
179  case LINESTRING:
180  case MULTILINESTRING:
181  case POLYGON:
182  case MULTIPOLYGON:
183  is_string = true;
184  string_values[i] = (String) elements[i];
185  break;
186  default:
187  throw new AssertionError(type.toString());
188  }
189  }
190  }
191  if (is_real) {
192  valuesData = new TColumnData(null, Arrays.asList(real_values), null, null);
193  } else if (is_string) {
194  valuesData = new TColumnData(null, null, Arrays.asList(string_values), null);
195  } else {
196  valuesData = new TColumnData(Arrays.asList(int_values), null, null, null);
197  }
198 
199  ArrayList<TColumn> columns = new ArrayList<>(2);
200  columns.add(new TColumn(idxData, idxNulls));
201  columns.add(new TColumn(valuesData, valueNulls));
202  TRowSet rowSet = new TRowSet(columnTypes, null, columns, true);
203  TQueryResult result = new TQueryResult(rowSet, 0, 0, "", "", true, TQueryType.READ);
204  return new HeavyAIResultSet(result, "");
205  }
206 
207  @Override
208  public void free() throws SQLException {
209  elements = null;
210  }
211 
212  @Override
213  public String toString() {
214  if (elements == null) {
215  return "NULL";
216  } else {
217  switch (type) {
218  case STR:
219  case POINT:
220  case MULTIPOINT:
221  case LINESTRING:
222  case MULTILINESTRING:
223  case POLYGON:
224  case MULTIPOLYGON:
225  case TIME:
226  case TIMESTAMP:
227  case DATE: {
228  StringBuilder sb = new StringBuilder("{");
229  for (Object e : elements) {
230  if (e != null) {
231  sb.append("'").append(e.toString()).append("', ");
232  } else {
233  sb.append("NULL").append(", ");
234  }
235  }
236  if (elements.length > 0) {
237  sb.delete(sb.length() - 2, sb.length());
238  }
239  sb.append("}");
240  return sb.toString();
241  }
242  default: {
243  String arr_str = Arrays.toString(elements);
244  return "{" + arr_str.substring(1, arr_str.length() - 1) + "}";
245  }
246  }
247  }
248  }
249 
250  @Override
251  public ResultSet getResultSet(long start, int size, Map<String, Class<?>> map)
252  throws SQLException {
253  throw new UnsupportedOperationException("Not supported yet,"
254  + " line:" + new Throwable().getStackTrace()[0].getLineNumber()
255  + " class:" + new Throwable().getStackTrace()[0].getClassName()
256  + " method:" + new Throwable().getStackTrace()[0].getMethodName());
257  }
258 
259  @Override
260  public ResultSet getResultSet(Map<String, Class<?>> map) throws SQLException {
261  throw new UnsupportedOperationException("Not supported yet,"
262  + " line:" + new Throwable().getStackTrace()[0].getLineNumber()
263  + " class:" + new Throwable().getStackTrace()[0].getClassName()
264  + " method:" + new Throwable().getStackTrace()[0].getMethodName());
265  }
266 
267  @Override
268  public Object getArray(long start, int size, Map<String, Class<?>> map)
269  throws SQLException {
270  throw new UnsupportedOperationException("Not supported yet,"
271  + " line:" + new Throwable().getStackTrace()[0].getLineNumber()
272  + " class:" + new Throwable().getStackTrace()[0].getClassName()
273  + " method:" + new Throwable().getStackTrace()[0].getMethodName());
274  }
275 
276  @Override
277  public Object getArray(Map<String, Class<?>> map) throws SQLException {
278  throw new UnsupportedOperationException("Not supported yet,"
279  + " line:" + new Throwable().getStackTrace()[0].getLineNumber()
280  + " class:" + new Throwable().getStackTrace()[0].getClassName()
281  + " method:" + new Throwable().getStackTrace()[0].getMethodName());
282  }
283 
284  private void checkSize(int start, int size) throws SQLException {
285  if (start < 0 || start >= elements.length || start + size > elements.length) {
286  throw new SQLException("Array length = " + Integer.toString(elements.length)
287  + ", slice start index = " + Integer.toString(start)
288  + ", slice length = " + Integer.toString(size));
289  }
290  }
291 
292  private void checkClass(Class<?> given, Class<?> expected) throws SQLException {
293  if (!expected.isAssignableFrom(given)) {
294  throw new SQLException("For array of " + getBaseTypeName() + ", elements of type "
295  + expected + " are expected. Got " + given + " instead");
296  }
297  }
298 }
Object getArray(long start, int size)
void checkSize(int start, int size)
size_t append(FILE *f, const size_t size, const int8_t *buf)
Appends the specified number of bytes to the end of the file f from buf.
Definition: File.cpp:158
HeavyAIArray(TDatumType type, Object[] elements)
ResultSet getResultSet(long start, int size, Map< String, Class<?>> map)
Object getArray(Map< String, Class<?>> map)
ResultSet getResultSet(Map< String, Class<?>> map)
void checkClass(Class<?> given, Class<?> expected)
Object getArray(long start, int size, Map< String, Class<?>> map)
ResultSet getResultSet(long start, int size)