OmniSciDB  0fdbebe030
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ResultSetGeoSerialization.h
Go to the documentation of this file.
1 /*
2  * Copyright 2018 MapD Technologies, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
24 #ifndef QUERYENGINE_RESULTSET_GEOSERIALIZATION_H
25 #define QUERYENGINE_RESULTSET_GEOSERIALIZATION_H
26 
27 #include "QueryEngine/ResultSet.h"
30 #include "Shared/geo_types.h"
31 #include "Shared/sqltypes.h"
32 
33 using VarlenDatumPtr = std::unique_ptr<VarlenDatum>;
34 
35 template <SQLTypes GEO_SOURCE_TYPE>
37  static_assert(IS_GEO(GEO_SOURCE_TYPE), "Invalid geo type for target value serializer.");
38 };
39 
40 template <SQLTypes GEO_SOURCE_TYPE>
42  static_assert(IS_GEO(GEO_SOURCE_TYPE), "Invalid geo type for wkt serializer.");
43 };
44 
45 template <SQLTypes GEO_SOURCE_TYPE>
47  static_assert(IS_GEO(GEO_SOURCE_TYPE),
48  "Invalid geo type for target value ptr serializer.");
49 };
50 
51 template <ResultSet::GeoReturnType GEO_RETURN_TYPE, SQLTypes GEO_SOURCE_TYPE>
53  static_assert(GEO_RETURN_TYPE == ResultSet::GeoReturnType::GeoTargetValue ||
54  GEO_RETURN_TYPE == ResultSet::GeoReturnType::WktString ||
56  "ResultSet: Unrecognized Geo Return Type encountered.");
57 };
58 
59 template <SQLTypes GEO_SOURCE_TYPE>
60 struct GeoReturnTypeTraits<ResultSet::GeoReturnType::GeoTargetValue, GEO_SOURCE_TYPE> {
62 };
63 
64 template <SQLTypes GEO_SOURCE_TYPE>
65 struct GeoReturnTypeTraits<ResultSet::GeoReturnType::WktString, GEO_SOURCE_TYPE> {
67 };
68 
69 template <SQLTypes GEO_SOURCE_TYPE>
70 struct GeoReturnTypeTraits<ResultSet::GeoReturnType::GeoTargetValuePtr, GEO_SOURCE_TYPE> {
72 };
73 
74 namespace {
75 
76 template <typename T>
77 void unpack_geo_vector(std::vector<T>& output, const int8_t* input_ptr, const size_t sz) {
78  if (sz == 0) {
79  return;
80  }
81  auto elems = reinterpret_cast<const T*>(input_ptr);
82  CHECK_EQ(size_t(0), sz % sizeof(T));
83  const size_t num_elems = sz / sizeof(T);
84  output.resize(num_elems);
85  for (size_t i = 0; i < num_elems; i++) {
86  output[i] = elems[i];
87  }
88 }
89 
90 template <typename T>
91 void decompress_geo_coords_geoint32(std::vector<T>& dec,
92  const int8_t* enc,
93  const size_t sz) {
94  if (sz == 0) {
95  return;
96  }
97  const auto compressed_coords = reinterpret_cast<const int32_t*>(enc);
98  const auto num_coords = sz / sizeof(int32_t);
99  dec.resize(num_coords);
100  for (size_t i = 0; i < num_coords; i += 2) {
101  dec[i] = Geo_namespace::decompress_longitude_coord_geoint32(compressed_coords[i]);
102  dec[i + 1] =
103  Geo_namespace::decompress_lattitude_coord_geoint32(compressed_coords[i + 1]);
104  }
105 }
106 
107 template <typename T>
108 std::shared_ptr<std::vector<T>> decompress_coords(const SQLTypeInfo& geo_ti,
109  const int8_t* coords,
110  const size_t coords_sz);
111 
112 template <>
113 std::shared_ptr<std::vector<double>> decompress_coords<double>(const SQLTypeInfo& geo_ti,
114  const int8_t* coords,
115  const size_t coords_sz) {
116  auto decompressed_coords_ptr = std::make_shared<std::vector<double>>();
117  if (geo_ti.get_compression() == kENCODING_GEOINT) {
118  if (geo_ti.get_comp_param() == 32) {
119  decompress_geo_coords_geoint32(*decompressed_coords_ptr, coords, coords_sz);
120  }
121  } else {
122  CHECK_EQ(geo_ti.get_compression(), kENCODING_NONE);
123  unpack_geo_vector(*decompressed_coords_ptr, coords, coords_sz);
124  }
125  return decompressed_coords_ptr;
126 }
127 
128 bool is_null_point(const SQLTypeInfo& geo_ti,
129  const int8_t* coords,
130  const size_t coords_sz) {
131  if (geo_ti.get_type() == kPOINT && !geo_ti.get_notnull()) {
132  if (geo_ti.get_compression() == kENCODING_GEOINT) {
133  if (geo_ti.get_comp_param() == 32) {
134  return Geo_namespace::is_null_point_longitude_geoint32(*((int32_t*)coords));
135  }
136  } else {
138  return *((double*)coords) == NULL_ARRAY_DOUBLE;
139  }
140  }
141  return false;
142 }
143 
144 } // namespace
145 
146 // Point
147 template <>
149  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
150  std::array<VarlenDatumPtr, 1>& vals) {
151  if (!geo_ti.get_notnull() && vals[0]->is_null) {
152  // Alternatively, could decompress vals[0] and check for NULL array sentinel
153  return GeoTargetValue(boost::optional<GeoPointTargetValue>{});
154  }
155  return GeoTargetValue(boost::optional<GeoPointTargetValue>{
156  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length)});
157  }
158 };
159 
160 template <>
162  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
163  std::array<VarlenDatumPtr, 1>& vals) {
164  // TODO: support EMPTY geo and serialize it as GEOMETRYCOLLECTION EMPTY
165  if (!geo_ti.get_notnull() && vals[0]->is_null) {
166  return NullableString("NULL");
167  }
169  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length));
170  return NullableString(point.getWktString());
171  }
172 };
173 
174 template <>
176  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
177  std::array<VarlenDatumPtr, 1>& vals) {
178  if (!geo_ti.get_notnull() && vals[0]->is_null) {
179  // NULL geo
180  // Pass along null datum, instead of an empty/null GeoTargetValuePtr
181  // return GeoTargetValuePtr();
182  }
183  return GeoPointTargetValuePtr({std::move(vals[0])});
184  }
185 };
186 
187 // LineString
188 template <>
190  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
191  std::array<VarlenDatumPtr, 1>& vals) {
192  if (!geo_ti.get_notnull() && vals[0]->is_null) {
193  return GeoTargetValue(boost::optional<GeoLineStringTargetValue>{});
194  }
195  return GeoTargetValue(boost::optional<GeoLineStringTargetValue>{
196  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length)});
197  }
198 };
199 
200 template <>
202  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
203  std::array<VarlenDatumPtr, 1>& vals) {
204  if (!geo_ti.get_notnull() && vals[0]->is_null) {
205  // May need to generate "LINESTRING EMPTY" instead of NULL
206  return NullableString("NULL");
207  }
208  Geo_namespace::GeoLineString linestring(
209  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length));
210  return NullableString(linestring.getWktString());
211  }
212 };
213 
214 template <>
216  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
217  std::array<VarlenDatumPtr, 1>& vals) {
218  if (!geo_ti.get_notnull() && vals[0]->is_null) {
219  // NULL geo
220  // Pass along null datum, instead of an empty/null GeoTargetValuePtr
221  // return GeoTargetValuePtr();
222  }
223  return GeoLineStringTargetValuePtr({std::move(vals[0])});
224  }
225 };
226 
227 // Polygon
228 template <>
230  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
231  std::array<VarlenDatumPtr, 2>& vals) {
232  if (!geo_ti.get_notnull() && (vals[0]->is_null || vals[1]->is_null)) {
233  return GeoTargetValue(boost::optional<GeoPolyTargetValue>{});
234  }
235  std::vector<int32_t> ring_sizes_vec;
236  unpack_geo_vector(ring_sizes_vec, vals[1]->pointer, vals[1]->length);
237  auto gtv = GeoPolyTargetValue(
238  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length),
239  ring_sizes_vec);
240  return GeoTargetValue(gtv);
241  }
242 };
243 
244 template <>
246  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
247  std::array<VarlenDatumPtr, 2>& vals) {
248  if (!geo_ti.get_notnull() && (vals[0]->is_null || vals[1]->is_null)) {
249  // May need to generate "POLYGON EMPTY" instead of NULL
250  return NullableString("NULL");
251  }
252  std::vector<int32_t> ring_sizes_vec;
253  unpack_geo_vector(ring_sizes_vec, vals[1]->pointer, vals[1]->length);
255  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length),
256  ring_sizes_vec);
257  return NullableString(poly.getWktString());
258  };
259 };
260 
261 template <>
263  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
264  std::array<VarlenDatumPtr, 2>& vals) {
265  if (!geo_ti.get_notnull() && (vals[0]->is_null || vals[1]->is_null)) {
266  // NULL geo
267  // Pass along null datum, instead of an empty/null GeoTargetValuePtr
268  // return GeoTargetValuePtr();
269  }
270  return GeoPolyTargetValuePtr({std::move(vals[0]), std::move(vals[1])});
271  }
272 };
273 
274 // MultiPolygon
275 template <>
277  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
278  std::array<VarlenDatumPtr, 3>& vals) {
279  if (!geo_ti.get_notnull() &&
280  (vals[0]->is_null || vals[1]->is_null || vals[2]->is_null)) {
281  return GeoTargetValue(boost::optional<GeoMultiPolyTargetValue>{});
282  }
283  std::vector<int32_t> ring_sizes_vec;
284  unpack_geo_vector(ring_sizes_vec, vals[1]->pointer, vals[1]->length);
285  std::vector<int32_t> poly_rings_vec;
286  unpack_geo_vector(poly_rings_vec, vals[2]->pointer, vals[2]->length);
287  auto gtv = GeoMultiPolyTargetValue(
288  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length),
289  ring_sizes_vec,
290  poly_rings_vec);
291  return GeoTargetValue(gtv);
292  }
293 };
294 
295 template <>
297  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
298  std::array<VarlenDatumPtr, 3>& vals) {
299  if (!geo_ti.get_notnull() &&
300  (vals[0]->is_null || vals[1]->is_null || vals[2]->is_null)) {
301  // May need to generate "MULTIPOLYGON EMPTY" instead of NULL
302  return NullableString("NULL");
303  }
304  std::vector<int32_t> ring_sizes_vec;
305  unpack_geo_vector(ring_sizes_vec, vals[1]->pointer, vals[1]->length);
306  std::vector<int32_t> poly_rings_vec;
307  unpack_geo_vector(poly_rings_vec, vals[2]->pointer, vals[2]->length);
309  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length),
310  ring_sizes_vec,
311  poly_rings_vec);
312  return NullableString(mpoly.getWktString());
313  }
314 };
315 
316 template <>
318  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
319  std::array<VarlenDatumPtr, 3>& vals) {
320  if (!geo_ti.get_notnull() &&
321  (vals[0]->is_null || vals[1]->is_null || vals[2]->is_null)) {
322  // NULL geo
323  // Pass along null datum, instead of an empty/null GeoTargetValuePtr
324  // return GeoTargetValuePtr();
325  }
327  {std::move(vals[0]), std::move(vals[1]), std::move(vals[2])});
328  }
329 };
330 
331 #endif // QUERYENGINE_RESULTSET_GEOSERIALIZATION_H
#define CHECK_EQ(x, y)
Definition: Logger.h:205
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 2 > &vals)
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 3 > &vals)
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 3 > &vals)
#define NULL_ARRAY_DOUBLE
Definition: sqltypes.h:183
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 1 > &vals)
std::string getWktString() const
Definition: geo_types.cpp:157
void unpack_geo_vector(std::vector< T > &output, const int8_t *input_ptr, const size_t sz)
bool is_null_point(const SQLTypeInfo &geo_ti, const int8_t *coords, const size_t coords_sz)
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 2 > &vals)
Constants for Builtin SQL Types supported by OmniSci.
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:248
Compression / decompression routines for geospatial coordinates. Suitable for inclusion by the LLVM c...
DEVICE bool is_null_point_longitude_geoint32(const int32_t compressed)
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 1 > &vals)
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 1 > &vals)
std::shared_ptr< std::vector< double > > decompress_coords< double >(const SQLTypeInfo &geo_ti, const int8_t *coords, const size_t coords_sz)
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 1 > &vals)
DEVICE double decompress_lattitude_coord_geoint32(const int32_t compressed)
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 3 > &vals)
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:256
boost::optional< boost::variant< GeoPointTargetValue, GeoLineStringTargetValue, GeoPolyTargetValue, GeoMultiPolyTargetValue >> GeoTargetValue
Definition: TargetValue.h:161
std::shared_ptr< std::vector< T > > decompress_coords(const SQLTypeInfo &geo_ti, const int8_t *coords, const size_t coords_sz)
boost::variant< std::string, void * > NullableString
Definition: TargetValue.h:155
HOST DEVICE int get_comp_param() const
Definition: sqltypes.h:257
void decompress_geo_coords_geoint32(std::vector< T > &dec, const int8_t *enc, const size_t sz)
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 1 > &vals)
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 2 > &vals)
Basic constructors and methods of the row set interface.
boost::variant< ScalarTargetValue, ArrayTargetValue, GeoTargetValue, GeoTargetValuePtr > TargetValue
Definition: TargetValue.h:167
DEVICE double decompress_longitude_coord_geoint32(const int32_t compressed)
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:255
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 1 > &vals)
std::unique_ptr< VarlenDatum > VarlenDatumPtr
#define IS_GEO(T)
Definition: sqltypes.h:163
boost::variant< GeoPointTargetValuePtr, GeoLineStringTargetValuePtr, GeoPolyTargetValuePtr, GeoMultiPolyTargetValuePtr > GeoTargetValuePtr
Definition: TargetValue.h:165