1 /* Copyright (c) 2002, 2021, Oracle and/or its affiliates.
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, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 /* Testing of the basic functions of a MyISAM rtree table         */
24 /* Written by Alex Barkov who has a shared copyright to this code */
25 
26 
27 #include "myisam.h"
28 #include "rt_index.h"
29 
30 #define MAX_REC_LENGTH 1024
31 #define ndims 2
32 #define KEYALG HA_KEY_ALG_RTREE
33 
34 static int read_with_pos(MI_INFO * file, int silent);
35 static void create_record(uchar *record,uint rownr);
36 static void create_record1(uchar *record,uint rownr);
37 static void print_record(uchar * record,my_off_t offs,const char * tail);
38 static  int run_test(const char *filename);
39 
40 static double rt_data[]=
41 {
42   /*1*/  0,10,0,10,
43   /*2*/  5,15,0,10,
44   /*3*/  0,10,5,15,
45   /*4*/  10,20,10,20,
46   /*5*/  0,10,0,10,
47   /*6*/  5,15,0,10,
48   /*7*/  0,10,5,15,
49   /*8*/  10,20,10,20,
50   /*9*/  0,10,0,10,
51   /*10*/  5,15,0,10,
52   /*11*/  0,10,5,15,
53   /*12*/  10,20,10,20,
54   /*13*/  0,10,0,10,
55   /*14*/  5,15,0,10,
56   /*15*/  0,10,5,15,
57   /*16*/  10,20,10,20,
58   /*17*/  5,15,0,10,
59   /*18*/  0,10,5,15,
60   /*19*/  10,20,10,20,
61   /*20*/  0,10,0,10,
62 
63   /*1*/  100,110,0,10,
64   /*2*/  105,115,0,10,
65   /*3*/  100,110,5,15,
66   /*4*/  110,120,10,20,
67   /*5*/  100,110,0,10,
68   /*6*/  105,115,0,10,
69   /*7*/  100,110,5,15,
70   /*8*/  110,120,10,20,
71   /*9*/  100,110,0,10,
72   /*10*/  105,115,0,10,
73   /*11*/  100,110,5,15,
74   /*12*/  110,120,10,20,
75   /*13*/  100,110,0,10,
76   /*14*/  105,115,0,10,
77   /*15*/  100,110,5,15,
78   /*16*/  110,120,10,20,
79   /*17*/  105,115,0,10,
80   /*18*/  100,110,5,15,
81   /*19*/  110,120,10,20,
82   /*20*/  100,110,0,10,
83   -1
84 };
85 
main(int argc MY_ATTRIBUTE ((unused)),char * argv[]MY_ATTRIBUTE ((unused)))86 int main(int argc MY_ATTRIBUTE((unused)),char *argv[] MY_ATTRIBUTE((unused)))
87 {
88   MY_INIT(argv[0]);
89   exit(run_test("rt_test"));
90 }
91 
92 
run_test(const char * filename)93 static int run_test(const char *filename)
94 {
95   MI_INFO        *file;
96   MI_UNIQUEDEF   uniquedef;
97   MI_CREATE_INFO create_info;
98   MI_COLUMNDEF   recinfo[20];
99   MI_KEYDEF      keyinfo[20];
100   HA_KEYSEG      keyseg[20];
101   key_range	range;
102 
103   int silent=0;
104   int opt_unique=0;
105   int create_flag=0;
106   int key_type=HA_KEYTYPE_DOUBLE;
107   int key_length=8;
108   int null_fields=0;
109   int nrecords=sizeof(rt_data)/(sizeof(double)*4);/* 3000;*/
110   int rec_length=0;
111   int uniques=0;
112   int i;
113   int error;
114   int row_count=0;
115   uchar record[MAX_REC_LENGTH];
116   uchar read_record[MAX_REC_LENGTH];
117   int upd= 10;
118   ha_rows hrows;
119 
120   /* Define a column for NULLs and DEL markers*/
121 
122   recinfo[0].type=FIELD_NORMAL;
123   recinfo[0].length=1; /* For NULL bits */
124   rec_length=1;
125 
126   /* Define 2*ndims columns for coordinates*/
127 
128   for (i=1; i<=2*ndims ;i++){
129     recinfo[i].type=FIELD_NORMAL;
130     recinfo[i].length=key_length;
131     rec_length+=key_length;
132   }
133 
134   /* Define a key with 2*ndims segments */
135 
136   keyinfo[0].seg=keyseg;
137   keyinfo[0].keysegs=2*ndims;
138   keyinfo[0].flag=0;
139   keyinfo[0].key_alg=KEYALG;
140 
141   for (i=0; i<2*ndims; i++){
142     keyinfo[0].seg[i].type= key_type;
143     keyinfo[0].seg[i].flag=0;          /* Things like HA_REVERSE_SORT */
144     keyinfo[0].seg[i].start= (key_length*i)+1;
145     keyinfo[0].seg[i].length=key_length;
146     keyinfo[0].seg[i].null_bit= null_fields ? 2 : 0;
147     keyinfo[0].seg[i].null_pos=0;
148     keyinfo[0].seg[i].language=default_charset_info->number;
149   }
150 
151   if (!silent)
152     printf("- Creating isam-file\n");
153 
154   memset(&create_info, 0, sizeof(create_info));
155   create_info.max_rows=10000000;
156 
157   if (mi_create(filename,
158                 1,            /*  keys   */
159                 keyinfo,
160                 1+2*ndims+opt_unique, /* columns */
161                 recinfo,uniques,&uniquedef,&create_info,create_flag))
162     goto err;
163 
164   if (!silent)
165     printf("- Open isam-file\n");
166 
167   if (!(file=mi_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
168     goto err;
169 
170   if (!silent)
171     printf("- Writing key:s\n");
172 
173   for (i=0; i<nrecords; i++ )
174   {
175     create_record(record,i);
176     error=mi_write(file,record);
177     print_record(record,mi_position(file),"\n");
178     if (!error)
179     {
180       row_count++;
181     }
182     else
183     {
184       printf("mi_write: %d\n", error);
185       goto err;
186     }
187   }
188 
189   if ((error=read_with_pos(file,silent)))
190     goto err;
191 
192   if (!silent)
193     printf("- Reading rows with key\n");
194 
195   for (i=0 ; i < nrecords ; i++)
196   {
197     my_errno=0;
198     create_record(record,i);
199 
200     memset(read_record, 0, MAX_REC_LENGTH);
201     error=mi_rkey(file,read_record,0,record+1,0,HA_READ_MBR_EQUAL);
202 
203     if (error && error!=HA_ERR_KEY_NOT_FOUND)
204     {
205       printf("     mi_rkey: %3d  errno: %3d\n",error,my_errno);
206       goto err;
207     }
208     if (error == HA_ERR_KEY_NOT_FOUND)
209     {
210       print_record(record,mi_position(file),"  NOT FOUND\n");
211       continue;
212     }
213     print_record(read_record,mi_position(file),"\n");
214   }
215 
216   if (!silent)
217     printf("- Deleting rows\n");
218   for (i=0; i < nrecords/4; i++)
219   {
220     my_errno=0;
221     memset(read_record, 0, MAX_REC_LENGTH);
222     error=mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
223     if (error)
224     {
225       printf("pos: %2d  mi_rrnd: %3d  errno: %3d\n",i,error,my_errno);
226       goto err;
227     }
228     print_record(read_record,mi_position(file),"\n");
229 
230     error=mi_delete(file,read_record);
231     if (error)
232     {
233       printf("pos: %2d mi_delete: %3d errno: %3d\n",i,error,my_errno);
234       goto err;
235     }
236   }
237 
238   if (!silent)
239     printf("- Updating rows with position\n");
240   for (i=0; i < (nrecords - nrecords/4) ; i++)
241   {
242     my_errno=0;
243     memset(read_record, 0, MAX_REC_LENGTH);
244     error=mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
245     if (error)
246     {
247       if (error==HA_ERR_RECORD_DELETED)
248         continue;
249       printf("pos: %2d  mi_rrnd: %3d  errno: %3d\n",i,error,my_errno);
250       goto err;
251     }
252     print_record(read_record,mi_position(file),"");
253     create_record(record,i+nrecords*upd);
254     printf("\t-> ");
255     print_record(record,mi_position(file),"\n");
256     error=mi_update(file,read_record,record);
257     if (error)
258     {
259       printf("pos: %2d  mi_update: %3d  errno: %3d\n",i,error,my_errno);
260       goto err;
261     }
262   }
263 
264   if ((error=read_with_pos(file,silent)))
265     goto err;
266 
267   if (!silent)
268     printf("- Test mi_rkey then a sequence of mi_rnext_same\n");
269 
270   create_record(record, nrecords*4/5);
271   print_record(record,0,"  search for\n");
272 
273   if ((error=mi_rkey(file,read_record,0,record+1,0,HA_READ_MBR_INTERSECT)))
274   {
275     printf("mi_rkey: %3d  errno: %3d\n",error,my_errno);
276     goto err;
277   }
278   print_record(read_record,mi_position(file),"  mi_rkey\n");
279   row_count=1;
280 
281   for (;;)
282   {
283     if ((error=mi_rnext_same(file,read_record)))
284     {
285       if (error==HA_ERR_END_OF_FILE)
286         break;
287       printf("mi_next: %3d  errno: %3d\n",error,my_errno);
288       goto err;
289     }
290     print_record(read_record,mi_position(file),"  mi_rnext_same\n");
291       row_count++;
292   }
293   printf("     %d rows\n",row_count);
294 
295   if (!silent)
296     printf("- Test mi_rfirst then a sequence of mi_rnext\n");
297 
298   error=mi_rfirst(file,read_record,0);
299   if (error)
300   {
301     printf("mi_rfirst: %3d  errno: %3d\n",error,my_errno);
302     goto err;
303   }
304   row_count=1;
305   print_record(read_record,mi_position(file),"  mi_frirst\n");
306 
307   for (i=0;i<nrecords;i++)
308   {
309     if ((error=mi_rnext(file,read_record,0)))
310     {
311       if (error==HA_ERR_END_OF_FILE)
312         break;
313       printf("mi_next: %3d  errno: %3d\n",error,my_errno);
314       goto err;
315     }
316     print_record(read_record,mi_position(file),"  mi_rnext\n");
317     row_count++;
318   }
319   printf("     %d rows\n",row_count);
320 
321   if (!silent)
322     printf("- Test mi_records_in_range()\n");
323 
324   create_record1(record, nrecords*4/5);
325   print_record(record,0,"\n");
326 
327   range.key= record+1;
328   range.length= 1000;                           /* Big enough */
329   range.flag= HA_READ_MBR_INTERSECT;
330   hrows= mi_records_in_range(file, 0, &range, (key_range*) 0);
331   printf("     %ld rows\n", (long) hrows);
332 
333   if (mi_close(file)) goto err;
334   my_end(MY_CHECK_ERROR);
335 
336   return 0;
337 
338 err:
339   printf("got error: %3d when using myisam-database\n",my_errno);
340   return 1;           /* skip warning */
341 }
342 
343 
344 
read_with_pos(MI_INFO * file,int silent)345 static int read_with_pos (MI_INFO * file,int silent)
346 {
347   int error;
348   int i;
349   uchar read_record[MAX_REC_LENGTH];
350 
351   if (!silent)
352     printf("- Reading rows with position\n");
353   for (i=0;;i++)
354   {
355     my_errno=0;
356     memset(read_record, 0, MAX_REC_LENGTH);
357     error=mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR);
358     if (error)
359     {
360       if (error==HA_ERR_END_OF_FILE)
361         break;
362       if (error==HA_ERR_RECORD_DELETED)
363         continue;
364       printf("pos: %2d  mi_rrnd: %3d  errno: %3d\n",i,error,my_errno);
365       return error;
366     }
367     print_record(read_record,mi_position(file),"\n");
368   }
369   return 0;
370 }
371 
372 
print_record(uchar * record,my_off_t offs MY_ATTRIBUTE ((unused)),const char * tail)373 static void print_record(uchar * record,
374 			 my_off_t offs MY_ATTRIBUTE((unused)),
375 			 const char * tail)
376 {
377   int i;
378   uchar * pos;
379   double c;
380 
381   printf("     rec=(%d)",(unsigned char)record[0]);
382   for ( pos=record+1, i=0; i<2*ndims; i++)
383    {
384       memcpy(&c,pos,sizeof(c));
385       float8get(&c,pos);
386       printf(" %.14g ",c);
387       pos+=sizeof(c);
388    }
389    printf("pos=%ld",(long int)offs);
390    printf("%s",tail);
391 }
392 
393 
394 
create_record1(uchar * record,uint rownr)395 static void create_record1(uchar *record,uint rownr)
396 {
397    int i;
398    uchar * pos;
399    double c=rownr+10;
400 
401    memset(record, 0, MAX_REC_LENGTH);
402    record[0]=0x01; /* DEL marker */
403 
404    for (pos=record+1, i=0; i<2*ndims; i++)
405    {
406       memcpy(pos,&c,sizeof(c));
407       float8store(pos,c);
408       pos+=sizeof(c);
409    }
410 }
411 
412 
create_record(uchar * record,uint rownr)413 static void create_record(uchar *record,uint rownr)
414 {
415    int i;
416    uchar *pos;
417    double *data= rt_data+rownr*4;
418    record[0]=0x01; /* DEL marker */
419    for (pos=record+1, i=0; i<ndims*2; i++)
420    {
421      float8store(pos,data[i]);
422      pos+=8;
423    }
424 }
425 
426 #else
main(int argc MY_ATTRIBUTE ((unused)),char * argv[]MY_ATTRIBUTE ((unused)))427 int main(int argc MY_ATTRIBUTE((unused)),char *argv[] MY_ATTRIBUTE((unused)))
428 {
429   exit(0);
430 }
431 
432 #include "mi_extrafunc.h"
433