summaryrefslogtreecommitdiff
path: root/sql/sql_type_geom.h
blob: db951297519ed8290e074b86613003f365de2b5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
#ifndef SQL_TYPE_GEOM_H_INCLUDED
#define SQL_TYPE_GEOM_H_INCLUDED
/*
   Copyright (c) 2015 MariaDB Foundation
   Copyright (c) 2019, 2022, MariaDB Corporation.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */

#ifdef USE_PRAGMA_IMPLEMENTATION
#pragma implementation				// gcc: Class implementation
#endif

#include "mariadb.h"
#include "sql_type.h"

#ifdef HAVE_SPATIAL
class Type_handler_geometry: public Type_handler_string_result
{
public:
  enum geometry_types
  {
    GEOM_GEOMETRY = 0, GEOM_POINT = 1, GEOM_LINESTRING = 2, GEOM_POLYGON = 3,
    GEOM_MULTIPOINT = 4, GEOM_MULTILINESTRING = 5, GEOM_MULTIPOLYGON = 6,
    GEOM_GEOMETRYCOLLECTION = 7
  };
  static bool check_type_geom_or_binary(const LEX_CSTRING &opname,
                                        const Item *item);
  static bool check_types_geom_or_binary(const LEX_CSTRING &opname,
                                         Item * const *args,
                                         uint start, uint end);
  static const Type_handler_geometry *type_handler_geom_by_type(uint type);
  LEX_CSTRING extended_metadata_data_type_name() const;
public:
  virtual ~Type_handler_geometry() {}
  enum_field_types field_type() const override { return MYSQL_TYPE_GEOMETRY; }
  bool Item_append_extended_type_info(Send_field_extended_metadata *to,
                                      const Item *item) const override
  {
    LEX_CSTRING tmp= extended_metadata_data_type_name();
    return tmp.length ? to->set_data_type_name(tmp) : false;
  }
  bool is_param_long_data_type() const override { return true; }
  uint32 max_display_length_for_field(const Conv_source &src) const override;
  uint32 calc_pack_length(uint32 length) const override;
  const Type_collection *type_collection() const override;
  const Type_handler *type_handler_for_comparison() const override;
  virtual geometry_types geometry_type() const { return GEOM_GEOMETRY; }
  virtual Item *create_typecast_item(THD *thd, Item *item,
                                     const Type_cast_attributes &attr)
                                     const override;
  const Type_handler *type_handler_frm_unpack(const uchar *buffer)
                                              const override;
  bool is_binary_compatible_geom_super_type_for(const Type_handler_geometry *th)
                                                const
  {
    return geometry_type() == GEOM_GEOMETRY ||
           geometry_type() == th->geometry_type();
  }
  bool type_can_have_key_part() const override { return true; }
  bool subquery_type_allows_materialization(const Item *, const Item *, bool)
    const override
  {
    return false; // Materialization does not work with GEOMETRY columns
  }
  void Item_param_set_param_func(Item_param *param,
                                 uchar **pos, ulong len) const override;
  bool Item_param_set_from_value(THD *thd,
                                 Item_param *param,
                                 const Type_all_attributes *attr,
                                 const st_value *value) const override;
  Field *make_conversion_table_field(MEM_ROOT *root,
                                     TABLE *table, uint metadata,
                                     const Field *target) const override;
  uint Column_definition_gis_options_image(uchar *buff,
                                           const Column_definition &def)
                                           const override;
  bool Column_definition_data_type_info_image(Binary_string *to,
                                              const Column_definition &def)
                                              const override
  {
    return false;
  }
  void
  Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
                                        uchar *buff) const override;
  bool
  Column_definition_attributes_frm_unpack(Column_definition_attributes *attr,
                                          TABLE_SHARE *share,
                                          const uchar *buffer,
                                          LEX_CUSTRING *gis_options) const
    override;
  bool Column_definition_fix_attributes(Column_definition *c) const override;
  void Column_definition_reuse_fix_attributes(THD *thd,
                                              Column_definition *c,
                                              const Field *field) const
    override;
  bool Column_definition_prepare_stage1(THD *thd,
                                        MEM_ROOT *mem_root,
                                        Column_definition *c,
                                        column_definition_type_t type,
                                        const Column_derived_attributes
                                              *derived_attr)
                                        const override;
  bool Column_definition_prepare_stage2(Column_definition *c,
                                        handler *file,
                                        ulonglong table_flags) const override;
  bool Key_part_spec_init_primary(Key_part_spec *part,
                                  const Column_definition &def,
                                  const handler *file) const override;
  bool Key_part_spec_init_unique(Key_part_spec *part,
                                 const Column_definition &def,
                                 const handler *file,
                                 bool *has_key_needed) const override;
  bool Key_part_spec_init_multiple(Key_part_spec *part,
                                   const Column_definition &def,
                                   const handler *file) const override;
  bool Key_part_spec_init_foreign(Key_part_spec *part,
                                  const Column_definition &def,
                                  const handler *file) const override;
  bool Key_part_spec_init_spatial(Key_part_spec *part,
                                  const Column_definition &def) const override;
  Field *make_table_field(MEM_ROOT *root,
                          const LEX_CSTRING *name,
                          const Record_addr &addr,
                          const Type_all_attributes &attr,
                          TABLE_SHARE *share) const override;

  Field *make_table_field_from_def(TABLE_SHARE *share,
                                   MEM_ROOT *mem_root,
                                   const LEX_CSTRING *name,
                                   const Record_addr &addr,
                                   const Bit_addr &bit,
                                   const Column_definition_attributes *attr,
                                   uint32 flags) const override;

  bool can_return_int() const override { return false; }
  bool can_return_decimal() const override { return false; }
  bool can_return_real() const override { return false; }
  bool can_return_text() const override { return false; }
  bool can_return_date() const override { return false; }
  bool can_return_time() const override { return false; }
  bool Item_func_round_fix_length_and_dec(Item_func_round *) const override;
  bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const override;
  bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override;
  bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const override;
  bool Item_hybrid_func_fix_attributes(THD *thd,
                                       const LEX_CSTRING &name,
                                       Type_handler_hybrid_field_type *h,
                                       Type_all_attributes *attr,
                                       Item **items, uint nitems) const
    override;
  bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const override;
  bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const override;
  bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const override;

  bool Item_func_signed_fix_length_and_dec(Item_func_signed *) const override;
  bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *) const
    override;
  bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *) const
    override;
  bool Item_float_typecast_fix_length_and_dec(Item_float_typecast *) const
    override;
  bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const
    override;
  bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const
    override;
  bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *) const
    override;
  bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *) const
    override;
  bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *) const
    override;
};


class Type_handler_point: public Type_handler_geometry
{
  // Binary length of a POINT value: 4 byte SRID + 21 byte WKB POINT
  static uint octet_length() { return 25; }
public:
  geometry_types geometry_type() const override { return GEOM_POINT; }
  Item *make_constructor_item(THD *thd, List<Item> *args) const override;
  bool Key_part_spec_init_primary(Key_part_spec *part,
                                  const Column_definition &def,
                                  const handler *file) const override;
  bool Key_part_spec_init_unique(Key_part_spec *part,
                                 const Column_definition &def,
                                 const handler *file,
                                 bool *has_key_needed) const override;
  bool Key_part_spec_init_multiple(Key_part_spec *part,
                                   const Column_definition &def,
                                   const handler *file) const override;
  bool Key_part_spec_init_foreign(Key_part_spec *part,
                                  const Column_definition &def,
                                  const handler *file) const override;
};


class Type_handler_linestring: public Type_handler_geometry
{
public:
  geometry_types geometry_type() const override { return GEOM_LINESTRING; }
  Item *make_constructor_item(THD *thd, List<Item> *args) const override;
};


class Type_handler_polygon: public Type_handler_geometry
{
public:
  geometry_types geometry_type() const override { return GEOM_POLYGON; }
  Item *make_constructor_item(THD *thd, List<Item> *args) const override;
};


class Type_handler_multipoint: public Type_handler_geometry
{
public:
  geometry_types geometry_type() const override { return GEOM_MULTIPOINT; }
  Item *make_constructor_item(THD *thd, List<Item> *args) const override;
};


class Type_handler_multilinestring: public Type_handler_geometry
{
public:
  geometry_types geometry_type() const override { return GEOM_MULTILINESTRING; }
  Item *make_constructor_item(THD *thd, List<Item> *args) const override;
};


class Type_handler_multipolygon: public Type_handler_geometry
{
public:
  geometry_types geometry_type() const override { return GEOM_MULTIPOLYGON; }
  Item *make_constructor_item(THD *thd, List<Item> *args) const override;
};


class Type_handler_geometrycollection: public Type_handler_geometry
{
public:
  geometry_types geometry_type() const override { return GEOM_GEOMETRYCOLLECTION; }
  Item *make_constructor_item(THD *thd, List<Item> *args) const override;
};

extern Named_type_handler<Type_handler_geometry> type_handler_geometry;
extern Named_type_handler<Type_handler_point> type_handler_point;
extern Named_type_handler<Type_handler_linestring> type_handler_linestring;
extern Named_type_handler<Type_handler_polygon> type_handler_polygon;
extern Named_type_handler<Type_handler_multipoint> type_handler_multipoint;
extern Named_type_handler<Type_handler_multilinestring> type_handler_multilinestring;
extern Named_type_handler<Type_handler_multipolygon> type_handler_multipolygon;
extern Named_type_handler<Type_handler_geometrycollection> type_handler_geometrycollection;

class Type_collection_geometry: public Type_collection
{
  const Type_handler *aggregate_common(const Type_handler *a,
                                       const Type_handler *b) const
  {
    if (a == b)
      return a;
    if (dynamic_cast<const Type_handler_geometry*>(a) &&
        dynamic_cast<const Type_handler_geometry*>(b))
      return &type_handler_geometry;
    return NULL;
  }
  const Type_handler *aggregate_if_null(const Type_handler *a,
                                        const Type_handler *b) const
  {
    return a == &type_handler_null ? b :
           b == &type_handler_null ? a :
           NULL;
  }
  const Type_handler *aggregate_if_long_blob(const Type_handler *a,
                                             const Type_handler *b) const
  {
    return a == &type_handler_long_blob ? &type_handler_long_blob :
           b == &type_handler_long_blob ? &type_handler_long_blob :
           NULL;
  }
  const Type_handler *aggregate_if_string(const Type_handler *a,
                                          const Type_handler *b) const;
#ifndef DBUG_OFF
  bool init_aggregators(Type_handler_data *data, const Type_handler *geom) const;
#endif
public:
  bool init(Type_handler_data *data) override;
  const Type_handler *handler_by_name(const LEX_CSTRING &name) const override;
  const Type_handler *aggregate_for_result(const Type_handler *a,
                                           const Type_handler *b)
                                           const override;
  const Type_handler *aggregate_for_comparison(const Type_handler *a,
                                               const Type_handler *b)
                                               const override;
  const Type_handler *aggregate_for_min_max(const Type_handler *a,
                                            const Type_handler *b)
                                            const override;
  const Type_handler *aggregate_for_num_op(const Type_handler *a,
                                           const Type_handler *b)
                                           const override
  {
    return NULL;
  }
};

extern Type_collection_geometry type_collection_geometry;

#include "field.h"

class Field_geom :public Field_blob
{
  const Type_handler_geometry *m_type_handler;
public:
  uint srid;
  uint precision;
  enum storage_type { GEOM_STORAGE_WKB= 0, GEOM_STORAGE_BINARY= 1};
  enum storage_type storage;

  Field_geom(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
	     enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
	     TABLE_SHARE *share, uint blob_pack_length,
	     const Type_handler_geometry *gth,
	     uint field_srid)
     :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
                 field_name_arg, share, blob_pack_length, &my_charset_bin),
      m_type_handler(gth)
  { srid= field_srid; }
  enum_conv_type rpl_conv_type_from(const Conv_source &source,
                                    const Relay_log_info *rli,
                                    const Conv_param &param) const override;
  enum ha_base_keytype key_type() const  override
  {
    return HA_KEYTYPE_VARBINARY2;
  }
  const Type_handler *type_handler() const override
  {
    return m_type_handler;
  }
  const Type_handler_geometry *type_handler_geom() const
  {
    return m_type_handler;
  }
  void set_type_handler(const Type_handler_geometry *th)
  {
    m_type_handler= th;
  }
  enum_field_types type() const override
  {
    return MYSQL_TYPE_GEOMETRY;
  }
  enum_field_types real_type() const override
  {
    return MYSQL_TYPE_GEOMETRY;
  }
  Information_schema_character_attributes
    information_schema_character_attributes() const override
  {
    return Information_schema_character_attributes();
  }
  void make_send_field(Send_field *to) override
  {
    Field_longstr::make_send_field(to);
    LEX_CSTRING tmp= m_type_handler->extended_metadata_data_type_name();
    if (tmp.length)
      to->set_data_type_name(tmp);
  }
  bool can_optimize_range(const Item_bool_func *cond,
                                  const Item *item,
                                  bool is_eq_func) const override;
  void sql_type(String &str) const override;
  Copy_func *get_copy_func(const Field *from) const override
  {
    const Type_handler_geometry *fth=
      dynamic_cast<const Type_handler_geometry*>(from->type_handler());
    if (fth && m_type_handler->is_binary_compatible_geom_super_type_for(fth))
      return get_identical_copy_func();
    return do_conv_blob;
  }
  bool memcpy_field_possible(const Field *from) const override
  {
    const Type_handler_geometry *fth=
      dynamic_cast<const Type_handler_geometry*>(from->type_handler());
    return fth &&
           m_type_handler->is_binary_compatible_geom_super_type_for(fth) &&
           !table->copy_blobs;
  }
  bool is_equal(const Column_definition &new_field) const override;
  int  store(const char *to, size_t length, CHARSET_INFO *charset) override;
  int  store(double nr) override;
  int  store(longlong nr, bool unsigned_val) override;
  int  store_decimal(const my_decimal *) override;
  uint size_of() const  override{ return sizeof(*this); }
  /**
   Key length is provided only to support hash joins. (compared byte for byte)
   Ex: SELECT .. FROM t1,t2 WHERE t1.field_geom1=t2.field_geom2.

   The comparison is not very relevant, as identical geometry might be
   represented differently, but we need to support it either way.
  */
  uint32 key_length() const  override{ return packlength; }
  uint get_key_image(uchar *buff,uint length,
                     const uchar *ptr_arg, imagetype type_arg) const override;

  /**
    Non-nullable GEOMETRY types cannot have defaults,
    but the underlying blob must still be reset.
   */
  int reset(void)  override{ return Field_blob::reset() || !maybe_null(); }
  bool load_data_set_null(THD *thd) override;
  bool load_data_set_no_data(THD *thd, bool fixed_format) override;

  uint get_srid() const { return srid; }
  void print_key_value(String *out, uint32 length) override
  {
    out->append(STRING_WITH_LEN("unprintable_geometry_value"));
  }
  Binlog_type_info binlog_type_info() const override;
};

#endif // HAVE_SPATIAL

#endif // SQL_TYPE_GEOM_H_INCLUDED