1/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
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 Street, Fifth Floor, Boston, MA 02111-1301 USA */
15
16/* Testing of the basic functions of a MARIA spatial table */
17/* Written by Alex Barkov, who has a shared copyright to this code */
18
19#include <my_global.h>
20#include "maria.h"
21
22#ifdef HAVE_SPATIAL
23#include "ma_sp_defs.h"
24
25#define MAX_REC_LENGTH 1024
26#define KEYALG HA_KEY_ALG_RTREE
27
28static void create_linestring(uchar *record,uint rownr);
29static void print_record(uchar * record,my_off_t offs,const char * tail);
30
31static void create_key(uchar *key,uint rownr);
32static void print_key(const uchar *key,const char * tail);
33
34static int run_test(const char *filename);
35static int read_with_pos(MARIA_HA * file, int silent);
36
37static int maria_rtree_CreateLineStringWKB(double *ords, uint n_dims, uint n_points,
38 uchar *wkb);
39static void maria_rtree_PrintWKB(uchar *wkb, uint n_dims);
40
41static char blob_key[MAX_REC_LENGTH];
42
43
44int main(int argc __attribute__((unused)),char *argv[])
45{
46 MY_INIT(argv[0]);
47 maria_init();
48 exit(run_test("sp_test"));
49}
50
51
52int run_test(const char *filename)
53{
54 MARIA_HA *file;
55 MARIA_UNIQUEDEF uniquedef;
56 MARIA_CREATE_INFO create_info;
57 MARIA_COLUMNDEF recinfo[20];
58 MARIA_KEYDEF keyinfo[20];
59 HA_KEYSEG keyseg[20];
60 key_range min_range, max_range;
61 int silent=0;
62 int create_flag=0;
63 int null_fields=0;
64 int nrecords=30;
65 int uniques=0;
66 int i;
67 int error;
68 int row_count=0;
69 uchar record[MAX_REC_LENGTH];
70 uchar key[MAX_REC_LENGTH];
71 uchar read_record[MAX_REC_LENGTH];
72 int upd=10;
73 ha_rows hrows;
74
75 /* Define a column for NULLs and DEL markers*/
76
77 recinfo[0].type=FIELD_NORMAL;
78 recinfo[0].length=1; /* For NULL bits */
79
80
81 /* Define spatial column */
82
83 recinfo[1].type=FIELD_BLOB;
84 recinfo[1].length=4 + portable_sizeof_char_ptr;
85
86
87
88 /* Define a key with 1 spatial segment */
89
90 keyinfo[0].seg=keyseg;
91 keyinfo[0].keysegs=1;
92 keyinfo[0].flag=HA_SPATIAL;
93 keyinfo[0].key_alg=KEYALG;
94
95 keyinfo[0].seg[0].type= HA_KEYTYPE_BINARY;
96 keyinfo[0].seg[0].flag=0;
97 keyinfo[0].seg[0].start= 1;
98 keyinfo[0].seg[0].length=1; /* Spatial ignores it anyway */
99 keyinfo[0].seg[0].null_bit= null_fields ? 2 : 0;
100 keyinfo[0].seg[0].null_pos=0;
101 keyinfo[0].seg[0].language=default_charset_info->number;
102 keyinfo[0].seg[0].bit_start=4; /* Long BLOB */
103
104
105 if (!silent)
106 printf("- Creating isam-file\n");
107
108 bzero((char*) &create_info,sizeof(create_info));
109 create_info.max_rows=10000000;
110
111 if (maria_create(filename,
112 DYNAMIC_RECORD,
113 1, /* keys */
114 keyinfo,
115 2, /* columns */
116 recinfo,uniques,&uniquedef,&create_info,create_flag))
117 goto err;
118
119 if (!silent)
120 printf("- Open isam-file\n");
121
122 if (!(file=maria_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
123 goto err;
124
125 if (!silent)
126 printf("- Writing key:s\n");
127
128 for (i=0; i<nrecords; i++ )
129 {
130 create_linestring(record,i);
131 error=maria_write(file,record);
132 print_record(record,maria_position(file),"\n");
133 if (!error)
134 {
135 row_count++;
136 }
137 else
138 {
139 printf("maria_write: %d\n", error);
140 goto err;
141 }
142 }
143
144 if ((error=read_with_pos(file,silent)))
145 goto err;
146
147 if (!silent)
148 printf("- Deleting rows with position\n");
149 for (i=0; i < nrecords/4; i++)
150 {
151 my_errno=0;
152 bzero((char*) read_record,MAX_REC_LENGTH);
153 error=maria_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
154 if (error)
155 {
156 printf("pos: %2d maria_rrnd: %3d errno: %3d\n",i,error,my_errno);
157 goto err;
158 }
159 print_record(read_record,maria_position(file),"\n");
160 error=maria_delete(file,read_record);
161 if (error)
162 {
163 printf("pos: %2d maria_delete: %3d errno: %3d\n",i,error,my_errno);
164 goto err;
165 }
166 }
167
168 if (!silent)
169 printf("- Updating rows with position\n");
170 for (i=0; i < nrecords/2 ; i++)
171 {
172 my_errno=0;
173 bzero((char*) read_record,MAX_REC_LENGTH);
174 error=maria_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
175 if (error)
176 {
177 if (error==HA_ERR_RECORD_DELETED)
178 continue;
179 printf("pos: %2d maria_rrnd: %3d errno: %3d\n",i,error,my_errno);
180 goto err;
181 }
182 print_record(read_record,maria_position(file),"");
183 create_linestring(record,i+nrecords*upd);
184 printf("\t-> ");
185 print_record(record,maria_position(file),"\n");
186 error=maria_update(file,read_record,record);
187 if (error)
188 {
189 printf("pos: %2d maria_update: %3d errno: %3d\n",i,error,my_errno);
190 goto err;
191 }
192 }
193
194 if ((error=read_with_pos(file,silent)))
195 goto err;
196
197 if (!silent)
198 printf("- Test maria_rkey then a sequence of maria_rnext_same\n");
199
200 create_key(key, nrecords*4/5);
201 print_key(key," search for INTERSECT\n");
202
203 if ((error=maria_rkey(file,read_record,0,key,0,HA_READ_MBR_INTERSECT)))
204 {
205 printf("maria_rkey: %3d errno: %3d\n",error,my_errno);
206 goto err;
207 }
208 print_record(read_record,maria_position(file)," maria_rkey\n");
209 row_count=1;
210
211 for (;;)
212 {
213 if ((error=maria_rnext_same(file,read_record)))
214 {
215 if (error==HA_ERR_END_OF_FILE)
216 break;
217 printf("maria_next: %3d errno: %3d\n",error,my_errno);
218 goto err;
219 }
220 print_record(read_record,maria_position(file)," maria_rnext_same\n");
221 row_count++;
222 }
223 printf(" %d rows\n",row_count);
224
225 if (!silent)
226 printf("- Test maria_rfirst then a sequence of maria_rnext\n");
227
228 error=maria_rfirst(file,read_record,0);
229 if (error)
230 {
231 printf("maria_rfirst: %3d errno: %3d\n",error,my_errno);
232 goto err;
233 }
234 row_count=1;
235 print_record(read_record,maria_position(file)," maria_frirst\n");
236
237 for(i=0;i<nrecords;i++) {
238 if ((error=maria_rnext(file,read_record,0)))
239 {
240 if (error==HA_ERR_END_OF_FILE)
241 break;
242 printf("maria_next: %3d errno: %3d\n",error,my_errno);
243 goto err;
244 }
245 print_record(read_record,maria_position(file)," maria_rnext\n");
246 row_count++;
247 }
248 printf(" %d rows\n",row_count);
249
250 if (!silent)
251 printf("- Test maria_records_in_range()\n");
252
253 create_key(key, nrecords*upd);
254 print_key(key," INTERSECT\n");
255 min_range.key= key;
256 min_range.length= 1000; /* Big enough */
257 min_range.flag= HA_READ_MBR_INTERSECT;
258 max_range.key= record+1;
259 max_range.length= 1000; /* Big enough */
260 max_range.flag= HA_READ_KEY_EXACT;
261 hrows= maria_records_in_range(file,0, &min_range, &max_range);
262 printf(" %ld rows\n", (long) hrows);
263
264 if (maria_close(file)) goto err;
265 maria_end();
266 my_end(MY_CHECK_ERROR);
267
268 return 0;
269
270err:
271 printf("got error: %3d when using maria-database\n",my_errno);
272 maria_end();
273 return 1; /* skip warning */
274}
275
276
277static int read_with_pos (MARIA_HA * file,int silent)
278{
279 int error;
280 int i;
281 uchar read_record[MAX_REC_LENGTH];
282 int rows=0;
283
284 if (!silent)
285 printf("- Reading rows with position\n");
286 for (i=0;;i++)
287 {
288 my_errno=0;
289 bzero((char*) read_record,MAX_REC_LENGTH);
290 error=maria_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
291 if (error)
292 {
293 if (error==HA_ERR_END_OF_FILE)
294 break;
295 if (error==HA_ERR_RECORD_DELETED)
296 continue;
297 printf("pos: %2d maria_rrnd: %3d errno: %3d\n",i,error,my_errno);
298 return error;
299 }
300 rows++;
301 print_record(read_record,maria_position(file),"\n");
302 }
303 printf(" %d rows\n",rows);
304 return 0;
305}
306
307
308#ifdef NOT_USED
309static void bprint_record(uchar * record,
310 my_off_t offs __attribute__((unused)),
311 const char * tail)
312{
313 int i;
314 char * pos;
315 i=(unsigned char)record[0];
316 printf("%02X ",i);
317
318 for( pos=record+1, i=0; i<32; i++,pos++)
319 {
320 int b=(unsigned char)*pos;
321 printf("%02X",b);
322 }
323 printf("%s",tail);
324}
325#endif
326
327
328static void print_record(uchar * record, my_off_t offs,const char * tail)
329{
330 uchar *pos;
331 char *ptr;
332 uint len;
333
334 printf(" rec=(%d)",(unsigned char)record[0]);
335 pos=record+1;
336 len=sint4korr(pos);
337 pos+=4;
338 printf(" len=%d ",len);
339 memcpy(&ptr,pos,sizeof(char*));
340 if (ptr)
341 maria_rtree_PrintWKB((uchar*) ptr,SPDIMS);
342 else
343 printf("<NULL> ");
344 printf(" offs=%ld ",(long int)offs);
345 printf("%s",tail);
346}
347
348
349#ifdef NOT_USED
350static void create_point(uchar *record,uint rownr)
351{
352 uint tmp;
353 char *ptr;
354 char *pos=record;
355 double x[200];
356 int i;
357
358 for(i=0;i<SPDIMS;i++)
359 x[i]=rownr;
360
361 bzero((char*) record,MAX_REC_LENGTH);
362 *pos=0x01; /* DEL marker */
363 pos++;
364
365 memset(blob_key,0,sizeof(blob_key));
366 tmp=maria_rtree_CreatePointWKB(x,SPDIMS,blob_key);
367
368 int4store(pos,tmp);
369 pos+=4;
370
371 ptr=blob_key;
372 memcpy(pos,&ptr,sizeof(char*));
373}
374#endif
375
376
377static void create_linestring(uchar *record,uint rownr)
378{
379 uint tmp;
380 char *ptr;
381 uchar *pos= record;
382 double x[200];
383 int i,j;
384 int npoints=2;
385
386 for(j=0;j<npoints;j++)
387 for(i=0;i<SPDIMS;i++)
388 x[i+j*SPDIMS]=rownr*j;
389
390 bzero((char*) record,MAX_REC_LENGTH);
391 *pos=0x01; /* DEL marker */
392 pos++;
393
394 memset(blob_key,0,sizeof(blob_key));
395 tmp=maria_rtree_CreateLineStringWKB(x,SPDIMS,npoints, (uchar*) blob_key);
396
397 int4store(pos,tmp);
398 pos+=4;
399
400 ptr=blob_key;
401 memcpy(pos,&ptr,sizeof(char*));
402}
403
404
405static void create_key(uchar *key,uint rownr)
406{
407 double c=rownr;
408 uchar *pos;
409 uint i;
410
411 bzero(key,MAX_REC_LENGTH);
412 for ( pos=key, i=0; i<2*SPDIMS; i++)
413 {
414 float8store(pos,c);
415 pos+=sizeof(c);
416 }
417}
418
419static void print_key(const uchar *key,const char * tail)
420{
421 double c;
422 uint i;
423
424 printf(" key=");
425 for (i=0; i<2*SPDIMS; i++)
426 {
427 float8get(c,key);
428 key+=sizeof(c);
429 printf("%.14g ",c);
430 }
431 printf("%s",tail);
432}
433
434
435#ifdef NOT_USED
436
437static int maria_rtree_CreatePointWKB(double *ords, uint n_dims, uchar *wkb)
438{
439 uint i;
440
441 *wkb = wkbXDR;
442 ++wkb;
443 int4store(wkb, wkbPoint);
444 wkb += 4;
445
446 for (i=0; i < n_dims; ++i)
447 {
448 float8store(wkb, ords[i]);
449 wkb += 8;
450 }
451 return 5 + n_dims * 8;
452}
453#endif
454
455
456static int maria_rtree_CreateLineStringWKB(double *ords, uint n_dims, uint n_points,
457 uchar *wkb)
458{
459 uint i;
460 uint n_ords = n_dims * n_points;
461
462 *wkb = wkbXDR;
463 ++wkb;
464 int4store(wkb, wkbLineString);
465 wkb += 4;
466 int4store(wkb, n_points);
467 wkb += 4;
468 for (i=0; i < n_ords; ++i)
469 {
470 float8store(wkb, ords[i]);
471 wkb += 8;
472 }
473 return 9 + n_points * n_dims * 8;
474}
475
476
477static void maria_rtree_PrintWKB(uchar *wkb, uint n_dims)
478{
479 uint wkb_type;
480
481 ++wkb;
482 wkb_type = uint4korr(wkb);
483 wkb += 4;
484
485 switch ((enum wkbType)wkb_type)
486 {
487 case wkbPoint:
488 {
489 uint i;
490 double ord;
491
492 printf("POINT(");
493 for (i=0; i < n_dims; ++i)
494 {
495 float8get(ord, wkb);
496 wkb += 8;
497 printf("%.14g", ord);
498 if (i < n_dims - 1)
499 printf(" ");
500 else
501 printf(")");
502 }
503 break;
504 }
505 case wkbLineString:
506 {
507 uint p, i;
508 uint n_points;
509 double ord;
510
511 printf("LineString(");
512 n_points = uint4korr(wkb);
513 wkb += 4;
514 for (p=0; p < n_points; ++p)
515 {
516 for (i=0; i < n_dims; ++i)
517 {
518 float8get(ord, wkb);
519 wkb += 8;
520 printf("%.14g", ord);
521 if (i < n_dims - 1)
522 printf(" ");
523 }
524 if (p < n_points - 1)
525 printf(", ");
526 else
527 printf(")");
528 }
529 break;
530 }
531 case wkbPolygon:
532 {
533 printf("POLYGON(...)");
534 break;
535 }
536 case wkbMultiPoint:
537 {
538 printf("MULTIPOINT(...)");
539 break;
540 }
541 case wkbMultiLineString:
542 {
543 printf("MULTILINESTRING(...)");
544 break;
545 }
546 case wkbMultiPolygon:
547 {
548 printf("MULTIPOLYGON(...)");
549 break;
550 }
551 case wkbGeometryCollection:
552 {
553 printf("GEOMETRYCOLLECTION(...)");
554 break;
555 }
556 default:
557 {
558 printf("UNKNOWN GEOMETRY TYPE");
559 break;
560 }
561 }
562}
563
564#include "ma_check_standalone.h"
565
566#else
567int main(int argc __attribute__((unused)),char *argv[] __attribute__((unused)))
568{
569 exit(0);
570}
571#endif /*HAVE_SPATIAL*/
572