Commit f5ea301a authored by Sergei Golubchik's avatar Sergei Golubchik

Added support for NO_RECORD record format (don't store any row data) for Aria.

This makes the keys smaller (no row pointer) and gives us proper errors if we
use the table wrongly.

sql/sql_select.cc:
  Use NO_RECORD for tables that doesn't need row data.
storage/maria/Makefile.am:
  Added ma_norec.c
storage/maria/ma_check.c:
  Added support for NO_RECORD record format (don't store any row data)
storage/maria/ma_norec.c:
  Added support for NO_RECORD record format
storage/maria/ma_open.c:
  Added support for NO_RECORD record format
storage/maria/ma_search.c:
  Added support for 0 size row pointers (used with NO_RECORD)
storage/maria/ma_test1.c:
  Added testing of NO_RECORD record format.
storage/maria/maria_chk.c:
  Added support for NO_RECORD
storage/maria/maria_def.h:
  Added support for NO_RECORD
storage/maria/unittest/ma_test_all-t:
  Added testing of NO_RECORD record format
parent 17c18877
...@@ -519,7 +519,7 @@ enum en_fieldtype { ...@@ -519,7 +519,7 @@ enum en_fieldtype {
}; };
enum data_file_type { enum data_file_type {
STATIC_RECORD, DYNAMIC_RECORD, COMPRESSED_RECORD, BLOCK_RECORD STATIC_RECORD, DYNAMIC_RECORD, COMPRESSED_RECORD, BLOCK_RECORD, NO_RECORD
}; };
/* For key ranges */ /* For key ranges */
......
...@@ -12550,9 +12550,10 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, ...@@ -12550,9 +12550,10 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
create_info.data_file_length= ~(ulonglong) 0; create_info.data_file_length= ~(ulonglong) 0;
if ((error= maria_create(share->table_name.str, if ((error= maria_create(share->table_name.str,
share->reclength < 64 && table->no_rows ? NO_RECORD :
(share->reclength < 64 &&
!share->blob_fields ? STATIC_RECORD : !share->blob_fields ? STATIC_RECORD :
BLOCK_RECORD, BLOCK_RECORD),
share->keys, &keydef, share->keys, &keydef,
(uint) (*recinfo-start_recinfo), (uint) (*recinfo-start_recinfo),
start_recinfo, start_recinfo,
......
...@@ -124,7 +124,7 @@ libaria_la_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \ ...@@ -124,7 +124,7 @@ libaria_la_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
ma_search.c ma_page.c ma_key_recover.c ma_key.c \ ma_search.c ma_page.c ma_key_recover.c ma_key.c \
ma_locking.c ma_state.c \ ma_locking.c ma_state.c \
ma_rrnd.c ma_scan.c ma_cache.c \ ma_rrnd.c ma_scan.c ma_cache.c \
ma_statrec.c ma_packrec.c ma_dynrec.c \ ma_statrec.c ma_packrec.c ma_dynrec.c ma_norec.c \
ma_blockrec.c ma_bitmap.c \ ma_blockrec.c ma_bitmap.c \
ma_update.c ma_write.c ma_unique.c \ ma_update.c ma_write.c ma_unique.c \
ma_delete.c \ ma_delete.c \
......
...@@ -993,10 +993,12 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, ...@@ -993,10 +993,12 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
/* fall through */ /* fall through */
} }
if ((share->data_file_type != BLOCK_RECORD && if ((share->data_file_type != BLOCK_RECORD &&
share->data_file_type != NO_RECORD &&
record >= share->state.state.data_file_length) || record >= share->state.state.data_file_length) ||
(share->data_file_type == BLOCK_RECORD && (share->data_file_type == BLOCK_RECORD &&
ma_recordpos_to_page(record) * share->base.min_block_length >= ma_recordpos_to_page(record) * share->base.min_block_length >=
share->state.state.data_file_length)) share->state.state.data_file_length) ||
(share->data_file_type == NO_RECORD && record != 0))
{ {
#ifndef DBUG_OFF #ifndef DBUG_OFF
char llbuff2[22], llbuff3[22]; char llbuff2[22], llbuff3[22];
...@@ -2047,6 +2049,12 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend) ...@@ -2047,6 +2049,12 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
case COMPRESSED_RECORD: case COMPRESSED_RECORD:
error= check_compressed_record(param, info, extend, record); error= check_compressed_record(param, info, extend, record);
break; break;
case NO_RECORD:
param->records= share->state.state.records;
param->record_checksum= 0;
extend= 1; /* No row checksums */
/* no data, nothing to do */
break;
} /* switch */ } /* switch */
if (error) if (error)
...@@ -2277,7 +2285,14 @@ static int initialize_variables_for_repair(HA_CHECK *param, ...@@ -2277,7 +2285,14 @@ static int initialize_variables_for_repair(HA_CHECK *param,
{ {
MARIA_SHARE *share= info->s; MARIA_SHARE *share= info->s;
/* Ro allow us to restore state and check how state changed */ if (share->data_file_type == NO_RECORD)
{
_ma_check_print_error(param,
"Can't repair tables with record type NO_DATA");
return 1;
}
/* Allow us to restore state and check how state changed */
memcpy(org_share, share, sizeof(*share)); memcpy(org_share, share, sizeof(*share));
/* Repair code relies on share->state.state so we have to update it here */ /* Repair code relies on share->state.state so we have to update it here */
...@@ -5184,6 +5199,8 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) ...@@ -5184,6 +5199,8 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
} }
DBUG_RETURN(0); DBUG_RETURN(0);
} }
case NO_RECORD:
DBUG_RETURN(1); /* Impossible */
} }
DBUG_RETURN(1); /* Impossible */ DBUG_RETURN(1); /* Impossible */
} }
...@@ -5305,6 +5322,8 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param) ...@@ -5305,6 +5322,8 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param)
sort_param->filepos+=reclength+length; sort_param->filepos+=reclength+length;
share->state.split++; share->state.split++;
break; break;
case NO_RECORD:
DBUG_RETURN(1); /* Impossible */
} }
} }
if (sort_param->master) if (sort_param->master)
......
...@@ -250,10 +250,16 @@ int maria_create(const char *name, enum data_file_type datafile_type, ...@@ -250,10 +250,16 @@ int maria_create(const char *name, enum data_file_type datafile_type,
datafile_type= BLOCK_RECORD; datafile_type= BLOCK_RECORD;
} }
if (datafile_type == NO_RECORD && uniques)
{
/* Can't do unique without data, revert to block records */
datafile_type= BLOCK_RECORD;
}
if (datafile_type == DYNAMIC_RECORD) if (datafile_type == DYNAMIC_RECORD)
options|= HA_OPTION_PACK_RECORD; /* Must use packed records */ options|= HA_OPTION_PACK_RECORD; /* Must use packed records */
if (datafile_type == STATIC_RECORD) if (datafile_type == STATIC_RECORD || datafile_type == NO_RECORD)
{ {
/* We can't use checksum with static length rows */ /* We can't use checksum with static length rows */
flags&= ~HA_CREATE_CHECKSUM; flags&= ~HA_CREATE_CHECKSUM;
...@@ -366,7 +372,9 @@ int maria_create(const char *name, enum data_file_type datafile_type, ...@@ -366,7 +372,9 @@ int maria_create(const char *name, enum data_file_type datafile_type,
} }
else else
{ {
if (datafile_type != STATIC_RECORD) if (datafile_type == NO_RECORD)
pointer= 0;
else if (datafile_type != STATIC_RECORD)
pointer= maria_get_pointer_length(ci->data_file_length, pointer= maria_get_pointer_length(ci->data_file_length,
maria_data_pointer_size); maria_data_pointer_size);
else else
......
/* Copyright (C) 2010 Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Functions to handle tables with no row data (only index)
This is useful when you just want to do key reads or want to use
the index to check against duplicates.
*/
#include "maria_def.h"
my_bool _ma_write_no_record(MARIA_HA *info __attribute__((unused)),
const uchar *record __attribute__((unused)))
{
return 0;
}
my_bool _ma_update_no_record(MARIA_HA *info __attribute__((unused)),
MARIA_RECORD_POS pos __attribute__((unused)),
const uchar *oldrec __attribute__((unused)),
const uchar *record __attribute__((unused)))
{
return HA_ERR_WRONG_COMMAND;
}
my_bool _ma_delete_no_record(MARIA_HA *info __attribute__((unused)),
const uchar *record __attribute__((unused)))
{
return HA_ERR_WRONG_COMMAND;
}
int _ma_read_no_record(MARIA_HA *info __attribute__((unused)),
uchar *record __attribute__((unused)),
MARIA_RECORD_POS pos __attribute__((unused)))
{
return HA_ERR_WRONG_COMMAND;
}
int _ma_read_rnd_no_record(MARIA_HA *info __attribute__((unused)),
uchar *buf __attribute__((unused)),
MARIA_RECORD_POS filepos __attribute__((unused)),
my_bool skip_deleted_blocks __attribute__((unused)))
{
return HA_ERR_WRONG_COMMAND;
}
my_off_t _ma_no_keypos_to_recpos(MARIA_SHARE *share __attribute__ ((unused)),
my_off_t pos __attribute__ ((unused)))
{
return 0;
}
...@@ -1076,6 +1076,20 @@ void _ma_setup_functions(register MARIA_SHARE *share) ...@@ -1076,6 +1076,20 @@ void _ma_setup_functions(register MARIA_SHARE *share)
else else
share->calc_checksum= _ma_checksum; share->calc_checksum= _ma_checksum;
break; break;
case NO_RECORD:
share->read_record= _ma_read_no_record;
share->scan= _ma_read_rnd_no_record;
share->delete_record= _ma_delete_no_record;
share->update_record= _ma_update_no_record;
share->write_record= _ma_write_no_record;
share->recpos_to_keypos= _ma_no_keypos_to_recpos;
share->keypos_to_recpos= _ma_no_keypos_to_recpos;
/* Abort if following functions are called */
share->compare_record= 0;
share->compare_unique= 0;
share->calc_checksum= 0;
break;
case BLOCK_RECORD: case BLOCK_RECORD:
share->once_init= _ma_once_init_block_record; share->once_init= _ma_once_init_block_record;
share->once_end= _ma_once_end_block_record; share->once_end= _ma_once_end_block_record;
......
...@@ -785,6 +785,7 @@ MARIA_RECORD_POS _ma_row_pos_from_key(const MARIA_KEY *key) ...@@ -785,6 +785,7 @@ MARIA_RECORD_POS _ma_row_pos_from_key(const MARIA_KEY *key)
case 4: pos= (my_off_t) mi_uint4korr(after_key); break; case 4: pos= (my_off_t) mi_uint4korr(after_key); break;
case 3: pos= (my_off_t) mi_uint3korr(after_key); break; case 3: pos= (my_off_t) mi_uint3korr(after_key); break;
case 2: pos= (my_off_t) mi_uint2korr(after_key); break; case 2: pos= (my_off_t) mi_uint2korr(after_key); break;
case 0: /* NO_RECORD */
default: default:
pos=0L; /* Shut compiler up */ pos=0L; /* Shut compiler up */
} }
...@@ -894,6 +895,7 @@ void _ma_dpointer(MARIA_SHARE *share, uchar *buff, my_off_t pos) ...@@ -894,6 +895,7 @@ void _ma_dpointer(MARIA_SHARE *share, uchar *buff, my_off_t pos)
case 4: mi_int4store(buff,pos); break; case 4: mi_int4store(buff,pos); break;
case 3: mi_int3store(buff,pos); break; case 3: mi_int3store(buff,pos); break;
case 2: mi_int2store(buff,(uint) pos); break; case 2: mi_int2store(buff,(uint) pos); break;
case 0: break; /* For NO_RECORD */
default: abort(); /* Impossible */ default: abort(); /* Impossible */
} }
} /* _ma_dpointer */ } /* _ma_dpointer */
......
...@@ -409,6 +409,10 @@ static int run_test(const char *filename) ...@@ -409,6 +409,10 @@ static int run_test(const char *filename)
if (!silent) if (!silent)
printf("- Reading rows with key\n"); printf("- Reading rows with key\n");
record[1]= 0; /* For nicer printf */ record[1]= 0; /* For nicer printf */
if (record_type == NO_RECORD)
maria_extra(file, HA_EXTRA_KEYREAD, 0);
for (i=0 ; i <= 25 ; i++) for (i=0 ; i <= 25 ; i++)
{ {
create_key(key,i); create_key(key,i);
...@@ -422,9 +426,15 @@ static int run_test(const char *filename) ...@@ -422,9 +426,15 @@ static int run_test(const char *filename)
(int) key_length,key+offset_to_key,error,my_errno,record+1); (int) key_length,key+offset_to_key,error,my_errno,record+1);
} }
} }
if (record_type == NO_RECORD)
{
maria_extra(file, HA_EXTRA_NO_KEYREAD, 0);
goto end;
}
if (!silent) if (!silent)
printf("- Reading rows with position\n"); printf("- Reading rows with position\n");
if (maria_scan_init(file)) if (maria_scan_init(file))
{ {
fprintf(stderr, "maria_scan_init failed\n"); fprintf(stderr, "maria_scan_init failed\n");
...@@ -757,6 +767,8 @@ static struct my_option my_long_options[] = ...@@ -757,6 +767,8 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"rows-in-block", 'M', "Store rows in block format", {"rows-in-block", 'M', "Store rows in block format",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"rows-no-data", 'n', "Don't store any data, only keys",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"row-pointer-size", 'R', "Undocumented", (uchar**) &rec_pointer_size, {"row-pointer-size", 'R', "Undocumented", (uchar**) &rec_pointer_size,
(uchar**) &rec_pointer_size, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, (uchar**) &rec_pointer_size, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"silent", 's', "Undocumented", {"silent", 's', "Undocumented",
...@@ -816,6 +828,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -816,6 +828,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'M': case 'M':
record_type= BLOCK_RECORD; record_type= BLOCK_RECORD;
break; break;
case 'n':
record_type= NO_RECORD;
break;
case 'S': case 'S':
if (key_field == FIELD_VARCHAR) if (key_field == FIELD_VARCHAR)
{ {
...@@ -887,6 +902,10 @@ static void get_options(int argc, char *argv[]) ...@@ -887,6 +902,10 @@ static void get_options(int argc, char *argv[])
exit(ho_error); exit(ho_error);
if (transactional) if (transactional)
record_type= BLOCK_RECORD; record_type= BLOCK_RECORD;
if (record_type == NO_RECORD)
skip_update= skip_delete= 1;
return; return;
} /* get options */ } /* get options */
......
...@@ -68,7 +68,7 @@ static const char *field_pack[]= ...@@ -68,7 +68,7 @@ static const char *field_pack[]=
static const char *record_formats[]= static const char *record_formats[]=
{ {
"Fixed length", "Packed", "Compressed", "Block", "?" "Fixed length", "Packed", "Compressed", "Block", "No data", "?", "?"
}; };
static const char *bitmap_description[]= static const char *bitmap_description[]=
......
...@@ -871,6 +871,18 @@ extern my_bool _ma_update_static_record(MARIA_HA *, MARIA_RECORD_POS, ...@@ -871,6 +871,18 @@ extern my_bool _ma_update_static_record(MARIA_HA *, MARIA_RECORD_POS,
const uchar *, const uchar *); const uchar *, const uchar *);
extern my_bool _ma_delete_static_record(MARIA_HA *info, const uchar *record); extern my_bool _ma_delete_static_record(MARIA_HA *info, const uchar *record);
extern my_bool _ma_cmp_static_record(MARIA_HA *info, const uchar *record); extern my_bool _ma_cmp_static_record(MARIA_HA *info, const uchar *record);
extern my_bool _ma_write_no_record(MARIA_HA *info, const uchar *record);
extern my_bool _ma_update_no_record(MARIA_HA *info, MARIA_RECORD_POS pos,
const uchar *oldrec, const uchar *record);
extern my_bool _ma_delete_no_record(MARIA_HA *info, const uchar *record);
extern int _ma_read_no_record(MARIA_HA *info, uchar *record,
MARIA_RECORD_POS pos);
extern int _ma_read_rnd_no_record(MARIA_HA *info, uchar *buf,
MARIA_RECORD_POS filepos,
my_bool skip_deleted_blocks);
my_off_t _ma_no_keypos_to_recpos(MARIA_SHARE *share, my_off_t pos);
extern my_bool _ma_ck_write(MARIA_HA *info, MARIA_KEY *key); extern my_bool _ma_ck_write(MARIA_HA *info, MARIA_KEY *key);
extern my_bool _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key, extern my_bool _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key,
MARIA_RECORD_POS *root); MARIA_RECORD_POS *root);
......
...@@ -250,6 +250,7 @@ sub run_check_tests ...@@ -250,6 +250,7 @@ sub run_check_tests
["-p -B --key_length=480","-sm"], ["-p -B --key_length=480","-sm"],
["--checksum --unique","-se"], ["--checksum --unique","-se"],
["--unique","-se"], ["--unique","-se"],
["--rows-no-data", "-s"],
["--key_multiple -N -S","-sm"], ["--key_multiple -N -S","-sm"],
["--key_multiple -a -p --key_length=480","-sm"], ["--key_multiple -a -p --key_length=480","-sm"],
["--key_multiple -a -B --key_length=480","-sm"], ["--key_multiple -a -B --key_length=480","-sm"],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment