Beispiel #1
0
/******************************************************************//**
Add a bound identifier to a symbol table.
@return	symbol table node */
UNIV_INTERN
sym_node_t*
sym_tab_add_bound_id(
/*===========*/
	sym_tab_t*	sym_tab,	/*!< in: symbol table */
	const char*	name)		/*!< in: name of bound id */
{
	sym_node_t*		node;
	pars_bound_id_t*	bid;

	bid = pars_info_get_bound_id(sym_tab->info, name);
	ut_a(bid);

	node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));

	node->common.type = QUE_NODE_SYMBOL;

	node->resolved = FALSE;
	node->indirection = NULL;

	node->name = mem_heap_strdup(sym_tab->heap, bid->id);
	node->name_len = strlen(node->name);

	UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);

	dfield_set_null(&node->common.val);

	node->common.val_buf_size = 0;
	node->prefetch_buf = NULL;
	node->cursor_def = NULL;

	node->sym_table = sym_tab;

	return(node);
}
Beispiel #2
0
/******************************************************************//**
Adds an identifier to a symbol table.
@return	symbol table node */
UNIV_INTERN
sym_node_t*
sym_tab_add_id(
/*===========*/
	sym_tab_t*	sym_tab,	/*!< in: symbol table */
	byte*		name,		/*!< in: identifier name */
	ulint		len)		/*!< in: identifier length */
{
	sym_node_t*	node;

	node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));

	node->common.type = QUE_NODE_SYMBOL;

	node->resolved = FALSE;
	node->indirection = NULL;

	node->name = mem_heap_strdupl(sym_tab->heap, (char*) name, len);
	node->name_len = len;

	UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);

	dfield_set_null(&node->common.val);

	node->common.val_buf_size = 0;
	node->prefetch_buf = NULL;
	node->cursor_def = NULL;

	node->sym_table = sym_tab;

	return(node);
}
Beispiel #3
0
/******************************************************************//**
Adds an SQL null literal to a symbol table.
@return	symbol table node */
UNIV_INTERN
sym_node_t*
sym_tab_add_null_lit(
/*=================*/
	sym_tab_t*	sym_tab)	/*!< in: symbol table */
{
	sym_node_t*	node;

	node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));

	node->common.type = QUE_NODE_SYMBOL;

	node->resolved = TRUE;
	node->token_type = SYM_LIT;

	node->indirection = NULL;

	dfield_get_type(&node->common.val)->mtype = DATA_ERROR;

	dfield_set_null(&node->common.val);

	node->common.val_buf_size = 0;
	node->prefetch_buf = NULL;
	node->cursor_def = NULL;

	UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);

	node->sym_table = sym_tab;

	return(node);
}
Beispiel #4
0
/*******************************************************************//**
Builds an update vector based on a remaining part of an undo log record.
@return remaining part of the record, NULL if an error detected, which
means that the record is corrupted */
UNIV_INTERN
byte*
trx_undo_update_rec_get_update(
/*===========================*/
	byte*		ptr,	/*!< in: remaining part in update undo log
				record, after reading the row reference
				NOTE that this copy of the undo log record must
				be preserved as long as the update vector is
				used, as we do NOT copy the data in the
				record! */
	dict_index_t*	index,	/*!< in: clustered index */
	ulint		type,	/*!< in: TRX_UNDO_UPD_EXIST_REC,
				TRX_UNDO_UPD_DEL_REC, or
				TRX_UNDO_DEL_MARK_REC; in the last case,
				only trx id and roll ptr fields are added to
				the update vector */
	trx_id_t	trx_id,	/*!< in: transaction id from this undo record */
	roll_ptr_t	roll_ptr,/*!< in: roll pointer from this undo record */
	ulint		info_bits,/*!< in: info bits from this undo record */
	trx_t*		trx,	/*!< in: transaction */
	mem_heap_t*	heap,	/*!< in: memory heap from which the memory
				needed is allocated */
	upd_t**		upd)	/*!< out, own: update vector */
{
	upd_field_t*	upd_field;
	upd_t*		update;
	ulint		n_fields;
	byte*		buf;
	ulint		i;

	ut_a(dict_index_is_clust(index));

	if (type != TRX_UNDO_DEL_MARK_REC) {
		ptr = trx_undo_update_rec_get_n_upd_fields(ptr, &n_fields);
	} else {
		n_fields = 0;
	}

	update = upd_create(n_fields + 2, heap);

	update->info_bits = info_bits;

	/* Store first trx id and roll ptr to update vector */

	upd_field = upd_get_nth_field(update, n_fields);
	buf = mem_heap_alloc(heap, DATA_TRX_ID_LEN);
	trx_write_trx_id(buf, trx_id);

	upd_field_set_field_no(upd_field,
			       dict_index_get_sys_col_pos(index, DATA_TRX_ID),
			       index, trx);
	dfield_set_data(&(upd_field->new_val), buf, DATA_TRX_ID_LEN);

	upd_field = upd_get_nth_field(update, n_fields + 1);
	buf = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN);
	trx_write_roll_ptr(buf, roll_ptr);

	upd_field_set_field_no(
		upd_field, dict_index_get_sys_col_pos(index, DATA_ROLL_PTR),
		index, trx);
	dfield_set_data(&(upd_field->new_val), buf, DATA_ROLL_PTR_LEN);

	/* Store then the updated ordinary columns to the update vector */

	for (i = 0; i < n_fields; i++) {

		byte*	field;
		ulint	len;
		ulint	field_no;
		ulint	orig_len;

		ptr = trx_undo_update_rec_get_field_no(ptr, &field_no);

		if (field_no >= dict_index_get_n_fields(index)) {
			fprintf(stderr,
				"InnoDB: Error: trying to access"
				" update undo rec field %lu in ",
				(ulong) field_no);
			dict_index_name_print(stderr, trx, index);
			fprintf(stderr, "\n"
				"InnoDB: but index has only %lu fields\n"
				"InnoDB: Submit a detailed bug report"
				" to http://bugs.mysql.com\n"
				"InnoDB: Run also CHECK TABLE ",
				(ulong) dict_index_get_n_fields(index));
			ut_print_name(stderr, trx, TRUE, index->table_name);
			fprintf(stderr, "\n"
				"InnoDB: n_fields = %lu, i = %lu, ptr %p\n",
				(ulong) n_fields, (ulong) i, ptr);
			*upd = NULL;
			return(NULL);
		}

		upd_field = upd_get_nth_field(update, i);

		upd_field_set_field_no(upd_field, field_no, index, trx);

		ptr = trx_undo_rec_get_col_val(ptr, &field, &len, &orig_len);

		upd_field->orig_len = orig_len;

		if (len == UNIV_SQL_NULL) {
			dfield_set_null(&upd_field->new_val);
		} else if (len < UNIV_EXTERN_STORAGE_FIELD) {
			dfield_set_data(&upd_field->new_val, field, len);
		} else {
			len -= UNIV_EXTERN_STORAGE_FIELD;

			dfield_set_data(&upd_field->new_val, field, len);
			dfield_set_ext(&upd_field->new_val);
		}
	}

	*upd = update;

	return(ptr);
}
Beispiel #5
0
/*****************************************************************//**
Based on a table object, this function builds the entry to be inserted
in the SYS_TABLES system table.
@return	the tuple which should be inserted */
static
dtuple_t*
dict_create_sys_tables_tuple(
    /*=========================*/
    const dict_table_t*	table,	/*!< in: table */
    mem_heap_t*		heap)	/*!< in: memory heap from
					which the memory for the built
					tuple is allocated */
{
    dict_table_t*	sys_tables;
    dtuple_t*	entry;
    dfield_t*	dfield;
    byte*		ptr;

    ut_ad(table);
    ut_ad(heap);

    sys_tables = dict_sys->sys_tables;

    entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS);

    dict_table_copy_types(entry, sys_tables);

    /* 0: NAME -----------------------------*/
    dfield = dtuple_get_nth_field(entry, 0/*NAME*/);

    dfield_set_data(dfield, table->name, ut_strlen(table->name));
    /* 3: ID -------------------------------*/
    dfield = dtuple_get_nth_field(entry, 1/*ID*/);

    ptr = mem_heap_alloc(heap, 8);
    mach_write_to_8(ptr, table->id);

    dfield_set_data(dfield, ptr, 8);
    /* 4: N_COLS ---------------------------*/
    dfield = dtuple_get_nth_field(entry, 2/*N_COLS*/);

#if DICT_TF_COMPACT != 1
#error
#endif

    ptr = mem_heap_alloc(heap, 4);
    if (dict_table_is_gcs(table))                       /* ±í¶¨ÒåÐÞ¸Ä */
    {
        ut_ad(dict_table_is_comp(table));

        mach_write_to_4(ptr, table->n_def
                        | (1 << 31) | (1 << 30));
    }
    else
    {
        mach_write_to_4(ptr, table->n_def
                        | ((table->flags & DICT_TF_COMPACT) << 31));
    }

    dfield_set_data(dfield, ptr, 4);
    /* 5: TYPE -----------------------------*/
    dfield = dtuple_get_nth_field(entry, 3/*TYPE*/);

    ptr = mem_heap_alloc(heap, 4);
    if (table->flags & (~DICT_TF_COMPACT & ~(~0 << DICT_TF_BITS))) {
        ut_a(table->flags & DICT_TF_COMPACT);
        ut_a(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
        ut_a((table->flags & DICT_TF_ZSSIZE_MASK)
             <= (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT));
        ut_a(!(table->flags & (~0 << DICT_TF2_BITS)));
        mach_write_to_4(ptr, table->flags & ~(~0 << DICT_TF_BITS));
    } else {
        mach_write_to_4(ptr, DICT_TABLE_ORDINARY);
    }

    dfield_set_data(dfield, ptr, 4);
    /* 6: MIX_ID (obsolete) ---------------------------*/
    dfield = dtuple_get_nth_field(entry, 4/*MIX_ID*/);

    ptr = mem_heap_zalloc(heap, 8);

    dfield_set_data(dfield, ptr, 8);
    /* 7: MIX_LEN (additional flags) --------------------------*/

    dfield = dtuple_get_nth_field(entry, 5/*MIX_LEN*/);

    ptr = mem_heap_alloc(heap, 4);
    mach_write_to_4(ptr, table->flags >> DICT_TF2_SHIFT);

    ut_ad(table->n_cols_before_alter_table == 0);

    dfield_set_data(dfield, ptr, 4);
    /* 8: CLUSTER_NAME ---------------------*/
    dfield = dtuple_get_nth_field(entry, 6/*CLUSTER_NAME*/);
    dfield_set_null(dfield); /* not supported */

    /* 9: SPACE ----------------------------*/
    dfield = dtuple_get_nth_field(entry, 7/*SPACE*/);

    ptr = mem_heap_alloc(heap, 4);
    mach_write_to_4(ptr, table->space);

    dfield_set_data(dfield, ptr, 4);
    /*----------------------------------*/

    return(entry);
}
/*******************************************************************//**
Converts an index record to a typed data tuple.
@return index entry built; does not set info_bits, and the data fields
in the entry will point directly to rec */
UNIV_INTERN
dtuple_t*
row_rec_to_index_entry_low(
/*=======================*/
	const rec_t*		rec,	/*!< in: record in the index */
	const dict_index_t*	index,	/*!< in: index */
	const ulint*		offsets,/*!< in: rec_get_offsets(rec, index) */
	ulint*			n_ext,	/*!< out: number of externally
					stored columns */
	mem_heap_t*		heap)	/*!< in: memory heap from which
					the memory needed is allocated */
{
	dtuple_t*	entry;
	dfield_t*	dfield;
	ulint		i;
	const byte*	field;
	ulint		len;
	ulint		rec_len;

	ut_ad(rec && heap && index);
	/* Because this function may be invoked by row0merge.c
	on a record whose header is in different format, the check
	rec_offs_validate(rec, index, offsets) must be avoided here. */
	ut_ad(n_ext);
	*n_ext = 0;

	rec_len = rec_offs_n_fields(offsets);

	if (srv_use_sys_stats_table
	    && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)) {
		if (rec_len < dict_index_get_n_fields(index)) {
			/* the new record should be extended */
			rec_len = dict_index_get_n_fields(index);
		}
	}

	entry = dtuple_create(heap, rec_len);

	dtuple_set_n_fields_cmp(entry,
				dict_index_get_n_unique_in_tree(index));
	ut_ad(rec_len == dict_index_get_n_fields(index));

	dict_index_copy_types(entry, index, rec_len);

	for (i = 0; i < rec_len; i++) {

		dfield = dtuple_get_nth_field(entry, i);

		if (srv_use_sys_stats_table
		    && index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
		    && i >= rec_offs_n_fields(offsets)) {
			dfield_set_null(dfield);
			continue;
		}

		field = rec_get_nth_field(rec, offsets, i, &len);

		dfield_set_data(dfield, field, len);

		if (rec_offs_nth_extern(offsets, i)) {
			dfield_set_ext(dfield);
			(*n_ext)++;
		}
	}

	ut_ad(dtuple_check_typed(entry));

	return(entry);
}