1
0
Files
irix-657m-src/eoe/cmd/sss/ssdb/ssdbserver/sql/handler.cc
2022-09-29 17:59:04 +03:00

1189 lines
31 KiB
C++

/* Copyright (C) 1979-1996 TcX AB & Monty Program KB & Detron HB
This software is distributed with NO WARRANTY OF ANY KIND. No author or
distributor accepts any responsibility for the consequences of using it, or
for whether it serves any particular purpose or works at all, unless he or
she says so in writing. Refer to the Free Public License (the "License")
for full details.
Every copy of this file must include a copy of the License, normally in a
plain ASCII text file named PUBLIC. The License grants you the right to
copy, modify and redistribute this file, but only under certain conditions
described in the License. Among other things, the License requires that
the copyright notice and this notice be preserved on all copies. */
/* Handler-calling-functions */
#include "mysql_priv.h"
#include <errno.h>
#include <nisam.h>
#ifndef NO_MISAM
#include <misam.h>
#else
#define is_open 0 /* Undefine for initarray */
#define is_close 0
#define is_write 0
#define is_update 0
#define is_delete 0
#define is_rkey 0
#define is_rnext 0
#define is_rprev 0
#define is_rfirst 0
#define is_rlast 0
#define is_rsame 0
#define is_rrnd 0
#define is_lock_database 0
#define is_extra 0
#define I_MAXKEY_SEG 5
#endif
#ifndef NO_HEAP
#include <heap.h>
#else
#define heap_open 0 /* Undefine for initarray */
#define heap_close 0
#define heap_write 0
#define heap_update 0
#define heap_delete 0
#define heap_rsame 0
#define heap_rrnd 0
#define heap_extra 0
#define heap_rnext 0
#define heap_rprev 0
#define heap_rfirst 0
#define heap_rlast 0
#define heap_rkey 0
#endif
#ifndef NO_HASH
#include <hashdb.h>
#else
#define h_open 0 /* Undefine for initarray */
#define h_close 0
#define h_write 0
#define h_update 0
#define h_delete 0
#define h_rkey 0
#define h_rnext 0
#define h_rprev 0
#define h_rfirst 0
#define h_rlast 0
#define h_rsame 0
#define h_rrnd 0
#define h_lock_database 0
#define h_extra 0
#endif
#ifndef NO_PISAM
#include <pisam.h>
#else
#define ps_open 0 /* Undefine for initarray */
#define ps_close 0
#define ps_write 0
#define ps_update 0
#define ps_delete 0
#define ps_rkey 0
#define ps_rnext 0
#define ps_rprev 0
#define ps_rfirst 0
#define ps_rlast 0
#define ps_rsame 0
#define ps_rrnd 0
#define ps_lock_database 0
#define ps_extra 0
#endif
#ifdef HAVE_RMS_ISAM
#include <rms_isam.h>
#else
#define rms_open 0 /* Undefine for initarray */
#define rms_close 0
#define rms_write 0
#define rms_update 0
#define rms_delete 0
#define rms_rkey 0
#define rms_rnext 0
#define rms_rprev 0
#define rms_rfirst 0
#define rms_rlast 0
#define rms_rsame 0
#define rms_rrnd 0
#define rms_lock_database 0
#define rms_extra 0
#endif
#ifndef NO_MERGE
#include <merge.h>
#else
#define mrg_open 0 /* Undefine for initarray */
#define mrg_close 0
#define mrg_write 0
#define mrg_update 0
#define mrg_delete 0
#define mrg_rkey 0
#define mrg_rnext 0
#define mrg_rprev 0
#define mrg_rfirst 0
#define mrg_rlast 0
#define mrg_rsame 0
#define mrg_rrnd 0
#define mrg_lock_database 0
#define mrg_extra 0
#endif
/* static functions defined in this file */
static int NEAR_F _ha_open(TABLE *form, my_string name,int mode,
int test_if_locked);
static void NEAR_F set_form_timestamp(byte *record);
static int ha_err(void);
static int ha_ok(void);
static void NEAR_F update_next_number(TABLE *form);
ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
ha_read_key_count, ha_read_first_count, ha_read_next_count, ha_read_rnd_count;
/* Index to functions in different handlers */
typedef int (*F) ();
static int (*funcs[][7])() = {
{ (F) h_open, (F) is_open, (F) ps_open,
(F) rms_open, (F) heap_open, (F) ni_open,
(F) mrg_open },
{ (F) h_close, (F) is_close, (F) ps_close,
(F) rms_close, (F) heap_close, (F) ni_close,
(F) mrg_close },
{ (F) h_write, (F) is_write, (F) ps_write,
(F) rms_write, (F) heap_write, (F) ni_write,
(F) ha_err },
{ (F) h_update, (F) is_update, (F) ps_update,
(F) rms_update, (F) heap_update, (F) ni_update,
(F) mrg_update },
{ (F) h_delete, (F) is_delete, (F) ps_delete,
(F) rms_delete, (F) heap_delete, (F) ni_delete,
(F) mrg_delete },
{ (F) h_rkey, (F) is_rkey, (F) ps_rkey,
(F) rms_rkey, (F) heap_rkey, (F) ni_rkey,
(F) ha_err },
{ (F) h_rnext, (F) is_rnext, (F) ps_rnext,
(F) rms_rnext, (F) heap_rnext, (F) ni_rnext,
(F) ha_err },
{ (F) h_rprev, (F) is_rprev, (F) ps_rprev,
(F) rms_rprev, (F) heap_rprev, (F) ni_rprev,
(F) ha_err },
{ (F) h_rfirst, (F) is_rfirst, (F) ps_rfirst,
(F) rms_rfirst, (F) heap_rfirst, (F) ni_rfirst,
(F) ha_err },
{ (F) h_rlast, (F) is_rlast, (F) ps_rlast,
(F) rms_rlast, (F) heap_rlast, (F) ni_rlast,
(F) ha_err },
#ifdef NOT_NEEDED
{ (F) h_rsame, (F) is_rsame, (F) ps_rsame,
(F) rms_rsame, (F) heap_rsame, (F) ni_rsame,
(F) mrg_rsame },
#else
{ (F) 0, (F) 0, (F) 0,
(F) 0, (F) 0, (F) 0,
(F) 0 },
#endif
{ (F) h_rrnd, (F) is_rrnd, (F) ps_rrnd,
(F) rms_rrnd, (F) heap_rrnd, (F) ni_rrnd,
(F) mrg_rrnd },
{ (F) h_lock_database,(F) is_lock_database, (F) ps_lock_database,
(F) rms_lock_database,(F) ha_ok, (F) ni_lock_database,
(F) mrg_lock_database },
{ (F) h_extra, (F) is_extra, (F) ps_extra,
(F) rms_extra, (F) heap_extra, (F) ni_extra,
(F) mrg_extra },
};
uint NEAR ha_option_flag[] = {
0,
/* DIAB_ISAM */
HA_READ_NEXT+HA_READ_PREV+HA_READ_ORDER+HA_RSAME_NO_INDEX,
/* HASH */
HA_READ_NEXT+HA_READ_PREV+HA_READ_RND_SAME+HA_KEYPOS_TO_RNDPOS+
HA_BINARY_KEYS+HA_WRONG_ASCII_ORDER,
/* M-ISAM */
HA_READ_NEXT+HA_READ_PREV+HA_READ_RND_SAME+HA_KEYPOS_TO_RNDPOS+
HA_READ_ORDER+HA_LASTKEY_ORDER+HA_HAVE_KEYREAD_ONLY+HA_READ_NOT_EXACT_KEY,
/* P-ISAM */
HA_READ_NEXT+HA_READ_PREV+HA_READ_RND_SAME+HA_KEYPOS_TO_RNDPOS+
HA_READ_ORDER+HA_LASTKEY_ORDER+HA_REC_NOT_IN_SEQ+HA_HAVE_KEYREAD_ONLY+
HA_READ_NOT_EXACT_KEY,
/* RMS-ISAM */
HA_READ_NEXT+HA_READ_RND_SAME+HA_KEYPOS_TO_RNDPOS+
HA_READ_ORDER+HA_LASTKEY_ORDER+HA_REC_NOT_IN_SEQ+HA_RSAME_NO_INDEX+
HA_WRONG_ASCII_ORDER+HA_READ_NOT_EXACT_KEY,
/* HEAP */
HA_READ_RND_SAME+HA_NO_INDEX+HA_BINARY_KEYS+HA_WRONG_ASCII_ORDER+
HA_KEYPOS_TO_RNDPOS,
/* ISAM */
HA_READ_NEXT+HA_READ_PREV+HA_READ_RND_SAME+HA_KEYPOS_TO_RNDPOS+
HA_READ_ORDER+HA_LASTKEY_ORDER+HA_HAVE_KEYREAD_ONLY+HA_READ_NOT_EXACT_KEY+
HA_LONGLONG_KEYS+HA_KEYREAD_WRONG_STR,
/* MERGE-ISAM */
HA_READ_RND_SAME+HA_KEYPOS_TO_RNDPOS,
/* MY_ISAM */
HA_READ_NEXT+HA_READ_PREV+HA_READ_RND_SAME+HA_KEYPOS_TO_RNDPOS+
HA_READ_ORDER+HA_LASTKEY_ORDER+HA_HAVE_KEYREAD_ONLY+HA_READ_NOT_EXACT_KEY+
HA_LONGLONG_KEYS+HA_NULL_KEY,
};
#ifndef MI_MAXKEY
#define MI_MAXKEY 0
#define MI_MAXKEY_SEG 0
#define MI_MAX_KEY_LENGTH 0
#endif
uint NEAR ha_maxrecordlength[]=
{ 0,1024,32767,32767,65535,65535,65535,65535,65535,65535};
uint NEAR ha_max_keys[]=
{ 0,MAX_KEY,MAX_KEY,MAX_KEY,MAX_KEY,MAX_KEY,16,N_MAXKEY,0,MI_MAXKEY };
uint NEAR ha_max_key_parts[]=
{ 0,5,5,I_MAXKEY_SEG,5,5,16,N_MAXKEY_SEG,0,MI_MAXKEY_SEG};
uint NEAR ha_max_key_length[]=
{ N_MAX_KEY_LENGTH,N_MAX_KEY_LENGTH,N_MAX_KEY_LENGTH,N_MAX_KEY_LENGTH,
N_MAX_KEY_LENGTH,N_MAX_KEY_LENGTH,65535,N_MAX_KEY_LENGTH,
N_MAX_KEY_LENGTH,MI_MAX_KEY_LENGTH};
char NEAR bas_ext[][2][FN_EXTLEN] = {
{ "","" },
{ ".DAT",".ISM"}, /* ISAM extensions */
{ ".DAT",".HSH"}, /* HASH extensions */
{ ".ISD",".ISM"}, /* M-ISAM extensions */
{ ".PSD",".PSM"}, /* P-ISAM extensions */
{ ".DAT",""}, /* RMS-ISAM extensions */
{ "",""}, /* HEAP extensions */
{ ".ISD",".ISM"},
{ ".MRG",""},
{ ".MYD",".MYM"},
};
/* Open database-handler. Try O_RDONLY if can't open as O_RDWR */
/* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */
int ha_open(TABLE *form, my_string name, int mode, int test_if_locked)
{
int error;
DBUG_ENTER("ha_open");
DBUG_PRINT("enter",("db_type: %d db_stat: %d mode: %d lock_test: %d",
form->db_type, form->db_stat, mode, test_if_locked));
form->file=0 ;
form->db_capabilities=ha_option_flag[form->db_type];
if ((error=_ha_open(form,name,mode,test_if_locked)))
{
if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
(form->db_stat & HA_TRY_READ_ONLY))
{
form->db_stat|=HA_READ_ONLY;
if (!(error=_ha_open(form,name,O_RDONLY,test_if_locked)) &&
errmsg[ERRMAPP])
my_error(ER_OPEN_AS_READONLY,ME_BELL | ME_WAITTOT | ME_COLOUR1,name);
}
}
if (error)
{
my_errno=error; /* Safeguard */
DBUG_PRINT("error",("error: %d errno: %d",error,errno));
}
DBUG_RETURN (error);
} /* ha_open */
/* sub_function to ha_open */
/* Name will be changed !! */
static int NEAR_F _ha_open(register TABLE *form, my_string name, int mode,
int test_if_locked)
{
char name_buff[FN_REFLEN];
form->keyfile_info.ref_length=sizeof(int32); /* Length of ref */
form->locked=F_UNLCK; /* Not locked */
switch (form->db_type) {
#ifndef NO_HEAP
case DB_TYPE_HEAP:
{
if (form->db_stat & (HA_OPEN_KEYFILE+HA_OPEN_RNDFILE+HA_GET_INFO))
{
uint key,part,parts;
HP_KEYDEF *keydef;
HP_KEYSEG *seg;
for (key=parts=0 ; key < form->keys ; key++)
parts+=form->key_info[key].key_parts;
if (!(keydef=(HP_KEYDEF*) my_alloca(form->keys*sizeof(HP_KEYDEF)+
parts*sizeof(HP_KEYSEG))))
return my_errno;
seg=(HP_KEYSEG*) (keydef+form->keys);
for (key=0 ; key < form->keys ; key++)
{
KEY *pos=form->key_info+key;
keydef[key].keysegs=(uint) pos->key_parts;
keydef[key].flag = pos->dupp_key ? 0 : HA_NOSAME;
keydef[key].seg=seg;
for (part=0 ; part < pos->key_parts ; part++)
{
uint flag=pos->key_part[part].key_type;
if (!f_is_packed(flag) &&
f_packtype(flag) == (int) FIELD_TYPE_DECIMAL &&
!(flag & FIELDFLAG_BINARY))
seg->type= (int) HA_KEYTYPE_TEXT;
else
seg->type= (int) HA_KEYTYPE_BINARY;
seg->start=(uint) pos->key_part[part].offset;
seg->length=(uint) pos->key_part[part].length;
seg++;
}
}
form->file=(byte*) heap_open(fn_format(name_buff,name,"","",1+2),mode,
form->keys,keydef,
form->reclength,form->max_records,
form->reloc);
my_afree((gptr) keydef);
ha_info(form,2);
return (!form->file ? errno : 0);
}
}
break;
#endif
case DB_TYPE_MRG_ISAM:
if (form->db_stat == HA_GET_INFO)
{ /* Skipp if not open */
form->db_stat=0; /* because .MRG may be wrong */
break;
}
/* fall through */
case DB_TYPE_MISAM:
case DB_TYPE_HASH:
case DB_TYPE_PISAM:
case DB_TYPE_ISAM:
case DB_TYPE_RMS_ISAM:
{
if (form->db_stat & (HA_OPEN_KEYFILE+HA_OPEN_RNDFILE+HA_GET_INFO))
{
if (!(form->file= (* ((byte *(*)(char *,int,int))
funcs[0][(int) form->db_type-2]))
(fn_format(name_buff,name,"","",2 | 4),mode,test_if_locked)))
return(my_errno ? my_errno : -1);
if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
VOID(ha_extra(form,HA_EXTRA_NO_WAIT_LOCK));
ha_info(form,2);
if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
VOID(ha_extra(form,HA_EXTRA_WAIT_LOCK));
if (form->db_create_options &
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))
form->db_capabilities|=HA_REC_NOT_IN_SEQ;
if (form->db_create_options & HA_OPTION_READ_ONLY_DATA)
form->db_stat|=HA_READ_ONLY;
if (form->db_type != DB_TYPE_MISAM && form->db_type != DB_TYPE_HASH)
form->db_record_offset=form->reclength;
}
}
break;
default:
break;
}
return 0;
}
/* close database */
int ha_close(register TABLE *form)
{
int error=0;
DBUG_ENTER("ha_close");
if (form->db_stat & (HA_OPEN_KEYFILE+HA_OPEN_RNDFILE+HA_GET_INFO))
error= (* ((int (*)(byte*)) (*funcs[1][(int) form->db_type-2])))(form->file);
if (error)
my_error(ER_ERROR_ON_CLOSE,MYF(ME_BELL+ME_WAITTANG),
form->table_name,my_errno);
DBUG_RETURN(error);
} /* ha_close */
/* write to database. Fix timestamp and next_number */
int ha_write(register TABLE *form, byte * buf)
{
register int error=0;
DBUG_ENTER("ha_write");
pthread_mutex_lock(&LOCK_status);
ha_write_count++;
pthread_mutex_unlock(&LOCK_status);
if (form->time_stamp)
set_form_timestamp(buf+form->time_stamp-1);
if (form->next_number_field && buf == form->record[0])
update_next_number(form);
if ((* ((int (*)(char *,byte *))(*funcs[2][(uint) form->db_type-2])))
((char*) form->file,buf))
error=my_errno ? my_errno : -1;
#ifndef DBUG_OFF
if (error && error != HA_ERR_FOUND_DUPP_KEY)
DBUG_PRINT("error",("errno: %d",error));
#endif
DBUG_RETURN (error);
} /* ha_write */
/* update database */
int ha_update(register TABLE *form, byte * old_data, byte * new_data)
{
register int error=0;
DBUG_ENTER("ha_update");
pthread_mutex_lock(&LOCK_status);
ha_update_count++;
pthread_mutex_unlock(&LOCK_status);
if (form->time_stamp)
set_form_timestamp(new_data+form->time_stamp-1);
if ((* ((int (*)(char *,byte*,byte*))(*funcs[3][(uint) form->db_type-2])))
((char*) form->file,old_data,new_data))
error=my_errno ? my_errno : -1;
#ifndef DBUG_OFF
if (error)
DBUG_PRINT("error",("errno: %d",error));
#endif
DBUG_RETURN (error);
} /* ha_update */
/* delete from database */
int ha_delete(register TABLE *form, byte * buf)
{
register int error=0;
DBUG_ENTER("ha_delete");
pthread_mutex_lock(&LOCK_status);
ha_delete_count++;
pthread_mutex_unlock(&LOCK_status);
if ((* ((int (*)(char *,byte*))(*funcs[4][(uint) form->db_type-2])))
((char*) form->file,buf))
error=(my_errno ? my_errno : -1);
#ifndef DBUG_OFF
if (error)
DBUG_PRINT("error",("errno: %d",error));
#endif
DBUG_RETURN (error);
} /* ha_delete */
/* read key in database */
int ha_rkey(register TABLE *form, byte * buf, int inx, byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
reg2 int error=0;
DBUG_ENTER("ha_rkey");
DBUG_PRINT("enter",("form: %lx '%s'",form,form->table_name));
DBUG_PRINT("enter",("index: %d key: '%.*s' key_len: %d flag: %d",
inx,
(key_len ? key_len : form->key_info[inx].key_length),key,
key_len,find_flag));
DBUG_DUMP("key",(char*) key,
(key_len ? key_len : form->key_info[inx].key_length));
pthread_mutex_lock(&LOCK_status);
ha_read_key_count++;
pthread_mutex_unlock(&LOCK_status);
switch (form->db_type) {
#if !defined(NO_HASH) || !defined(NO_HEAP)
case DB_TYPE_HASH:
case DB_TYPE_HEAP:
if ((* ((int (*)(char *,byte *,int,byte*))(*funcs[5][(uint) form->db_type-2])))((char*) form->file,buf,inx,key))
error=my_errno ? my_errno : -1;
break;
#endif
default: /* M_ISAM,PISAM,RMS,ISAM */
if ((* ((int (*)(char *,byte *,int,byte *,uint,int))(*funcs[5][(uint) form->db_type-2])))((char*) form->file,buf,inx,key,key_len,(int) find_flag))
error=my_errno ? my_errno : -1;
break;
}
if (error)
{
DBUG_PRINT((error == HA_ERR_KEY_NOT_FOUND ? "extra_info" : "error"),
("my_errno: %d",error));
form->status=STATUS_NOT_FOUND;
}
else
form->status=0;
DBUG_RETURN (error);
} /* ha_rkey */
/* read next record from database */
int ha_rnext(register TABLE *form, byte * buf, register int inx)
{
reg3 int error=0;
DBUG_ENTER("ha_rnext");
DBUG_PRINT("enter",("form: %lx '%s'",form,form->table_name));
pthread_mutex_lock(&LOCK_status);
ha_read_next_count++;
pthread_mutex_unlock(&LOCK_status);
if ((* ((int (*)(char *,byte *,int))(*funcs[6][(uint) form->db_type-2])))((char*) form->file,buf,inx))
error=(my_errno ? my_errno : HA_ERR_END_OF_FILE);
if (error)
{
DBUG_PRINT((error == HA_ERR_END_OF_FILE ? "extra_info" : "error"),
("my_errno: %d",error));
form->status=STATUS_NOT_FOUND;
}
else
form->status=0;
DBUG_RETURN (error);
} /* ha_rnext */
/* read previous record from database */
int ha_rprev(register TABLE *form, byte * buf, register int inx)
{
reg3 int error=0;
DBUG_ENTER("ha_rprev");
pthread_mutex_lock(&LOCK_status);
ha_read_next_count++;
pthread_mutex_unlock(&LOCK_status);
if ((* ((int (*)(char *,byte *,int))(*funcs[7][(uint) form->db_type-2])))((char*) form->file,buf,inx))
error=my_errno ? my_errno : HA_ERR_END_OF_FILE;
if (error)
{
DBUG_PRINT("error",("my_errno: %d",error));
form->status=STATUS_NOT_FOUND;
}
else
form->status=0;
DBUG_RETURN (error);
} /* ha_rprev */
/* read first record from database */
int ha_rfirst(register TABLE *form, byte * buf, int inx)
{
register int error=0;
DBUG_ENTER("ha_rfirst");
pthread_mutex_lock(&LOCK_status);
ha_read_key_count++;
pthread_mutex_unlock(&LOCK_status);
if ((* ((int (*)(char *,byte *,int))(*funcs[8][(uint) form->db_type-2])))((char*) form->file,buf,inx))
error=my_errno ? my_errno : HA_ERR_END_OF_FILE;
if (error)
{
DBUG_PRINT("error",("my_errno: %d",error));
form->status=STATUS_NOT_FOUND;
}
else
form->status=0;
DBUG_RETURN (error);
} /* ha_rfirst */
/* read last record from database */
int ha_rlast(register TABLE *form, byte * buf, int inx)
{
register int error=0;
DBUG_ENTER("ha_rlast");
pthread_mutex_lock(&LOCK_status);
ha_read_next_count++;
pthread_mutex_unlock(&LOCK_status);
if ((* ((int (*)(char *,byte *,int))(*funcs[9][(uint) form->db_type-2])))((char*)form->file,buf,inx))
error=my_errno ? my_errno : HA_ERR_END_OF_FILE;
if (error)
{
DBUG_PRINT("error",("my_errno: %d",error));
form->status=STATUS_NOT_FOUND;
}
else
form->status=0;
DBUG_RETURN (error);
} /* ha_rlast */
/* read the same record that we read last time */
#ifdef NOT_NEEDED_YET
int ha_rsame(register TABLE *form, byte * buf, int inx)
{
register int error=0;
DBUG_ENTER("ha_rsame");
pthread_mutex_lock(&LOCK_status);
ha_read_key_count++;
pthread_mutex_unlock(&LOCK_status);
if ((* ((int (*)(char *,byte *,int))(*funcs[10][(uint) form->db_type-2])))((char*) form->file,buf,inx))
error=my_errno ? my_errno : -1;
if (error)
{
DBUG_PRINT("error",("my_errno: %d",error));
form->status=STATUS_NOT_FOUND;
}
else
form->status=0;
DBUG_RETURN (error);
} /* ha_rsame */
#endif
/* read the same record that we read last time and fix keys */
#ifdef NOT_NEEDED_YET
int ha_rsame_with_pos(register TABLE *form, byte * buf, int inx, byte *pos)
{
register int error=0;
DBUG_ENTER("ha_rsame_with_pos");
pthread_mutex_lock(&LOCK_status);
ha_read_key_count++;
pthread_mutex_unlock(&LOCK_status);
if (form->db_type == DB_TYPE_ISAM)
{
error=ni_rsame_with_pos((N_INFO*) form->file,buf,inx,
(long) *((uint32*) pos));
#ifndef DBUG_OFF
if (error)
DBUG_PRINT("error",("my_errno: %d",error));
#endif
}
else
{
if (!(error=ha_r_rnd(form,buf,pos)) && inx != -1)
error=ha_rsame(form,buf,inx);
}
if (error)
form->status=STATUS_NOT_FOUND;
else
form->status=0;
DBUG_RETURN (error);
} /* ha_rsame_with_pos */
#endif
/* read a record with rnd-acsess */
/* If pos == NullS find next record */
/* else pos must be get using ha_info() after some read */
/* If ha_r_rnd() = -1 then record is not in database */
int ha_r_rnd(register TABLE *form, byte * buf, byte *pos)
{
int error;
DBUG_ENTER("ha_r_rnd");
pthread_mutex_lock(&LOCK_status);
ha_read_rnd_count++;
pthread_mutex_unlock(&LOCK_status);
#ifdef HAVE_RMS_ISAM
if (form->db_type == DB_TYPE_RMS_ISAM)
{
error= -rms_rrnd((RMS_INFO*) form->file,buf,pos); /* Get 1 if eof */
}
else
#endif
{
DBUG_PRINT("enter",("form: %lx buf: %lx pos: %ld",form,buf,
pos ? (long) *((uint32*) pos) : -1L));
if ((error=(* ((int (*)(char *,byte *,long))(*funcs[11][(uint) form->db_type-2])))((char*) form->file,buf,pos ? (long) *((uint32*) pos) : -1L)))
{
if (error == 1)
error= -1; /* record deleted */
else
error= my_errno > 0 ? my_errno : HA_ERR_END_OF_FILE;
}
}
#ifndef DBUG_OFF
if (error > 0 && error != HA_ERR_END_OF_FILE)
DBUG_PRINT("error",("error: %d my_errno: %d",error,my_errno));
#endif
if (error)
form->status=STATUS_NOT_FOUND;
else
form->status=0;
DBUG_RETURN (error);
} /* ha_r_rnd */
/* L{ser f|rsta recorden fr}n en fil */
/* Detta oberoende hur filen {r |ppnad */
int ha_readfirst(register TABLE *form, byte * buf)
{
register int error;
DBUG_ENTER("ha_readfirst");
pthread_mutex_lock(&LOCK_status);
ha_read_first_count++;
pthread_mutex_unlock(&LOCK_status);
error=0;
if (!(form->db_stat & HA_OPEN_KEYFILE) || form->keys == 0 ||
! (ha_option_flag[form->db_type] & HA_READ_ORDER))
{
ha_reset(form);
while ((error= ha_r_rnd(form,buf,(byte*) NullS)) <0) ;
DBUG_RETURN(error);
}
else
error=ha_rfirst(form,buf,0);
if (error)
form->status=STATUS_NOT_FOUND;
else
form->status=0;
DBUG_RETURN (error);
} /* ha_readfirst */
/* Get KEYFILE_INFO from database */
/* if flag == 1 we only get lastpos */
void ha_info(register TABLE *form, int flag)
{
DBUG_ENTER("ha_info");
switch (form->db_type) {
#ifndef NO_HASH
case DB_TYPE_HASH:
{
HASHINFO info;
VOID(h_info((H_INFO*) form->file,&info,flag));
form->keyfile_info.ref.lastpos = info.h_recpos;
if (flag != 1)
{
form->keyfile_info.records = info.h_ant;
form->keyfile_info.deleted = info.h_delete;
form->keyfile_info.errkey = info.h_errkey;
form->keyfile_info.mean_rec_length=form->reclength;
form->keyfile_info.data_file_length=form->reclength*
(info.h_ant+info.h_delete);
}
}
break;
#endif
#ifndef NO_MISAM
case DB_TYPE_MISAM:
{
ISAMINFO info;
VOID(is_info((I_INFO*) form->file,&info,flag));
form->keyfile_info.ref.lastpos = info.i_recpos;
if (flag != 1)
{
form->keyfile_info.records = info.i_ant;
form->keyfile_info.deleted = info.i_delete;
form->keyfile_info.errkey = info.i_errkey;
form->keyfile_info.mean_rec_length=form->reclength;
form->keyfile_info.data_file_length=form->reclength*
(info.i_ant+info.i_delete);
}
}
break;
#endif
#ifndef NO_PISAM
case DB_TYPE_PISAM:
{
P_ISAMINFO info;
VOID(ps_info((P_INFO*) form->file,&info,flag));
form->keyfile_info.ref.lastpos = info.p_recpos;
if (flag != 1)
{
form->keyfile_info.records = info.p_ant;
form->keyfile_info.deleted = info.p_delete;
form->keyfile_info.errkey = info.p_errkey;
form->keyfile_info.mean_rec_length=form->reclength;
}
}
break;
#endif
#ifdef HAVE_RMS_ISAM
case DB_TYPE_RMS_ISAM:
{
RMSINFO info;
VOID(rms_info((RMS_INFO*) form->file,&info,flag));
memcpy(form->keyfile_info.ref.refpos,info.recpos,RMS_REFLENGTH);
if (flag != 1)
{
form->keyfile_info.records = info.ant;
form->keyfile_info.deleted = info.deleted;
form->keyfile_info.errkey = info.errkey;
form->keyfile_info.ref_length=RMS_REFLENGTH;
form->keyfile_info.mean_rec_length=form->reclength;
}
}
break;
#endif
#ifndef NO_HEAP
case DB_TYPE_HEAP:
{
HEAPINFO info;
VOID(heap_info((HP_INFO *) form->file,&info,flag));
form->keyfile_info.ref.lastpos = info.current_record;
if (flag != 1)
{
form->keyfile_info.records = info.records;
form->keyfile_info.deleted = info.deleted;
form->keyfile_info.errkey = info.errkey;
form->keyfile_info.mean_rec_length=form->reclength;
form->keyfile_info.data_file_length=form->reclength*
(info.records+info.deleted);
}
}
break;
#endif
case DB_TYPE_ISAM:
{
N_ISAMINFO info;
VOID(ni_info((N_INFO*) form->file,&info,flag));
form->keyfile_info.ref.lastpos = info.recpos;
if (flag != 1)
{
form->keyfile_info.records = info.records;
form->keyfile_info.deleted = info.deleted;
form->keyfile_info.data_file_length=info.data_file_length;
form->keyfile_info.errkey = info.errkey;
form->keyfile_info.create_time = info.create_time;
form->keyfile_info.check_time = info.isamchk_time;
form->keyfile_info.update_time = info.update_time;
form->keyfile_info.mean_rec_length=info.mean_reclength;
form->keyfile_info.rec_per_key=info.rec_per_key;
form->keyfile_info.sortkey = info.sortkey;
form->keyfile_info.filenr = info.filenr;
form->keyfile_info.block_size=nisam_block_size;
form->db_create_options = info.options;
/* Set keys in use */
if (form->db_stat & HA_OPEN_KEYFILE)
form->keys = min(form->keys,info.keys);
}
}
break;
case DB_TYPE_MRG_ISAM:
#ifndef NO_MERGE
{
MERGE_INFO info;
VOID(mrg_info((MRG_INFO*) form->file,&info,flag));
form->keyfile_info.ref.lastpos = (ha_rows) info.recpos;
if (flag != 1)
{
form->keyfile_info.records = (ha_rows) info.records;
form->keyfile_info.deleted = (ha_rows) info.deleted;
form->keyfile_info.errkey = info.errkey;
form->keyfile_info.data_file_length=info.data_file_length;
form->db_create_options = info.options;
}
}
#endif
break;
default:
break; /* impossible */
}
DBUG_PRINT("exit",("records: %ld deleted: %ld lastpos: %ld",
form->keyfile_info.records,
form->keyfile_info.deleted,
form->keyfile_info.ref.lastpos));
DBUG_VOID_RETURN;
} /* ha_info */
/* Some extra flags we can use on database */
int ha_extra(TABLE *form, enum ha_extra_function operation)
{
DBUG_ENTER("ha_extra");
DBUG_PRINT("enter",("operation: %d",operation));
if ((specialflag & SPECIAL_SAFE_MODE || test_flags & TEST_NO_EXTRA) &&
(operation == HA_EXTRA_WRITE_CACHE ||
operation == HA_EXTRA_KEYREAD))
DBUG_RETURN(0);
DBUG_RETURN((* ((int (*)(char *,int))(*funcs[13][(uint) form->db_type-2])))
((char*) form->file,(int) operation));
} /* ha_extra */
/* Reset database to state after open */
void ha_reset(TABLE *form)
{
DBUG_ENTER("ha_reset");
VOID((* ((int (*)(char *,int))(*funcs[13][(uint) form->db_type-2])))((char*) form->file,(int) HA_EXTRA_RESET));
DBUG_VOID_RETURN;
} /* ha_reset */
/* Lock a database for reading or writing */
int ha_lock(TABLE *form, int lock_type)
{
int error;
DBUG_ENTER("ha_lock");
if (!(error=(* ((int (*)(char *,int))(*funcs[12][(uint) form->db_type-2])))((char*) form->file,lock_type)))
form->locked=lock_type;
DBUG_RETURN(error);
} /* ha_lock */
/* close, flush or restart databases */
/* Ignore this for other databases than ours */
int ha_panic(enum ha_panic_function flag)
{
int error=0;
#ifndef NO_MERGE
error|=mrg_panic(flag);
#endif
#ifndef NO_HASH
error|=h_panic(flag); /* fix hash */
#endif
#ifndef NO_MISAM
error|=is_panic(flag); /* close m_isam files */
#endif
#ifndef NO_PISAM
error|=ps_panic(flag); /* close p_isam files */
#endif
#ifndef NO_HEAP
error|=heap_panic(flag);
#endif
error|=ni_panic(flag);
return error;
} /* ha_panic */
/* Use key cacheing on all databases */
void ha_key_cache(void)
{
if (keybuff_size)
VOID(init_key_cache(keybuff_size,(uint) (10*4*(IO_SIZE+MALLOC_OVERHEAD))));
} /* ha_key_cache */
/* Print error that we got from handler function */
void ha_error(TABLE *form, int error, myf errflag)
{
int textno=ER_GET_ERRNO;
switch (error) {
case EAGAIN:
textno=ER_FILE_USED;
break;
case ENOENT:
textno=ER_FILE_NOT_FOUND;
break;
case HA_ERR_KEY_NOT_FOUND:
case HA_ERR_NO_ACTIVE_RECORD:
case HA_ERR_END_OF_FILE:
textno=ER_KEY_NOT_FOUND;
break;
case HA_ERR_FOUND_DUPP_KEY:
{
int key_nr=ha_keyerror(form,error);
if (key_nr >= 0)
{
/* Write the dupplicated key in the error message */
char key[MAX_KEY_LENGTH];
String str(key,sizeof(key));
key_unpack(&str,form,(uint) key_nr);
uint max_length=MYSQL_ERRMSG_SIZE-strlen(ER(ER_DUP_ENTRY));
if (str.length() >= max_length)
{
str.length(max_length-4);
str.append("...");
}
my_error(ER_DUP_ENTRY,MYF(0),str.c_ptr(),key_nr+1);
return;
}
textno=ER_DUP_KEY;
break;
}
case HA_ERR_RECORD_CHANGED:
textno=ER_CHECKREAD;
break;
case HA_ERR_CRASHED:
textno=ER_NOT_KEYFILE;
break;
case HA_ERR_OUT_OF_MEM:
textno=ER_OUTOFMEMORY;
break;
case HA_ERR_WRONG_COMMAND:
textno=ER_ILLEGAL_HA;
break;
case HA_ERR_OLD_FILE:
textno=ER_OLD_KEYFILE;
break;
case HA_ERR_UNSUPPORTED:
textno=ER_UNSUPPORTED_EXTENSION;
break;
case HA_ERR_RECORD_FILE_FULL:
textno=ER_RECORD_FILE_FULL;
break;
default:
{
my_error(ER_GET_ERRNO,errflag,error);
return;
}
}
my_error(textno,errflag,form->table_name,error);
} /* ha_error() */
/* Return key if error because of dupplicated keys */
int ha_keyerror(TABLE *form, int error)
{
DBUG_ENTER("ha_keyerror");
form->keyfile_info.errkey = -1;
if (error == HA_ERR_FOUND_DUPP_KEY)
ha_info(form,2);
DBUG_RETURN(form->keyfile_info.errkey);
} /* ha_keyerror */
/* Use other databasehandler if databasehandler is not incompiled */
enum db_type ha_checktype(enum db_type database_type)
{
switch (database_type) {
#ifndef NO_HASH
case DB_TYPE_HASH:
#endif
#ifndef NO_MISAM
case DB_TYPE_MISAM:
#endif
#ifndef NO_PISAM
case DB_TYPE_PISAM:
#endif
#ifdef HAVE_RMS_ISAM
case DB_TYPE_RMS_ISAM:
#endif
#ifndef NO_HEAP
case DB_TYPE_HEAP:
#endif
#ifndef NO_MERGE
case DB_TYPE_MRG_ISAM:
#endif
case DB_TYPE_ISAM:
return (database_type); /* Database exists on system */
default:
break;
}
return(DB_TYPE_ISAM); /* Use this as default */
} /* ha_checktype */
/* rename database (indexfile and datafile) */
int ha_frename(enum db_type base, const char * from, const char * to)
{
DBUG_ENTER("ha_frename");
if ((bas_ext[(uint) base][0][0] &&
rename_file_ext(from,to,bas_ext[(uint) base][0])) ||
(bas_ext[(uint) base][1][0] &&
rename_file_ext(from,to,bas_ext[(uint) base][1])))
DBUG_RETURN(1);
DBUG_RETURN(0);
}
/* dummys for not existing functions */
static int ha_err(void)
{
my_errno=HA_ERR_WRONG_COMMAND;
return -1;
}
static int ha_ok(void)
{
return 0;
}
static int delete_file(my_string name,my_string ext,int extflag)
{
char buff[FN_REFLEN];
VOID(fn_format(buff,name,"",ext,extflag | 4));
return(my_delete(buff,MYF(MY_WME)));
}
int ha_fdelete(enum db_type base,my_string name)
{
DBUG_ENTER("ha_fdelete");
if ((bas_ext[base][0][0] && delete_file(name,bas_ext[base][0],2)) ||
(bas_ext[base][1][0] && delete_file(name,bas_ext[base][1],2)))
DBUG_RETURN(1);
switch (base) {
#ifndef NO_HEAP
case DB_TYPE_HEAP:
{
char buff[FN_REFLEN];
DBUG_RETURN (heap_delete_all(fn_format(buff,name,"","",1+2)));
}
#endif
default:
break;
}
DBUG_RETURN(0);
} /* ha_fdelete */
/* Set a timestamp in record */
static void NEAR_F set_form_timestamp(byte *record)
{
long skr= (long) current_thd->query_start();
longstore(record,skr);
return;
}
/* Updates field with field_type NEXT_NUMBER according to following:
if field = 0 change field to the next free key in database.
*/
static void NEAR_F update_next_number(TABLE *form)
{
longlong nr;
int error;
THD *thd;
DBUG_ENTER("update_next_number");
if (form->next_number_field->val_int() != 0)
DBUG_VOID_RETURN;
thd=current_thd;
if ((nr=thd->next_insert_id))
{
thd->next_insert_id=0; // Clear after use
}
else
{
VOID(ha_extra(form,HA_EXTRA_KEYREAD));
error=ha_rlast(form,form->record[1],(int) form->next_number_index);
if (error)
nr=1;
else
nr=(longlong) form->next_number_field->
val_int_offset(form->rec_buff_length)+1;
VOID(ha_extra(form,HA_EXTRA_NO_KEYREAD));
}
thd->insert_id((ulonglong) nr);
form->next_number_field->store(nr);
DBUG_VOID_RETURN;
}