OmniSciDB  b24e664e58
 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 <Shared/geo_compression.h>
28 #include <Shared/geo_types.h>
29 #include <Shared/sqltypes.h>
30 #include "ResultSet.h"
31 #include "TargetValue.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  auto elems = reinterpret_cast<const T*>(input_ptr);
79  CHECK(elems);
80  CHECK_EQ(size_t(0), sz % sizeof(T));
81  const size_t num_elems = sz / sizeof(T);
82  output.resize(num_elems);
83  for (size_t i = 0; i < num_elems; i++) {
84  output[i] = elems[i];
85  }
86 }
87 
88 template <typename T>
89 void decompress_geo_coords_geoint32(std::vector<T>& dec,
90  const int8_t* enc,
91  const size_t sz) {
92  const auto compressed_coords = reinterpret_cast<const int32_t*>(enc);
93  const auto num_coords = sz / sizeof(int32_t);
94  dec.resize(num_coords);
95  for (size_t i = 0; i < num_coords; i += 2) {
96  dec[i] = Geo_namespace::decompress_longitude_coord_geoint32(compressed_coords[i]);
97  dec[i + 1] =
99  }
100 }
101 
102 template <typename T>
103 std::shared_ptr<std::vector<T>> decompress_coords(const SQLTypeInfo& geo_ti,
104  const int8_t* coords,
105  const size_t coords_sz);
106 
107 template <>
108 std::shared_ptr<std::vector<double>> decompress_coords<double>(const SQLTypeInfo& geo_ti,
109  const int8_t* coords,
110  const size_t coords_sz) {
111  auto decompressed_coords_ptr = std::make_shared<std::vector<double>>();
112  if (geo_ti.get_compression() == kENCODING_GEOINT) {
113  if (geo_ti.get_comp_param() == 32) {
114  decompress_geo_coords_geoint32(*decompressed_coords_ptr, coords, coords_sz);
115  }
116  } else {
117  CHECK_EQ(geo_ti.get_compression(), kENCODING_NONE);
118  unpack_geo_vector(*decompressed_coords_ptr, coords, coords_sz);
119  }
120  return decompressed_coords_ptr;
121 }
122 
123 } // namespace
124 
125 // Point
126 template <>
128  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
129  std::array<VarlenDatumPtr, 1>& vals) {
130  // Removing errant NULL check: default ChunkIter accessor may mistake POINT coords
131  // fixlen array for a NULL, plus it is not needed currently - there is no NULL geo
132  // in existing tables, all NULL/empty geo is currently discarded on import.
133  // TODO: add custom ChunkIter accessor able to properly recognize NULL coords
134  // TODO: once NULL geo support is in, resurrect coords NULL check under !notnull
135  // if (!geo_ti.get_notnull() && vals[0]->is_null) {
136  // return GeoTargetValue();
137  // }
138  return GeoPointTargetValue(
139  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length));
140  }
141 };
142 
143 template <>
145  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
146  std::array<VarlenDatumPtr, 1>& vals) {
147  // TODO: Check geo nullness first
148  // if (!geo_ti.get_notnull() && vals[0]->is_null) {
149  // // TODO: What WKT should NULL serialize to? NULL? POINT EMPTY?
150  // return NullableString("NULL");
151  // }
153  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length));
154  return NullableString(point.getWktString());
155  }
156 };
157 
158 template <>
160  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
161  std::array<VarlenDatumPtr, 1>& vals) {
162  // TODO: add custom ChunkIter accessor able to properly recognize NULL coords
163  // TODO: once NULL geo support is in, add coords NULL check under !notnull
164  // if (!geo_ti.get_notnull() && vals[0]->is_null) {
165  // return GeoTargetValuePtr();
166  // }
167  return GeoPointTargetValuePtr({std::move(vals[0])});
168  }
169 };
170 
171 // LineString
172 template <>
174  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
175  std::array<VarlenDatumPtr, 1>& vals) {
176  // Removing errant NULL check: not needed currently - there is no NULL geo
177  // in existing tables, all NULL/empty geo is currently discarded on import.
178  // TODO: once NULL geo support is in, resurrect coords NULL check under !notnull
179  // if (!geo_ti.get_notnull() && vals[0]->is_null) {
180  // return GeoTargetValue();
181  // }
183  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length));
184  }
185 };
186 
187 template <>
189  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
190  std::array<VarlenDatumPtr, 1>& vals) {
191  // TODO: Check geo nullness first
192  // if (!geo_ti.get_notnull() && vals[0]->is_null) {
193  // // TODO: What WKT should NULL serialize to? NULL? LINESTRING EMPTY?
194  // return NullableString("NULL");
195  // }
196  Geo_namespace::GeoLineString linestring(
197  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length));
198  return NullableString(linestring.getWktString());
199  }
200 };
201 
202 template <>
204  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
205  std::array<VarlenDatumPtr, 1>& vals) {
206  // TODO: once NULL geo support is in, add coords NULL check under !notnull
207  // if (!geo_ti.get_notnull() && vals[0]->is_null) {
208  // return GeoTargetValuePtr();
209  // }
210  return GeoLineStringTargetValuePtr({std::move(vals[0])});
211  }
212 };
213 
214 // Polygon
215 template <>
217  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
218  std::array<VarlenDatumPtr, 2>& vals) {
219  // TODO: once NULL geo support is in, add coords NULL check under !notnull
220  // if (!geo_ti.get_notnull() && (vals[0]->is_null || vals[1]->is_null)) {
221  // return GeoTargetValue();
222  // }
223  std::vector<int32_t> ring_sizes_vec;
224  unpack_geo_vector(ring_sizes_vec, vals[1]->pointer, vals[1]->length);
225  return GeoPolyTargetValue(
226  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length),
227  ring_sizes_vec);
228  }
229 };
230 
231 template <>
233  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
234  std::array<VarlenDatumPtr, 2>& vals) {
235  // TODO: Check geo nullness first
236  // if (!geo_ti.get_notnull() && (vals[0]->is_null || vals[1]->is_null)) {
237  // // TODO: What WKT should NULL serialize to? NULL? POLYGON EMPTY?
238  // return NullableString("NULL");
239  // }
240  std::vector<int32_t> ring_sizes_vec;
241  unpack_geo_vector(ring_sizes_vec, vals[1]->pointer, vals[1]->length);
243  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length),
244  ring_sizes_vec);
245  return NullableString(poly.getWktString());
246  };
247 };
248 
249 template <>
251  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
252  std::array<VarlenDatumPtr, 2>& vals) {
253  // TODO: once NULL geo support is in, add coords NULL check under !notnull
254  // if (!geo_ti.get_notnull() && (vals[0]->is_null || vals[1]->is_null)) {
255  // return GeoTargetValuePtr();
256  // }
257  return GeoPolyTargetValuePtr({std::move(vals[0]), std::move(vals[1])});
258  }
259 };
260 
261 // MultiPolygon
262 template <>
264  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
265  std::array<VarlenDatumPtr, 3>& vals) {
266  // TODO: once NULL geo support is in, resurrect coords NULL check under !notnull
267  // if (!geo_ti.get_notnull() &&
268  // (vals[0]->is_null || vals[1]->is_null || vals[2]->is_null)) {
269  // return GeoTargetValue();
270  // }
271  std::vector<int32_t> ring_sizes_vec;
272  unpack_geo_vector(ring_sizes_vec, vals[1]->pointer, vals[1]->length);
273  std::vector<int32_t> poly_rings_vec;
274  unpack_geo_vector(poly_rings_vec, vals[2]->pointer, vals[2]->length);
276  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length),
277  ring_sizes_vec,
278  poly_rings_vec);
279  }
280 };
281 
282 template <>
284  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
285  std::array<VarlenDatumPtr, 3>& vals) {
286  // TODO: Check geo nullness first
287  // if (!geo_ti.get_notnull() &&
288  // (vals[0]->is_null || vals[1]->is_null) || vals[2]->is_null) {
289  // // TODO: What WKT should NULL serialize to? NULL? MULTIPOLYGON EMPTY?
290  // return NullableString("NULL");
291  // }
292  std::vector<int32_t> ring_sizes_vec;
293  unpack_geo_vector(ring_sizes_vec, vals[1]->pointer, vals[1]->length);
294  std::vector<int32_t> poly_rings_vec;
295  unpack_geo_vector(poly_rings_vec, vals[2]->pointer, vals[2]->length);
297  *decompress_coords<double>(geo_ti, vals[0]->pointer, vals[0]->length),
298  ring_sizes_vec,
299  poly_rings_vec);
300  return NullableString(mpoly.getWktString());
301  }
302 };
303 
304 template <>
306  static inline TargetValue serialize(const SQLTypeInfo& geo_ti,
307  std::array<VarlenDatumPtr, 3>& vals) {
308  // TODO: once NULL geo support is in, add coords NULL check under !notnull
309  // if (!geo_ti.get_notnull() &&
310  // (vals[0]->is_null || vals[1]->is_null || vals[2]->is_null)) {
311  // return GeoTargetValuePtr();
312  // }
314  {std::move(vals[0]), std::move(vals[1]), std::move(vals[2])});
315  }
316 };
317 
318 #endif // QUERYENGINE_RESULTSET_GEOSERIALIZATION_H
#define CHECK_EQ(x, y)
Definition: Logger.h:198
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)
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)
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 2 > &vals)
boost::variant< GeoPointTargetValue, GeoLineStringTargetValue, GeoPolyTargetValue, GeoMultiPolyTargetValue > GeoTargetValue
Definition: TargetValue.h:161
Constants for Builtin SQL Types supported by MapD.
Compression / decompression routines for geospatial coordinates.
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 1 > &vals)
CHECK(cgen_state)
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)
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
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)
static TargetValue serialize(const SQLTypeInfo &geo_ti, std::array< VarlenDatumPtr, 1 > &vals)
std::unique_ptr< VarlenDatum > VarlenDatumPtr
#define IS_GEO(T)
Definition: sqltypes.h:167
boost::variant< GeoPointTargetValuePtr, GeoLineStringTargetValuePtr, GeoPolyTargetValuePtr, GeoMultiPolyTargetValuePtr > GeoTargetValuePtr
Definition: TargetValue.h:165