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