MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sp_key.c
1 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #include "myisamdef.h"
17 
18 #ifdef HAVE_SPATIAL
19 
20 #include "sp_defs.h"
21 
22 static int sp_add_point_to_mbr(uchar *(*wkb), uchar *end, uint n_dims,
23  uchar byte_order, double *mbr);
24 static int sp_get_point_mbr(uchar *(*wkb), uchar *end, uint n_dims,
25  uchar byte_order, double *mbr);
26 static int sp_get_linestring_mbr(uchar *(*wkb), uchar *end, uint n_dims,
27  uchar byte_order, double *mbr);
28 static int sp_get_polygon_mbr(uchar *(*wkb), uchar *end, uint n_dims,
29  uchar byte_order, double *mbr);
30 static int sp_get_geometry_mbr(uchar *(*wkb), uchar *end, uint n_dims,
31  double *mbr, int top);
32 static int sp_mbr_from_wkb(uchar (*wkb), uint size, uint n_dims, double *mbr);
33 
34 uint sp_make_key(register MI_INFO *info, uint keynr, uchar *key,
35  const uchar *record, my_off_t filepos)
36 {
37  HA_KEYSEG *keyseg;
38  MI_KEYDEF *keyinfo = &info->s->keyinfo[keynr];
39  uint len = 0;
40  uchar *pos;
41  uint dlen;
42  uchar *dptr;
43  double mbr[SPDIMS * 2];
44  uint i;
45 
46  keyseg = &keyinfo->seg[-1];
47  pos = (uchar*)record + keyseg->start;
48 
49  dlen = _mi_calc_blob_length(keyseg->bit_start, pos);
50  memcpy(&dptr, pos + keyseg->bit_start, sizeof(char*));
51  if (!dptr)
52  {
53  my_errno= HA_ERR_NULL_IN_SPATIAL;
54  return 0;
55  }
56  sp_mbr_from_wkb(dptr + 4, dlen - 4, SPDIMS, mbr); /* SRID */
57 
58  for (i = 0, keyseg = keyinfo->seg; keyseg->type; keyseg++, i++)
59  {
60  uint length = keyseg->length, start= keyseg->start;
61  double val;
62 
63  DBUG_ASSERT(length == sizeof(double));
64  DBUG_ASSERT(!(start % sizeof(double)));
65  DBUG_ASSERT(start < sizeof(mbr));
66  DBUG_ASSERT(keyseg->type == HA_KEYTYPE_DOUBLE);
67 
68  val= mbr[start / sizeof (double)];
69 #ifdef HAVE_ISNAN
70  if (isnan(val))
71  {
72  memset(key, 0, length);
73  key+= length;
74  len+= length;
75  continue;
76  }
77 #endif
78 
79  if (keyseg->flag & HA_SWAP_KEY)
80  {
81  uchar buf[sizeof(double)];
82 
83  float8store(buf, val);
84  pos= &buf[length];
85  while (pos > buf)
86  *key++ = *--pos;
87  }
88  else
89  {
90  float8store((uchar *)key, val);
91  key += length;
92  }
93  len+= length;
94  }
95  _mi_dpointer(info, key, filepos);
96  return len;
97 }
98 
99 /*
100 Calculate minimal bounding rectangle (mbr) of the spatial object
101 stored in "well-known binary representation" (wkb) format.
102 */
103 static int sp_mbr_from_wkb(uchar *wkb, uint size, uint n_dims, double *mbr)
104 {
105  uint i;
106 
107  for (i=0; i < n_dims; ++i)
108  {
109  mbr[i * 2] = DBL_MAX;
110  mbr[i * 2 + 1] = -DBL_MAX;
111  }
112 
113  return sp_get_geometry_mbr(&wkb, wkb + size, n_dims, mbr, 1);
114 }
115 
116 /*
117  Add one point stored in wkb to mbr
118 */
119 
120 static int sp_add_point_to_mbr(uchar *(*wkb), uchar *end, uint n_dims,
121  uchar byte_order __attribute__((unused)),
122  double *mbr)
123 {
124  double ord;
125  double *mbr_end= mbr + n_dims * 2;
126 
127  while (mbr < mbr_end)
128  {
129  if ((*wkb) > end - 8)
130  return -1;
131  float8get(ord, (const uchar*) *wkb);
132  (*wkb)+= 8;
133  if (ord < *mbr)
134  *mbr= ord;
135  mbr++;
136  if (ord > *mbr)
137  *mbr= ord;
138  mbr++;
139  }
140  return 0;
141 }
142 
143 
144 static int sp_get_point_mbr(uchar *(*wkb), uchar *end, uint n_dims,
145  uchar byte_order, double *mbr)
146 {
147  return sp_add_point_to_mbr(wkb, end, n_dims, byte_order, mbr);
148 }
149 
150 
151 static int sp_get_linestring_mbr(uchar *(*wkb), uchar *end, uint n_dims,
152  uchar byte_order, double *mbr)
153 {
154  uint n_points;
155 
156  n_points = uint4korr(*wkb);
157  (*wkb) += 4;
158  for (; n_points > 0; --n_points)
159  {
160  /* Add next point to mbr */
161  if (sp_add_point_to_mbr(wkb, end, n_dims, byte_order, mbr))
162  return -1;
163  }
164  return 0;
165 }
166 
167 
168 static int sp_get_polygon_mbr(uchar *(*wkb), uchar *end, uint n_dims,
169  uchar byte_order, double *mbr)
170 {
171  uint n_linear_rings;
172  uint n_points;
173 
174  n_linear_rings = uint4korr((*wkb));
175  (*wkb) += 4;
176 
177  for (; n_linear_rings > 0; --n_linear_rings)
178  {
179  n_points = uint4korr((*wkb));
180  (*wkb) += 4;
181  for (; n_points > 0; --n_points)
182  {
183  /* Add next point to mbr */
184  if (sp_add_point_to_mbr(wkb, end, n_dims, byte_order, mbr))
185  return -1;
186  }
187  }
188  return 0;
189 }
190 
191 static int sp_get_geometry_mbr(uchar *(*wkb), uchar *end, uint n_dims,
192  double *mbr, int top)
193 {
194  int res;
195  uchar byte_order;
196  uint wkb_type;
197 
198  byte_order = *(*wkb);
199  ++(*wkb);
200 
201  wkb_type = uint4korr((*wkb));
202  (*wkb) += 4;
203 
204  switch ((enum wkbType) wkb_type)
205  {
206  case wkbPoint:
207  res = sp_get_point_mbr(wkb, end, n_dims, byte_order, mbr);
208  break;
209  case wkbLineString:
210  res = sp_get_linestring_mbr(wkb, end, n_dims, byte_order, mbr);
211  break;
212  case wkbPolygon:
213  res = sp_get_polygon_mbr(wkb, end, n_dims, byte_order, mbr);
214  break;
215  case wkbMultiPoint:
216  {
217  uint n_items;
218  n_items = uint4korr((*wkb));
219  (*wkb) += 4;
220  for (; n_items > 0; --n_items)
221  {
222  byte_order = *(*wkb);
223  ++(*wkb);
224  (*wkb) += 4;
225  if (sp_get_point_mbr(wkb, end, n_dims, byte_order, mbr))
226  return -1;
227  }
228  res = 0;
229  break;
230  }
231  case wkbMultiLineString:
232  {
233  uint n_items;
234  n_items = uint4korr((*wkb));
235  (*wkb) += 4;
236  for (; n_items > 0; --n_items)
237  {
238  byte_order = *(*wkb);
239  ++(*wkb);
240  (*wkb) += 4;
241  if (sp_get_linestring_mbr(wkb, end, n_dims, byte_order, mbr))
242  return -1;
243  }
244  res = 0;
245  break;
246  }
247  case wkbMultiPolygon:
248  {
249  uint n_items;
250  n_items = uint4korr((*wkb));
251  (*wkb) += 4;
252  for (; n_items > 0; --n_items)
253  {
254  byte_order = *(*wkb);
255  ++(*wkb);
256  (*wkb) += 4;
257  if (sp_get_polygon_mbr(wkb, end, n_dims, byte_order, mbr))
258  return -1;
259  }
260  res = 0;
261  break;
262  }
263  case wkbGeometryCollection:
264  {
265  uint n_items;
266 
267  if (!top)
268  return -1;
269 
270  n_items = uint4korr((*wkb));
271  (*wkb) += 4;
272  for (; n_items > 0; --n_items)
273  {
274  if (sp_get_geometry_mbr(wkb, end, n_dims, mbr, 0))
275  return -1;
276  }
277  res = 0;
278  break;
279  }
280  default:
281  res = -1;
282  }
283  return res;
284 }
285 
286 #endif /*HAVE_SPATIAL*/