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