~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/**********************************************************************
2
Data dictionary system
3
4
(c) 1996 Innobase Oy
5
6
Created 1/8/1996 Heikki Tuuri
7
***********************************************************************/
8
9
#include "dict0load.h"
10
#include "trx0undo.h"
11
#include "trx0sys.h"
12
#include "rem0types.h"
13
#include "data0type.h"
14
15
/*************************************************************************
16
Gets the column data type. */
17
UNIV_INLINE
18
void
19
dict_col_copy_type(
20
/*===============*/
21
	const dict_col_t*	col,	/* in: column */
22
	dtype_t*		type)	/* out: data type */
23
{
24
	ut_ad(col && type);
25
26
	type->mtype = col->mtype;
27
	type->prtype = col->prtype;
28
	type->len = col->len;
29
	type->mbminlen = col->mbminlen;
30
	type->mbmaxlen = col->mbmaxlen;
31
}
32
33
#ifdef UNIV_DEBUG
34
/*************************************************************************
35
Assert that a column and a data type match. */
36
UNIV_INLINE
37
ibool
38
dict_col_type_assert_equal(
39
/*=======================*/
40
					/* out: TRUE */
41
	const dict_col_t*	col,	/* in: column */
42
	const dtype_t*		type)	/* in: data type */
43
{
44
	ut_ad(col);
45
	ut_ad(type);
46
47
	ut_ad(col->mtype == type->mtype);
48
	ut_ad(col->prtype == type->prtype);
49
	ut_ad(col->len == type->len);
50
	ut_ad(col->mbminlen == type->mbminlen);
51
	ut_ad(col->mbmaxlen == type->mbmaxlen);
52
53
	return(TRUE);
54
}
55
#endif /* UNIV_DEBUG */
56
57
/***************************************************************************
58
Returns the minimum size of the column. */
59
UNIV_INLINE
60
ulint
61
dict_col_get_min_size(
62
/*==================*/
63
					/* out: minimum size */
64
	const dict_col_t*	col)	/* in: column */
65
{
66
	return(dtype_get_min_size_low(col->mtype, col->prtype, col->len,
67
				      col->mbminlen, col->mbmaxlen));
68
}
69
/***************************************************************************
70
Returns the maximum size of the column. */
71
UNIV_INLINE
72
ulint
73
dict_col_get_max_size(
74
/*==================*/
75
					/* out: maximum size */
76
	const dict_col_t*	col)	/* in: column */
77
{
78
	return(dtype_get_max_size_low(col->mtype, col->len));
79
}
80
/***************************************************************************
81
Returns the size of a fixed size column, 0 if not a fixed size column. */
82
UNIV_INLINE
83
ulint
84
dict_col_get_fixed_size(
85
/*====================*/
86
					/* out: fixed size, or 0 */
87
	const dict_col_t*	col)	/* in: column */
88
{
89
	return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len,
90
					col->mbminlen, col->mbmaxlen));
91
}
92
/***************************************************************************
93
Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column.
94
For fixed length types it is the fixed length of the type, otherwise 0. */
95
UNIV_INLINE
96
ulint
97
dict_col_get_sql_null_size(
98
/*=======================*/
99
					/* out: SQL null storage size
100
					in ROW_FORMAT=REDUNDANT */
101
	const dict_col_t*	col)	/* in: column */
102
{
103
	return(dict_col_get_fixed_size(col));
104
}
105
106
/*************************************************************************
107
Gets the column number. */
108
UNIV_INLINE
109
ulint
110
dict_col_get_no(
111
/*============*/
112
	const dict_col_t*	col)
113
{
114
	ut_ad(col);
115
116
	return(col->ind);
117
}
118
119
/*************************************************************************
120
Gets the column position in the clustered index. */
121
UNIV_INLINE
122
ulint
123
dict_col_get_clust_pos(
124
/*===================*/
125
	const dict_col_t*	col,		/* in: table column */
126
	const dict_index_t*	clust_index)	/* in: clustered index */
127
{
128
	ulint	i;
129
130
	ut_ad(col);
131
	ut_ad(clust_index && clust_index->type & DICT_CLUSTERED);
132
133
	for (i = 0; i < clust_index->n_def; i++) {
134
		const dict_field_t*	field = &clust_index->fields[i];
135
136
		if (!field->prefix_len && field->col == col) {
137
			return(i);
138
		}
139
	}
140
141
	return(ULINT_UNDEFINED);
142
}
143
144
/************************************************************************
145
Gets the first index on the table (the clustered index). */
146
UNIV_INLINE
147
dict_index_t*
148
dict_table_get_first_index(
149
/*=======================*/
150
				/* out: index, NULL if none exists */
151
	dict_table_t*	table)	/* in: table */
152
{
153
	ut_ad(table);
154
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
155
156
	return(UT_LIST_GET_FIRST(table->indexes));
157
}
158
159
/************************************************************************
160
Gets the next index on the table. */
161
UNIV_INLINE
162
dict_index_t*
163
dict_table_get_next_index(
164
/*======================*/
165
				/* out: index, NULL if none left */
166
	dict_index_t*	index)	/* in: index */
167
{
168
	ut_ad(index);
169
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
170
171
	return(UT_LIST_GET_NEXT(indexes, index));
172
}
173
174
/************************************************************************
175
Gets the number of user-defined columns in a table in the dictionary
176
cache. */
177
UNIV_INLINE
178
ulint
179
dict_table_get_n_user_cols(
180
/*=======================*/
181
				/* out: number of user-defined (e.g., not
182
				ROW_ID) columns of a table */
183
	dict_table_t*	table)	/* in: table */
184
{
185
	ut_ad(table);
186
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
187
188
	return(table->n_cols - DATA_N_SYS_COLS);
189
}
190
191
/************************************************************************
192
Gets the number of system columns in a table in the dictionary cache. */
193
UNIV_INLINE
194
ulint
195
dict_table_get_n_sys_cols(
196
/*======================*/
197
				/* out: number of system (e.g.,
198
				ROW_ID) columns of a table */
199
	dict_table_t*	table __attribute__((unused)))	/* in: table */
200
{
201
	ut_ad(table);
202
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
203
	ut_ad(table->cached);
204
205
	return(DATA_N_SYS_COLS);
206
}
207
208
/************************************************************************
209
Gets the number of all columns (also system) in a table in the dictionary
210
cache. */
211
UNIV_INLINE
212
ulint
213
dict_table_get_n_cols(
214
/*==================*/
215
				/* out: number of columns of a table */
216
	dict_table_t*	table)	/* in: table */
217
{
218
	ut_ad(table);
219
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
220
221
	return(table->n_cols);
222
}
223
224
/************************************************************************
225
Gets the nth column of a table. */
226
UNIV_INLINE
227
const dict_col_t*
228
dict_table_get_nth_col(
229
/*===================*/
230
					/* out: pointer to column object */
231
	const dict_table_t*	table,	/* in: table */
232
	ulint			pos)	/* in: position of column */
233
{
234
	ut_ad(table);
235
	ut_ad(pos < table->n_def);
236
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
237
238
	return((table->cols) + pos);
239
}
240
241
/************************************************************************
242
Gets the given system column of a table. */
243
UNIV_INLINE
244
const dict_col_t*
245
dict_table_get_sys_col(
246
/*===================*/
247
					/* out: pointer to column object */
248
	const dict_table_t*	table,	/* in: table */
249
	ulint			sys)	/* in: DATA_ROW_ID, ... */
250
{
251
	const dict_col_t*	col;
252
253
	ut_ad(table);
254
	ut_ad(sys < DATA_N_SYS_COLS);
255
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
256
257
	col = dict_table_get_nth_col(table, table->n_cols
258
				     - DATA_N_SYS_COLS + sys);
259
	ut_ad(col->mtype == DATA_SYS);
260
	ut_ad(col->prtype == (sys | DATA_NOT_NULL));
261
262
	return(col);
263
}
264
265
/************************************************************************
266
Gets the given system column number of a table. */
267
UNIV_INLINE
268
ulint
269
dict_table_get_sys_col_no(
270
/*======================*/
271
				/* out: column number */
272
	dict_table_t*	table,	/* in: table */
273
	ulint		sys)	/* in: DATA_ROW_ID, ... */
274
{
275
	ut_ad(table);
276
	ut_ad(sys < DATA_N_SYS_COLS);
277
	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
278
279
	return(table->n_cols - DATA_N_SYS_COLS + sys);
280
}
281
282
/************************************************************************
283
Check whether the table uses the compact page format. */
284
UNIV_INLINE
285
ibool
286
dict_table_is_comp(
287
/*===============*/
288
					/* out: TRUE if table uses the
289
					compact page format */
290
	const dict_table_t*	table)	/* in: table */
291
{
292
	ut_ad(table);
293
294
#if DICT_TF_COMPACT != TRUE
295
#error
296
#endif
297
298
	return(UNIV_LIKELY(table->flags & DICT_TF_COMPACT));
299
}
300
301
/************************************************************************
302
Gets the number of fields in the internal representation of an index,
303
including fields added by the dictionary system. */
304
UNIV_INLINE
305
ulint
306
dict_index_get_n_fields(
307
/*====================*/
308
				/* out: number of fields */
309
	dict_index_t*	index)	/* in: an internal representation of index
310
				(in the dictionary cache) */
311
{
312
	ut_ad(index);
313
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
314
315
	return(index->n_fields);
316
}
317
318
/************************************************************************
319
Gets the number of fields in the internal representation of an index
320
that uniquely determine the position of an index entry in the index, if
321
we do not take multiversioning into account: in the B-tree use the value
322
returned by dict_index_get_n_unique_in_tree. */
323
UNIV_INLINE
324
ulint
325
dict_index_get_n_unique(
326
/*====================*/
327
				/* out: number of fields */
328
	dict_index_t*	index)	/* in: an internal representation of index
329
				(in the dictionary cache) */
330
{
331
	ut_ad(index);
332
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
333
	ut_ad(index->cached);
334
335
	return(index->n_uniq);
336
}
337
338
/************************************************************************
339
Gets the number of fields in the internal representation of an index
340
which uniquely determine the position of an index entry in the index, if
341
we also take multiversioning into account. */
342
UNIV_INLINE
343
ulint
344
dict_index_get_n_unique_in_tree(
345
/*============================*/
346
				/* out: number of fields */
347
	dict_index_t*	index)	/* in: an internal representation of index
348
				(in the dictionary cache) */
349
{
350
	ut_ad(index);
351
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
352
	ut_ad(index->cached);
353
354
	if (index->type & DICT_CLUSTERED) {
355
356
		return(dict_index_get_n_unique(index));
357
	}
358
359
	return(dict_index_get_n_fields(index));
360
}
361
362
/************************************************************************
363
Gets the number of user-defined ordering fields in the index. In the internal
364
representation of clustered indexes we add the row id to the ordering fields
365
to make a clustered index unique, but this function returns the number of
366
fields the user defined in the index as ordering fields. */
367
UNIV_INLINE
368
ulint
369
dict_index_get_n_ordering_defined_by_user(
370
/*======================================*/
371
				/* out: number of fields */
372
	dict_index_t*	index)	/* in: an internal representation of index
373
				(in the dictionary cache) */
374
{
375
	return(index->n_user_defined_cols);
376
}
377
378
/************************************************************************
379
Gets the nth field of an index. */
380
UNIV_INLINE
381
dict_field_t*
382
dict_index_get_nth_field(
383
/*=====================*/
384
				/* out: pointer to field object */
385
	dict_index_t*	index,	/* in: index */
386
	ulint		pos)	/* in: position of field */
387
{
388
	ut_ad(index);
389
	ut_ad(pos < index->n_def);
390
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
391
392
	return((index->fields) + pos);
393
}
394
395
/************************************************************************
396
Returns the position of a system column in an index. */
397
UNIV_INLINE
398
ulint
399
dict_index_get_sys_col_pos(
400
/*=======================*/
401
				/* out: position, ULINT_UNDEFINED if not
402
				contained */
403
	dict_index_t*	index,	/* in: index */
404
	ulint		type)	/* in: DATA_ROW_ID, ... */
405
{
406
	ut_ad(index);
407
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
408
	ut_ad(!(index->type & DICT_UNIVERSAL));
409
410
	if (index->type & DICT_CLUSTERED) {
411
412
		return(dict_col_get_clust_pos(
413
			       dict_table_get_sys_col(index->table, type),
414
			       index));
415
	}
416
417
	return(dict_index_get_nth_col_pos(
418
		       index, dict_table_get_sys_col_no(index->table, type)));
419
}
420
421
/*************************************************************************
422
Gets the field column. */
423
UNIV_INLINE
424
const dict_col_t*
425
dict_field_get_col(
426
/*===============*/
427
	const dict_field_t*	field)
428
{
429
	ut_ad(field);
430
431
	return(field->col);
432
}
433
434
/************************************************************************
435
Gets pointer to the nth column in an index. */
436
UNIV_INLINE
437
const dict_col_t*
438
dict_index_get_nth_col(
439
/*===================*/
440
					/* out: column */
441
	const dict_index_t*	index,	/* in: index */
442
	ulint			pos)	/* in: position of the field */
443
{
444
	return(dict_field_get_col(dict_index_get_nth_field((dict_index_t*)
445
							   index, pos)));
446
}
447
448
/************************************************************************
449
Gets the column number the nth field in an index. */
450
UNIV_INLINE
451
ulint
452
dict_index_get_nth_col_no(
453
/*======================*/
454
					/* out: column number */
455
	const dict_index_t*	index,	/* in: index */
456
	ulint			pos)	/* in: position of the field */
457
{
458
	return(dict_col_get_no(dict_index_get_nth_col(index, pos)));
459
}
460
461
/*************************************************************************
462
Gets the space id of the root of the index tree. */
463
UNIV_INLINE
464
ulint
465
dict_index_get_space(
466
/*=================*/
467
				/* out: space id */
468
	dict_index_t*	index)	/* in: index */
469
{
470
	ut_ad(index);
471
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
472
473
	return(index->space);
474
}
475
476
/*************************************************************************
477
Sets the space id of the root of the index tree. */
478
UNIV_INLINE
479
void
480
dict_index_set_space(
481
/*=================*/
482
	dict_index_t*	index,	/* in: index */
483
	ulint		space)	/* in: space id */
484
{
485
	ut_ad(index);
486
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
487
488
	index->space = space;
489
}
490
491
/*************************************************************************
492
Gets the page number of the root of the index tree. */
493
UNIV_INLINE
494
ulint
495
dict_index_get_page(
496
/*================*/
497
				/* out: page number */
498
	dict_index_t*	index)	/* in: index */
499
{
500
	ut_ad(index);
501
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
502
503
	return(index->page);
504
}
505
506
/*************************************************************************
507
Sets the page number of the root of index tree. */
508
UNIV_INLINE
509
void
510
dict_index_set_page(
511
/*================*/
512
	dict_index_t*	index,	/* in: index */
513
	ulint		page)	/* in: page number */
514
{
515
	ut_ad(index);
516
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
517
518
	index->page = page;
519
}
520
521
/*************************************************************************
522
Gets the type of the index tree. */
523
UNIV_INLINE
524
ulint
525
dict_index_get_type(
526
/*================*/
527
				/* out: type */
528
	dict_index_t*	index)	/* in: index */
529
{
530
	ut_ad(index);
531
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
532
533
	return(index->type);
534
}
535
536
/*************************************************************************
537
Gets the read-write lock of the index tree. */
538
UNIV_INLINE
539
rw_lock_t*
540
dict_index_get_lock(
541
/*================*/
542
				/* out: read-write lock */
543
	dict_index_t*	index)	/* in: index */
544
{
545
	ut_ad(index);
546
	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
547
548
	return(&(index->lock));
549
}
550
551
/************************************************************************
552
Returns free space reserved for future updates of records. This is
553
relevant only in the case of many consecutive inserts, as updates
554
which make the records bigger might fragment the index. */
555
UNIV_INLINE
556
ulint
557
dict_index_get_space_reserve(void)
558
/*==============================*/
559
				/* out: number of free bytes on page,
560
				reserved for updates */
561
{
562
	return(UNIV_PAGE_SIZE / 16);
563
}
564
565
/**************************************************************************
566
Checks if a table is in the dictionary cache. */
567
UNIV_INLINE
568
dict_table_t*
569
dict_table_check_if_in_cache_low(
570
/*=============================*/
571
					/* out: table, NULL if not found */
572
	const char*	table_name)	/* in: table name */
573
{
574
	dict_table_t*	table;
575
	ulint		table_fold;
576
577
	ut_ad(table_name);
578
	ut_ad(mutex_own(&(dict_sys->mutex)));
579
580
	/* Look for the table name in the hash table */
581
	table_fold = ut_fold_string(table_name);
582
583
	HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold, table,
584
		    ut_strcmp(table->name, table_name) == 0);
585
	return(table);
586
}
587
588
/**************************************************************************
589
Gets a table; loads it to the dictionary cache if necessary. A low-level
590
function. */
591
UNIV_INLINE
592
dict_table_t*
593
dict_table_get_low(
594
/*===============*/
595
					/* out: table, NULL if not found */
596
	const char*	table_name)	/* in: table name */
597
{
598
	dict_table_t*	table;
599
600
	ut_ad(table_name);
601
	ut_ad(mutex_own(&(dict_sys->mutex)));
602
603
	table = dict_table_check_if_in_cache_low(table_name);
604
605
	if (table == NULL) {
606
		table = dict_load_table(table_name);
607
	}
608
609
	return(table);
610
}
611
612
/**************************************************************************
613
Returns a table object based on table id. */
614
UNIV_INLINE
615
dict_table_t*
616
dict_table_get_on_id_low(
617
/*=====================*/
618
				/* out: table, NULL if does not exist */
619
	dulint	table_id)	/* in: table id */
620
{
621
	dict_table_t*	table;
622
	ulint		fold;
623
624
	ut_ad(mutex_own(&(dict_sys->mutex)));
625
626
	/* Look for the table name in the hash table */
627
	fold = ut_fold_dulint(table_id);
628
629
	HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold, table,
630
		    ut_dulint_cmp(table->id, table_id) == 0);
631
	if (table == NULL) {
632
		table = dict_load_table_on_id(table_id);
633
	}
634
635
	/* TODO: should get the type information from MySQL */
636
637
	return(table);
638
}
639
640
/**************************************************************************
641
Returns an index object. */
642
UNIV_INLINE
643
dict_index_t*
644
dict_table_get_index(
645
/*=================*/
646
				/* out: index, NULL if does not exist */
647
	dict_table_t*	table,	/* in: table */
648
	const char*	name)	/* in: index name */
649
{
650
	dict_index_t*	index	= NULL;
651
652
	index = dict_table_get_first_index(table);
653
654
	while (index != NULL) {
655
		if (ut_strcmp(name, index->name) == 0) {
656
657
			break;
658
		}
659
660
		index = dict_table_get_next_index(index);
661
	}
662
663
	return(index);
664
}