~drizzle-trunk/drizzle/development

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