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