summaryrefslogtreecommitdiff
path: root/myisam/mi_create.c
diff options
context:
space:
mode:
Diffstat (limited to 'myisam/mi_create.c')
-rw-r--r--myisam/mi_create.c150
1 files changed, 102 insertions, 48 deletions
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index 19abb9ca745..41c965c7c80 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -16,7 +16,9 @@
/* Create a MyISAM table */
-#include "fulltext.h"
+#include "ftdefs.h"
+#include "sp_defs.h"
+
#if defined(MSDOS) || defined(__WIN__)
#ifdef __WIN__
#include <fcntl.h>
@@ -39,10 +41,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
File dfile,file;
int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
myf create_flag;
- uint fields,length,max_key_length,packed,pointer,
- key_length,info_length,key_segs,options,min_key_length_skipp,
+ uint fields,length,max_key_length,packed,pointer,real_length_diff,
+ key_length,info_length,key_segs,options,min_key_length_skip,
base_pos,varchar_count,long_varchar_count,varchar_length,
- max_key_block_length,unique_key_parts,offset;
+ max_key_block_length,unique_key_parts,fulltext_keys,offset;
ulong reclength, real_reclength,min_pack_length;
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
ulong pack_reclength;
@@ -51,7 +53,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
MYISAM_SHARE share;
MI_KEYDEF *keydef,tmp_keydef;
MI_UNIQUEDEF *uniquedef;
- MI_KEYSEG *keyseg,tmp_keyseg;
+ HA_KEYSEG *keyseg,tmp_keyseg;
MI_COLUMNDEF *rec;
ulong *rec_per_key_part;
my_off_t key_root[MI_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
@@ -192,11 +194,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD));
min_pack_length+=packed;
- if (!ci->data_file_length)
+ if (!ci->data_file_length && ci->max_rows)
{
- if (ci->max_rows == 0 || pack_reclength == INT_MAX32)
- ci->data_file_length= INT_MAX32-1; /* Should be enough */
- else if ((~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength)
+ if (pack_reclength == INT_MAX32 ||
+ (~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength)
ci->data_file_length= ~(ulonglong) 0;
else
ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength;
@@ -207,9 +208,9 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
3 : 0)));
if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))
- pointer=mi_get_pointer_length(ci->data_file_length,4);
+ pointer=mi_get_pointer_length(ci->data_file_length,myisam_data_pointer_size);
else
- pointer=mi_get_pointer_length(ci->max_rows,4);
+ pointer=mi_get_pointer_length(ci->max_rows,myisam_data_pointer_size);
if (!(max_rows=(ulonglong) ci->max_rows))
max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length);
@@ -224,6 +225,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
reclength+=long_varchar_count; /* We need space for this! */
max_key_length=0; tot_length=0 ; key_segs=0;
+ fulltext_keys=0;
max_key_block_length=0;
share.state.rec_per_key_part=rec_per_key_part;
share.state.key_root=key_root;
@@ -236,28 +238,57 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++)
{
- share.state.key_root[i]= HA_OFFSET_ERROR;
- min_key_length_skipp=length=0;
+ share.state.key_root[i]= HA_OFFSET_ERROR;
+ min_key_length_skip=length=real_length_diff=0;
key_length=pointer;
-
- if (keydef->flag & HA_FULLTEXT) /* SerG */
+ if (keydef->flag & HA_SPATIAL)
{
- keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
- options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
+#ifdef HAVE_SPATIAL
+ /* BAR TODO to support 3D and more dimensions in the future */
+ uint sp_segs=SPDIMS*2;
+ keydef->flag=HA_SPATIAL;
if (flags & HA_DONT_TOUCH_DATA)
{
- /* called by myisamchk - i.e. table structure was taken from
- MYI file and FULLTEXT key *do has* additional FT_SEGS keysegs.
- We'd better delete them now
+ /*
+ called by myisamchk - i.e. table structure was taken from
+ MYI file and SPATIAL key *does have* additional sp_segs keysegs.
+ keydef->seg here points right at the GEOMETRY segment,
+ so we only need to decrease keydef->keysegs.
+ (see recreate_table() in mi_check.c)
*/
- keydef->keysegs-=FT_SEGS;
+ keydef->keysegs-=sp_segs-1;
}
for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
j++, keyseg++)
{
+ if (keyseg->type != HA_KEYTYPE_BINARY &&
+ keyseg->type != HA_KEYTYPE_VARBINARY)
+ {
+ my_errno=HA_WRONG_CREATE_OPTION;
+ goto err;
+ }
+ }
+ keydef->keysegs+=sp_segs;
+ key_length+=SPLEN*sp_segs;
+ length++; /* At least one length byte */
+ min_key_length_skip+=SPLEN*2*SPDIMS;
+#else
+ my_errno= HA_ERR_UNSUPPORTED;
+ goto err;
+#endif /*HAVE_SPATIAL*/
+ }
+ else
+ if (keydef->flag & HA_FULLTEXT)
+ {
+ keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
+ options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
+
+ for (j=0, keyseg=keydef->seg ; (int) j < keydef->keysegs ;
+ j++, keyseg++)
+ {
if (keyseg->type != HA_KEYTYPE_TEXT &&
keyseg->type != HA_KEYTYPE_VARTEXT)
{
@@ -265,19 +296,12 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
goto err;
}
}
- keydef->keysegs+=FT_SEGS;
-
- key_length+= HA_FT_MAXLEN+HA_FT_WLEN;
-#ifdef EVAL_RUN
- key_length++;
-#endif
+ fulltext_keys++;
+ key_length+= HA_FT_MAXBYTELEN+HA_FT_WLEN;
length++; /* At least one length byte */
- min_key_length_skipp+=HA_FT_MAXLEN;
-#if HA_FT_MAXLEN >= 255
- min_key_length_skipp+=2; /* prefix may be 3 bytes */
- length+=2;
-#endif
+ min_key_length_skip+=HA_FT_MAXBYTELEN;
+ real_length_diff=HA_FT_MAXBYTELEN-FT_MAX_WORD_LEN_FOR_SORT;
}
else
{
@@ -334,10 +358,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
length++; /* At least one length byte */
- min_key_length_skipp+=keyseg->length;
+ min_key_length_skip+=keyseg->length;
if (keyseg->length >= 255)
{ /* prefix may be 3 bytes */
- min_key_length_skipp+=2;
+ min_key_length_skip+=2;
length+=2;
}
}
@@ -346,10 +370,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
keydef->flag|=HA_VAR_LENGTH_KEY;
length++; /* At least one length byte */
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
- min_key_length_skipp+=keyseg->length;
+ min_key_length_skip+=keyseg->length;
if (keyseg->length >= 255)
{ /* prefix may be 3 bytes */
- min_key_length_skipp+=2;
+ min_key_length_skip+=2;
length+=2;
}
}
@@ -378,7 +402,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
key_segs)
share.state.rec_per_key_part[key_segs-1]=1L;
length+=key_length;
- keydef->block_length= MI_BLOCK_SIZE(length,pointer,MI_MAX_KEYPTR_SIZE);
+ keydef->block_length= MI_BLOCK_SIZE(length-real_length_diff,
+ pointer,MI_MAX_KEYPTR_SIZE);
if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
length >= MI_MAX_KEY_BUFF)
{
@@ -387,7 +412,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
}
set_if_bigger(max_key_block_length,keydef->block_length);
keydef->keylength= (uint16) key_length;
- keydef->minlength= (uint16) (length-min_key_length_skipp);
+ keydef->minlength= (uint16) (length-min_key_length_skip);
keydef->maxlength= (uint16) length;
if (length > max_key_length)
@@ -420,7 +445,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
info_length=base_pos+(uint) (MI_BASE_INFO_SIZE+
keys * MI_KEYDEF_SIZE+
uniques * MI_UNIQUEDEF_SIZE +
- (key_segs + unique_key_parts)*MI_KEYSEG_SIZE+
+ (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
columns*MI_COLUMNDEF_SIZE);
bmove(share.state.header.file_version,(byte*) myisam_file_magic,4);
@@ -433,7 +458,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
mi_int2store(share.state.header.base_info_length,MI_BASE_INFO_SIZE);
mi_int2store(share.state.header.base_pos,base_pos);
share.state.header.language= (ci->language ?
- ci->language : MY_CHARSET_CURRENT);
+ ci->language : default_charset_info->number);
share.state.header.max_block_size=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;
share.state.dellink = HA_OFFSET_ERROR;
@@ -454,8 +479,9 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
*/
share.base.key_reflength=
mi_get_pointer_length(max(ci->key_file_length,tmp),3);
- share.base.keys= share.state.header.keys = keys;
+ share.base.keys= share.state.header.keys= keys;
share.state.header.uniques= uniques;
+ share.state.header.fulltext_keys= fulltext_keys;
mi_int2store(share.state.header.key_parts,key_segs);
mi_int2store(share.state.header.unique_key_parts,unique_key_parts);
@@ -511,6 +537,21 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
create_flag=MY_DELETE_OLD;
}
+ /*
+ If a MRG_MyISAM table is in use, the mapped MyISAM tables are open,
+ but no entry is made in the table cache for them.
+ A TRUNCATE command checks for the table in the cache only and could
+ be fooled to believe, the table is not open.
+ Pull the emergency brake in this situation. (Bug #8306)
+ */
+ if (test_if_reopen(filename))
+ {
+ my_printf_error(0, "MyISAM table '%s' is in use "
+ "(most likely by a MERGE table). Try FLUSH TABLES.",
+ MYF(0), name + dirname_length(name));
+ goto err;
+ }
+
if ((file= my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
MYF(MY_WME | create_flag))) < 0)
goto err;
@@ -568,20 +609,30 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* Write key and keyseg definitions */
for (i=0 ; i < share.base.keys - uniques; i++)
{
- uint ft_segs=(keydefs[i].flag & HA_FULLTEXT) ? FT_SEGS : 0;
+ uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0;
if (mi_keydef_write(file, &keydefs[i]))
goto err;
- for (j=0 ; j < keydefs[i].keysegs-ft_segs ; j++)
+ for (j=0 ; j < keydefs[i].keysegs-sp_segs ; j++)
if (mi_keyseg_write(file, &keydefs[i].seg[j]))
- goto err;
- for (j=0 ; j < ft_segs ; j++)
+ goto err;
+#ifdef HAVE_SPATIAL
+ for (j=0 ; j < sp_segs ; j++)
{
- MI_KEYSEG seg=ft_keysegs[j];
- seg.language= keydefs[i].seg[0].language;
- if (mi_keyseg_write(file, &seg))
+ HA_KEYSEG sseg;
+ sseg.type=SPTYPE;
+ sseg.language= 7;
+ sseg.null_bit=0;
+ sseg.bit_start=0;
+ sseg.bit_end=0;
+ sseg.length=SPLEN;
+ sseg.null_pos=0;
+ sseg.start=j*SPLEN;
+ sseg.flag= HA_SWAP_KEY;
+ if (mi_keyseg_write(file, &sseg))
goto err;
}
+#endif
}
/* Create extra keys for unique definitions */
offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
@@ -674,10 +725,13 @@ err:
uint mi_get_pointer_length(ulonglong file_length, uint def)
{
+ DBUG_ASSERT(def >= 2 && def <= 7);
if (file_length) /* If not default */
{
+#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS
if (file_length >= (longlong) 1 << 56)
def=8;
+#endif
if (file_length >= (longlong) 1 << 48)
def=7;
if (file_length >= (longlong) 1 << 40)