1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
(at your option) any later version.
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 */
/* Remove all rows from a MARIA table */
/* This clears the status information and truncates files */
#include "maria_def.h"
int maria_delete_all_rows(MARIA_HA *info)
{
uint i;
MARIA_SHARE *share=info->s;
MARIA_STATE_INFO *state=&share->state;
DBUG_ENTER("maria_delete_all_rows");
if (share->options & HA_OPTION_READ_ONLY_DATA)
{
DBUG_RETURN(my_errno=EACCES);
}
/* LOCKTODO take X-lock on table here */
if (_ma_readinfo(info,F_WRLCK,1))
DBUG_RETURN(my_errno);
if (_ma_mark_file_changed(info))
goto err;
info->state->records=info->state->del=state->split=0;
state->dellink = HA_OFFSET_ERROR;
state->sortkey= (ushort) ~0;
info->state->key_file_length=share->base.keystart;
info->state->data_file_length=0;
info->state->empty=info->state->key_empty=0;
info->state->checksum=0;
for (i=share->base.max_key_block_length/MARIA_MIN_KEY_BLOCK_LENGTH ; i-- ; )
state->key_del[i]= HA_OFFSET_ERROR;
for (i=0 ; i < share->base.keys ; i++)
state->key_root[i]= HA_OFFSET_ERROR;
/*
If we are using delayed keys or if the user has done changes to the tables
since it was locked then there may be key blocks in the key cache
*/
flush_key_blocks(share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED);
/*
RECOVERYTODO Log the two chsize and header modifications and force the
log. So that if crash between the two chsize, we finish the work at
Recovery. For this scenario:
"TRUNCATE TABLE t1; DROP TABLE t1; RENAME TABLE t2 to t1; crash;"
Recovery mustn't truncate the new t1, so the log records of TRUNCATE
should be applied only if t1 exists and its ZeroDirtyPagesLSN is smaller
than the records'. See more comments below.
*/
if (my_chsize(info->dfile, 0, 0, MYF(MY_WME)) ||
my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) )
goto err;
/*
RECOVERYTODO Consider updating ZeroDirtyPagesLSN here. It is
not a necessity (it is one only in RENAME commands) but an optional
optimization which will allow some REDO skipping at Recovery.
*/
VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
#ifdef HAVE_MMAP
/* Resize mmaped area */
rw_wrlock(&info->s->mmap_lock);
_ma_remap_file(info, (my_off_t)0);
rw_unlock(&info->s->mmap_lock);
#endif
/*
RECOVERYTODO Until we have the TRUNCATE log record and take it into
account for log-low-water-mark calculation and use it in Recovery, we need
to sync.
*/
if (_ma_sync_table_files(info))
goto err;
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0);
err:
{
int save_errno=my_errno;
/* RECOVERYTODO log the header modifications */
VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
info->update|=HA_STATE_WRITTEN; /* Buffer changed */
/* RECOVERYTODO until we log above we have to sync */
if (_ma_sync_table_files(info) && !save_errno)
save_errno= my_errno;
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(my_errno=save_errno);
}
} /* maria_delete */
|