Below is the list of changes that have just been committed into a local
5.1 repository of mikron. When mikron does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.1846 05/07/13 22:35:34 mronstrom@stripped +97 -0
This change set constitutes the change set for
WL #1354 Basic Partitioning support in MySQL
WL #2493 Move out Fragmentation function from NDB Kernel into NDB API
WL #2497 Map Fragments to Node groups
WL #2505 Handle SHOW CREATE TABLE for partitioning
WL #2507 Handle ALTER TABLE for partitioning
WL #2606 Write test cases for Partitioned Table Implementation in 5.1
Bug #8928 Fixed
The patch contains a number of new files
ha_partition.cc/h a new partition handler with lots of documentation
for the handler interface, this is probably the first handler implementing
the entire handler interface since it is an abstract handler on top
of underlying handlers.
sql_partition.cc a file that contains lots of partitioning code that is
reused also by the NDB partitioning handler that supports partitioning
natively.
Lots of test files and result files
storage/ndb/tools/restore/Restore.cpp
1.27 05/07/13 22:33:47 mikron@stripped +1
-1
Node group handling for NDB partitioning
storage/ndb/test/run-test/README
1.3 05/07/13 22:33:46 mikron@stripped +2 -2
Spell checker
storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
1.35 05/07/13 22:33:46 mikron@stripped +2
-1
Spell checker
storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
1.85 05/07/13 22:33:46 mikron@stripped +30
-12
Spell checker
storage/ndb/src/ndbapi/NdbDictionary.cpp
1.38 05/07/13 22:33:46 mikron@stripped +16
-0
Node Group routines
storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
1.9 05/07/13 22:33:46 mikron@stripped +1 -0
WL 2493
storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
1.19 05/07/13 22:33:46 mikron@stripped +5
-5
Spell checker
storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
1.25 05/07/13 22:33:45 mikron@stripped +1
-1
Spell checker
storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
1.82 05/07/13 22:33:45 mikron@stripped +51
-7
WL 2493
storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
1.30 05/07/13 22:33:45 mikron@stripped +7
-0
WL 2493
storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
1.71 05/07/13 22:33:45 mikron@stripped +2
-2
Spell checker
storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
1.16 05/07/13 22:33:45 mikron@stripped +1
-1
Spell checker
storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
1.35 05/07/13 22:33:44 mikron@stripped +1
-1
Spell checker
storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
1.30 05/07/13 22:33:44 mikron@stripped +156
-120
Changes for new fragmentation schemes for NDB Partitioning
storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
1.10 05/07/13 22:33:44 mikron@stripped +4
-2
New methods for fragmentation
storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
1.13 05/07/13 22:33:44 mikron@stripped +4
-0
Node group storage
storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
1.46 05/07/13 22:33:44 mikron@stripped +30
-7
WL 2493
NDB Partitioning
storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
1.54 05/07/13 22:33:43 mikron@stripped +1
-1
Spell checker
storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
1.15 05/07/13 22:33:43 mikron@stripped +1
-1
Spell checker
storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
1.21 05/07/13 22:33:43 mikron@stripped +1
-1
Spell checker
storage/ndb/src/common/debugger/signaldata/CreateFragmentation.cpp
1.4 05/07/13 22:33:43 mikron@stripped +0 -1
NDB partitioning
storage/ndb/include/ndbapi/NdbDictionary.hpp
1.51 05/07/13 22:33:42 mikron@stripped +11
-0
New methods for setting node groups for fragments
storage/ndb/include/kernel/signaldata/FireTrigOrd.hpp
1.3 05/07/13 22:33:42 mikron@stripped +4 -3
WL 2493 Unique indexes contain fragment id
storage/ndb/include/kernel/signaldata/DictTabInfo.hpp
1.19 05/07/13 22:33:42 mikron@stripped +4
-1
NDB Partitioning
storage/ndb/include/kernel/signaldata/CreateFragmentation.hpp
1.4 05/07/13 22:33:42 mikron@stripped +1 -2
NDB Partitioning
storage/ndb/include/kernel/ndb_limits.h
1.18 05/07/13 22:33:41 mikron@stripped +1
-0
Max partitions also in NDB
storage/ndb/include/kernel/GlobalSignalNumbers.h
1.9 05/07/13 22:33:41 mikron@stripped +1 -1
Spell checker
storage/ndb/include/kernel/AttributeHeader.hpp
1.9 05/07/13 22:33:41 mikron@stripped +2 -2
Spell checker
sql/unireg.h
1.40 05/07/13 22:33:41 mikron@stripped +1
-0
Max number of partitions 1024
sql/unireg.cc
1.62 05/07/13 22:33:41 mikron@stripped +38
-20
Partitioning updates of frm file
sql/tztime.cc
1.25 05/07/13 22:33:40 mikron@stripped +5
-5
Sorted order handling
sql/table.h
1.101 05/07/13 22:33:40 mikron@stripped +7
-0
partitioning additions to table data structures
sql/table.cc
1.172 05/07/13 22:33:40 mikron@stripped +36
-6
New additions to frm file for partitioning
sql/sql_yacc.yy
1.395 05/07/13 22:33:39 mikron@stripped
+430 -10
Big new syntax added for partitioning
sql/sql_update.cc
1.163 05/07/13 22:33:39 mikron@stripped +7
-3
Fix for WL 2445
Partition fields need special care when updated
sql/sql_table.cc
1.254 05/07/13 22:33:39 mikron@stripped
+124 -7
Create Table and Alter Table support for partitioned tables
sql/sql_show.cc
1.255 05/07/13 22:33:39 mikron@stripped +25
-6
SHOW TABLE STATUS for partitioned tables
sql/sql_select.h
1.89 05/07/13 22:33:38 mikron@stripped +1
-0
Sorted order handling
sql/sql_select.cc
1.347 05/07/13 22:33:38 mikron@stripped +44
-19
Sorted order handling
Bug #8928
return code from index_read fixes
sql/sql_lex.h
1.186 05/07/13 22:33:38 mikron@stripped +7
-0
New variable in lex
sql/sql_lex.cc
1.152 05/07/13 22:33:38 mikron@stripped +3
-0
New variable in lex
sql/sql_help.cc
1.46 05/07/13 22:33:37 mikron@stripped +2
-2
Sorted order handling
sql/sql_handler.cc
1.72 05/07/13 22:33:37 mikron@stripped +3
-3
Sorted order handling
sql/sql_base.cc
1.257 05/07/13 22:33:37 mikron@stripped +40
-1
New method for list of fields plus some new code to find fields in
an item tree.
sql/sql_acl.cc
1.148 05/07/13 22:33:37 mikron@stripped +5
-5
Sorted order handling
sql/sp.cc
1.78 05/07/13 22:33:37 mikron@stripped +2
-2
Sorted order handling
sql/share/errmsg.txt
1.35 05/07/13 22:33:36 mikron@stripped +78
-0
Lots of new error messages
Even translated to swedish
sql/set_var.cc
1.122 05/07/13 22:33:36 mikron@stripped +1
-0
New engine
sql/records.cc
1.41 05/07/13 22:33:36 mikron@stripped +68
-0
Comments on methods in records.cc
sql/opt_sum.cc
1.45 05/07/13 22:33:35 mikron@stripped +2
-2
Sorted order handling
sql/opt_range.cc
1.174 05/07/13 22:33:35 mikron@stripped +34
-21
Sorted order handling + return values from index_read
sql/mysqld.cc
1.467 05/07/13 22:33:35 mikron@stripped +18
-0
Some new stuff for NBD partitioning and partitioning in general
sql/mysql_priv.h
1.313 05/07/13 22:33:35 mikron@stripped +18
-1
A few new general methods
sql/lex.h
1.137 05/07/13 22:33:34 mikron@stripped +13
-0
Partitioning keywords added
sql/key.cc
1.35 05/07/13 22:33:34 mikron@stripped +83
-0
New method used for merge sort between handlers in partition handler
Will later be used for similar tasks when parallelising
Tried to optimise and I'm quite satisfied with the solution.
sql/item_subselect.cc
1.111 05/07/13 22:33:34 mikron@stripped +2
-2
Sorted order handling
sql/handler.h
1.147 05/07/13 22:33:34 mikron@stripped
+242 -4
Some adaptions for the partition support
sql/handler.cc
1.178 05/07/13 22:33:34 mikron@stripped +75
-20
Some adaptions for the partition handler
sql/ha_ndbcluster.h
1.88 05/07/13 22:33:34 mikron@stripped +25
-7
NDB Partitioning support
sql/ha_ndbcluster.cc
1.195 05/07/13 22:33:33 mikron@stripped
+336 -135
NDB Partitioning support
sql/ha_innodb.h
1.98 05/07/13 22:33:33 mikron@stripped +1
-1
Introduced sorted flag in index_init
sql/ha_innodb.cc
1.219 05/07/13 22:33:32 mikron@stripped +3
-2
Introduced sorted flag in index_init
sql/ha_federated.h
1.14 05/07/13 22:33:32 mikron@stripped +1
-1
Introduced sorted flag in index_init
sql/ha_federated.cc
1.30 05/07/13 22:33:32 mikron@stripped +3
-3
Introduced sorted flag in index_init
sql/ha_berkeley.h
1.71 05/07/13 22:33:32 mikron@stripped +2
-2
Introduced sorted flag in index_init
sql/ha_berkeley.cc
1.152 05/07/13 22:33:32 mikron@stripped +4
-4
Introduced sorted flag in index_init
sql/field.h
1.164 05/07/13 22:33:32 mikron@stripped +16
-3
A number of changes to field methods for new compare routine
key_rec_cmp
sql/field.cc
1.274 05/07/13 22:33:31 mikron@stripped +38
-4
A number of changes to field methods for new compare routine
key_rec_cmp
sql/Makefile.am
1.111 05/07/13 22:33:31 mikron@stripped +2
-1
Added new header files and code files to make process
mysys/queues.c
1.16 05/07/13 22:33:31 mikron@stripped +388
-12
Some adaptions and improvements of priority queue
mysys/my_bitmap.c
1.32 05/07/13 22:33:30 mikron@stripped +14
-22
Some adaptions and improvements of bitmap
mysys/Makefile.am
1.65 05/07/13 22:33:30 mikron@stripped +3
-0
New build of test program for priority queue
include/queues.h
1.12 05/07/13 22:33:30 mikron@stripped +3
-0
New macros for the priority queue
include/mysql_com.h
1.99 05/07/13 22:33:29 mikron@stripped +2
-0
New field flags
include/my_global.h
1.93 05/07/13 22:33:29 mikron@stripped +88
-0
New macros
configure.in
1.279 05/07/13 22:33:29 mikron@stripped +1
-0
Check for Partitioning
config/ac-macros/ha_ndbcluster.m4
1.7 05/07/13 22:33:29 mikron@stripped +2 -1
Make Partitioning be defined for NDB Cluster
mysql-test/include/have_partition.inc
1.1 05/07/12 10:10:29 mronstrom@stripped +4 -0
mysql-test/include/have_partition.inc
1.0 05/07/12 10:10:29 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/include/have_partition.inc
mysql-test/r/have_partition.require
1.1 05/07/12 10:09:34 mronstrom@stripped +2 -0
mysql-test/r/have_partition.require
1.0 05/07/12 10:09:34 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/r/have_partition.require
mysql-test/r/ndb_partition_key.result
1.1 05/07/11 18:21:34 mronstrom@stripped +71 -0
mysql-test/r/ndb_partition_key.result
1.0 05/07/11 18:21:34 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/r/ndb_partition_key.result
mysql-test/r/ndb_partition_range.result
1.1 05/07/11 18:21:28 mronstrom@stripped +102 -0
mysql-test/r/ndb_partition_range.result
1.0 05/07/11 18:21:28 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/r/ndb_partition_range.result
mysql-test/r/partition_range.result
1.1 05/07/11 18:21:21 mronstrom@stripped +455 -0
mysql-test/r/partition_range.result
1.0 05/07/11 18:21:21 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/r/partition_range.result
mysql-test/r/partition_hash.result
1.1 05/07/11 18:21:12 mronstrom@stripped +66 -0
mysql-test/r/partition_hash.result
1.0 05/07/11 18:21:12 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/r/partition_hash.result
mysql-test/r/partition_list.result
1.1 05/07/11 18:21:06 mronstrom@stripped +342 -0
mysql-test/r/partition_list.result
1.0 05/07/11 18:21:05 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/r/partition_list.result
mysql-test/r/partition_order.result
1.1 05/07/11 18:20:59 mronstrom@stripped +733 -0
mysql-test/r/partition_order.result
1.0 05/07/11 18:20:59 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/r/partition_order.result
mysql-test/r/partition.result
1.1 05/07/11 18:20:53 mronstrom@stripped +355 -0
mysql-test/r/partition.result
1.0 05/07/11 18:20:53 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/r/partition.result
mysql-test/t/ndb_partition_key.test
1.1 05/07/11 18:20:14 mronstrom@stripped +58 -0
mysql-test/t/ndb_partition_key.test
1.0 05/07/11 18:20:14 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/t/ndb_partition_key.test
mysql-test/t/ndb_partition_range.test
1.1 05/07/11 18:20:04 mronstrom@stripped +85 -0
mysql-test/t/ndb_partition_range.test
1.0 05/07/11 18:20:04 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/t/ndb_partition_range.test
mysql-test/t/partition_range.test
1.1 05/07/11 18:19:22 mronstrom@stripped +560 -0
mysql-test/t/partition_range.test
1.0 05/07/11 18:19:22 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/t/partition_range.test
mysql-test/t/partition_list.test
1.1 05/07/11 18:19:16 mronstrom@stripped +316 -0
mysql-test/t/partition_list.test
1.0 05/07/11 18:19:16 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/t/partition_list.test
mysql-test/t/partition_order.test
1.1 05/07/11 18:19:07 mronstrom@stripped +828 -0
mysql-test/t/partition_order.test
1.0 05/07/11 18:19:07 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/t/partition_order.test
mysql-test/t/partition_hash.test
1.1 05/07/11 18:19:02 mronstrom@stripped +77 -0
mysql-test/t/partition_hash.test
1.0 05/07/11 18:19:02 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/t/partition_hash.test
mysql-test/t/partition.test
1.1 05/07/11 18:18:54 mronstrom@stripped +494 -0
mysql-test/t/partition.test
1.0 05/07/11 18:18:54 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/mysql-test/t/partition.test
sql/sql_partition.cc
1.1 05/07/11 18:17:24 mronstrom@stripped +3101 -0
sql/sql_partition.cc
1.0 05/07/11 18:17:24 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/sql/sql_partition.cc
sql/ha_partition.cc
1.1 05/07/11 18:17:16 mronstrom@stripped +3162 -0
sql/ha_partition.cc
1.0 05/07/11 18:17:15 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/sql/ha_partition.cc
sql/ha_partition.h
1.1 05/07/11 18:17:11 mronstrom@stripped +916 -0
sql/ha_partition.h
1.0 05/07/11 18:17:11 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/sql/ha_partition.h
config/ac-macros/ha_partition.m4
1.1 05/07/11 14:56:03 mronstrom@stripped +30 -0
config/ac-macros/ha_partition.m4
1.0 05/07/11 14:56:03 mronstrom@stripped +0 -0
BitKeeper file /Users/mikron/wl1354/config/ac-macros/ha_partition.m4
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: mronstrom
# Host: c-6308e253.1238-1-64736c10.cust.bredbandsbolaget.se
# Root: /Users/mikron/wl1354
--- 1.278/configure.in 2005-06-22 16:12:28 +02:00
+++ 1.279/configure.in 2005-07-13 22:33:29 +02:00
@@ -2437,6 +2437,7 @@
MYSQL_CHECK_BLACKHOLEDB
MYSQL_CHECK_NDBCLUSTER
MYSQL_CHECK_FEDERATED
+MYSQL_CHECK_PARTITIONDB
# If we have threads generate some library functions and test programs
sql_server_dirs=
--- 1.98/include/mysql_com.h 2005-06-17 21:26:17 +02:00
+++ 1.99/include/mysql_com.h 2005-07-13 22:33:29 +02:00
@@ -88,6 +88,8 @@
#define GROUP_FLAG 32768 /* Intern: Group field */
#define UNIQUE_FLAG 65536 /* Intern: Used by sql_yacc */
#define BINCMP_FLAG 131072 /* Intern: Used by sql_yacc */
+#define GET_FIXED_FIELDS_FLAG (1 << 18) /* Used to get fields in item tree */
+#define FIELD_IN_PART_FUNC_FLAG (1 << 19)/* Field part of partition func */
#define REFRESH_GRANT 1 /* Refresh grant tables */
#define REFRESH_LOG 2 /* Start on new log file */
--- 1.11/include/queues.h 2004-11-21 09:50:20 +01:00
+++ 1.12/include/queues.h 2005-07-13 22:33:30 +02:00
@@ -41,6 +41,9 @@
#define queue_element(queue,index) ((queue)->root[index+1])
#define queue_end(queue) ((queue)->root[(queue)->elements])
#define queue_replaced(queue) _downheap(queue,1)
+#define queue_set_cmp_arg(queue, set_arg) (queue)->first_cmp_arg= set_arg
+#define queue_set_max_at_top(queue, set_arg) \
+ (queue)->max_at_top= set_arg ? (-1 ^ 1) : 0
typedef int (*queue_compare)(void *,byte *, byte *);
int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
--- 1.64/mysys/Makefile.am 2005-06-07 18:17:03 +02:00
+++ 1.65/mysys/Makefile.am 2005-07-13 22:33:30 +02:00
@@ -83,6 +83,9 @@
test_bitmap$(EXEEXT): my_bitmap.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN ./my_bitmap.c $(LDADD) $(LIBS)
+test_priority_queue$(EXEEXT): queues.c $(LIBRARIES)
+ $(LINK) $(FLAGS) -DMAIN ./queues.c $(LDADD) $(LIBS)
+
test_thr_alarm$(EXEEXT): thr_alarm.c $(LIBRARIES)
$(CP) $(srcdir)/thr_alarm.c ./test_thr_alarm.c
$(LINK) $(FLAGS) -DMAIN ./test_thr_alarm.c $(LDADD) $(LIBS)
--- 1.15/mysys/queues.c 2003-10-16 02:08:36 +02:00
+++ 1.16/mysys/queues.c 2005-07-13 22:33:31 +02:00
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (C) 2000, 2005 MySQL 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
@@ -17,6 +17,10 @@
/*
Code for generell handling of priority Queues.
Implemention of queues from "Algoritms in C" by Robert Sedgewick.
+ An optimisation of _downheap suggested in Exercise 7.51 in "Data
+ Structures & Algorithms in C++" by Mark Allen Weiss, Second Edition
+ was implemented by Mikael Ronström 2005. Also the O(N) algorithm
+ of queue_fix was implemented.
*/
#include "mysys_priv.h"
@@ -214,11 +218,67 @@
}
#endif
- /* Fix heap when index have changed */
+#ifndef OLD_VERSION
void _downheap(register QUEUE *queue, uint idx)
{
byte *element;
+ uint elements,half_queue,offset_to_key, next_index;
+ bool first= TRUE;
+ uint start_idx= idx;
+
+ offset_to_key=queue->offset_to_key;
+ element=queue->root[idx];
+ half_queue=(elements=queue->elements) >> 1;
+
+ while (idx <= half_queue)
+ {
+ int cmp;
+ next_index=idx+idx;
+ if (next_index < elements &&
+ (queue->compare(queue->first_cmp_arg,
+ queue->root[next_index]+offset_to_key,
+ queue->root[next_index+1]+offset_to_key) ^
+ queue->max_at_top) > 0)
+ next_index++;
+ if (first &&
+ (((cmp=queue->compare(queue->first_cmp_arg,
+ queue->root[next_index]+offset_to_key,
+ element+offset_to_key)) == 0) ||
+ ((cmp ^ queue->max_at_top) > 0)))
+ {
+ queue->root[idx]= element;
+ return;
+ }
+ queue->root[idx]=queue->root[next_index];
+ idx=next_index;
+ first= FALSE;
+ }
+
+ next_index= idx >> 1;
+ while (next_index > start_idx)
+ {
+ if ((queue->compare(queue->first_cmp_arg,
+ queue->root[next_index]+offset_to_key,
+ element+offset_to_key) ^
+ queue->max_at_top) < 0)
+ break;
+ queue->root[idx]=queue->root[next_index];
+ idx=next_index;
+ next_index= idx >> 1;
+ }
+ queue->root[idx]=element;
+}
+
+#else
+ /*
+ The old _downheap version is kept for comparisons with the benchmark
+ suit or new benchmarks anyone wants to run for comparisons.
+ */
+ /* Fix heap when index have changed */
+void _downheap(register QUEUE *queue, uint idx)
+{
+ byte *element;
uint elements,half_queue,next_index,offset_to_key;
int cmp;
@@ -247,20 +307,336 @@
}
-static int queue_fix_cmp(QUEUE *queue, void **a, void **b)
-{
- return queue->compare(queue->first_cmp_arg,
- (byte*) (*a)+queue->offset_to_key,
- (byte*) (*b)+queue->offset_to_key);
-}
+#endif
/*
- Fix heap when every element was changed,
- actually, it can be done better, in linear time, not in n*log(n)
+ Fix heap when every element was changed.
*/
void queue_fix(QUEUE *queue)
{
- qsort2(queue->root+1,queue->elements, sizeof(void *),
- (qsort2_cmp)queue_fix_cmp, queue);
+ uint i;
+ for (i= queue->elements >> 1; i > 0; i--)
+ _downheap(queue, i);
+}
+
+#ifdef MAIN
+ /*
+ A test program for the priority queue implementation.
+ It can also be used to benchmark changes of the implementation
+ Build by doing the following in the directory mysys
+ make test_priority_queue
+ ./test_priority_queue
+
+ Written by Mikael Ronström, 2005
+ */
+
+static uint num_array[1025];
+static uint tot_no_parts= 0;
+static uint tot_no_loops= 0;
+static uint expected_part= 0;
+static uint expected_num= 0;
+static bool max_ind= 0;
+static bool fix_used= 0;
+static ulonglong start_time= 0;
+
+static bool is_divisible_by(uint num, uint divisor)
+{
+ uint quotient= num / divisor;
+ if (quotient * divisor == num)
+ return TRUE;
+ return FALSE;
+}
+
+void calculate_next()
+{
+ uint part= expected_part, num= expected_num;
+ uint no_parts= tot_no_parts;
+ if (max_ind)
+ {
+ do
+ {
+ while (++part <= no_parts)
+ {
+ if (is_divisible_by(num, part) &&
+ (num <= ((1 << 21) + part)))
+ {
+ expected_part= part;
+ expected_num= num;
+ return;
+ }
+ }
+ part= 0;
+ } while (--num);
+ }
+ else
+ {
+ do
+ {
+ while (--part > 0)
+ {
+ if (is_divisible_by(num, part))
+ {
+ expected_part= part;
+ expected_num= num;
+ return;
+ }
+ }
+ part= no_parts + 1;
+ } while (++num);
+ }
}
+
+void calculate_end_next(uint part)
+{
+ uint no_parts= tot_no_parts, num;
+ num_array[part]= 0;
+ if (max_ind)
+ {
+ expected_num= 0;
+ for (part= no_parts; part > 0 ; part--)
+ {
+ if (num_array[part])
+ {
+ num= num_array[part] & 0x3FFFFF;
+ if (num >= expected_num)
+ {
+ expected_num= num;
+ expected_part= part;
+ }
+ }
+ }
+ if (expected_num == 0)
+ expected_part= 0;
+ }
+ else
+ {
+ expected_num= 0xFFFFFFFF;
+ for (part= 1; part <= no_parts; part++)
+ {
+ if (num_array[part])
+ {
+ num= num_array[part] & 0x3FFFFF;
+ if (num <= expected_num)
+ {
+ expected_num= num;
+ expected_part= part;
+ }
+ }
+ }
+ if (expected_num == 0xFFFFFFFF)
+ expected_part= 0;
+ }
+ return;
+}
+static int test_compare(void *null_arg, byte *a, byte *b)
+{
+ uint a_num= (*(uint*)a) & 0x3FFFFF;
+ uint b_num= (*(uint*)b) & 0x3FFFFF;
+ uint a_part, b_part;
+ if (a_num > b_num)
+ return +1;
+ if (a_num < b_num)
+ return -1;
+ a_part= (*(uint*)a) >> 22;
+ b_part= (*(uint*)b) >> 22;
+ if (a_part < b_part)
+ return +1;
+ if (a_part > b_part)
+ return -1;
+ return 0;
+}
+
+bool check_num(uint num_part)
+{
+ uint part= num_part >> 22;
+ uint num= num_part & 0x3FFFFF;
+ if (part == expected_part)
+ if (num == expected_num)
+ return FALSE;
+ printf("Expect part %u Expect num 0x%x got part %u num 0x%x max_ind %u fix_used %u \n",
+ expected_part, expected_num, part, num, max_ind, fix_used);
+ return TRUE;
+}
+
+
+void perform_insert(QUEUE *queue)
+{
+ uint i= 1, no_parts= tot_no_parts;
+ uint backward_start= 0;
+
+ expected_part= 1;
+ expected_num= 1;
+
+ if (max_ind)
+ backward_start= 1 << 21;
+
+ do
+ {
+ uint num= (i + backward_start);
+ if (max_ind)
+ {
+ while (!is_divisible_by(num, i))
+ num--;
+ if (max_ind && (num > expected_num ||
+ (num == expected_num && i < expected_part)))
+ {
+ expected_num= num;
+ expected_part= i;
+ }
+ }
+ num_array[i]= num + (i << 22);
+ if (fix_used)
+ queue_element(queue, i-1)= (byte*)&num_array[i];
+ else
+ queue_insert(queue, (byte*)&num_array[i]);
+ } while (++i <= no_parts);
+ if (fix_used)
+ {
+ queue->elements= no_parts;
+ queue_fix(queue);
+ }
+}
+
+bool perform_ins_del(QUEUE *queue, bool max_ind)
+{
+ uint i= 0, no_loops= tot_no_loops, j= tot_no_parts;
+ do
+ {
+ uint num_part= *(uint*)queue_top(queue);
+ uint part= num_part >> 22;
+ if (check_num(num_part))
+ return TRUE;
+ if (j++ >= no_loops)
+ {
+ calculate_end_next(part);
+ queue_remove(queue, (uint) 0);
+ }
+ else
+ {
+ calculate_next();
+ if (max_ind)
+ num_array[part]-= part;
+ else
+ num_array[part]+= part;
+ queue_top(queue)= (byte*)&num_array[part];
+ queue_replaced(queue);
+ }
+ } while (++i < no_loops);
+ return FALSE;
+}
+
+bool do_test(uint no_parts, uint l_max_ind, bool l_fix_used)
+{
+ QUEUE queue;
+ bool result;
+ max_ind= l_max_ind;
+ fix_used= l_fix_used;
+ init_queue(&queue, no_parts, 0, max_ind, test_compare, NULL);
+ tot_no_parts= no_parts;
+ tot_no_loops= 1024;
+ perform_insert(&queue);
+ if ((result= perform_ins_del(&queue, max_ind)))
+ delete_queue(&queue);
+ if (result)
+ {
+ printf("Error\n");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void start_measurement()
+{
+ start_time= my_getsystime();
+}
+
+static void stop_measurement()
+{
+ ulonglong stop_time= my_getsystime();
+ uint time_in_micros;
+ stop_time-= start_time;
+ stop_time/= 10; /* Convert to microseconds */
+ time_in_micros= (uint)stop_time;
+ printf("Time expired is %u microseconds \n", time_in_micros);
+}
+
+static void benchmark_test()
+{
+ QUEUE queue_real;
+ QUEUE *queue= &queue_real;
+ uint i, add;
+ fix_used= TRUE;
+ max_ind= FALSE;
+ tot_no_parts= 1024;
+ init_queue(queue, tot_no_parts, 0, max_ind, test_compare, NULL);
+ /*
+ First benchmark whether queue_fix is faster than using queue_insert
+ for sizes of 16 partitions.
+ */
+ for (tot_no_parts= 2, add=2; tot_no_parts < 128;
+ tot_no_parts+= add, add++)
+ {
+ printf("Start benchmark queue_fix, tot_no_parts= %u \n", tot_no_parts);
+ start_measurement();
+ for (i= 0; i < 128; i++)
+ {
+ perform_insert(queue);
+ queue_remove_all(queue);
+ }
+ stop_measurement();
+
+ fix_used= FALSE;
+ printf("Start benchmark queue_insert\n");
+ start_measurement();
+ for (i= 0; i < 128; i++)
+ {
+ perform_insert(queue);
+ queue_remove_all(queue);
+ }
+ stop_measurement();
+ }
+ /*
+ Now benchmark insertion and deletion of 16400 elements.
+ Used in consecutive runs this shows whether the optimised _downheap
+ is faster than the standard implementation.
+ */
+ printf("Start benchmarking _downheap \n");
+ start_measurement();
+ perform_insert(queue);
+ for (i= 0; i < 65536; i++)
+ {
+ uint num, part;
+ num= *(uint*)queue_top(queue);
+ num+= 16;
+ part= num >> 22;
+ num_array[part]= num;
+ queue_top(queue)= (byte*)&num_array[part];
+ queue_replaced(queue);
+ }
+ for (i= 0; i < 16; i++)
+ queue_remove(queue, (uint) 0);
+ queue_remove_all(queue);
+ stop_measurement();
+}
+
+int main()
+{
+ int i, add= 1;
+ for (i= 1; i < 1024; i+=add, add++)
+ {
+ printf("Start test for priority queue of size %u\n", i);
+ if (do_test(i, 0, 1))
+ return -1;
+ if (do_test(i, 1, 1))
+ return -1;
+ if (do_test(i, 0, 0))
+ return -1;
+ if (do_test(i, 1, 0))
+ return -1;
+ }
+ benchmark_test();
+ printf("OK\n");
+ return 0;
+}
+#endif
--- 1.110/sql/Makefile.am 2005-06-21 07:52:30 +02:00
+++ 1.111/sql/Makefile.am 2005-07-13 22:33:31 +02:00
@@ -63,7 +63,7 @@
parse_file.h sql_view.h sql_trigger.h \
examples/ha_example.h examples/ha_archive.h \
examples/ha_tina.h ha_blackhole.h \
- ha_federated.h
+ ha_federated.h ha_partition.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
@@ -100,6 +100,7 @@
sp_cache.cc parse_file.cc sql_trigger.cc \
examples/ha_example.cc examples/ha_archive.cc \
examples/ha_tina.cc ha_blackhole.cc \
+ ha_partition.cc sql_partition.cc \
ha_federated.cc
gen_lex_hash_SOURCES = gen_lex_hash.cc
--- 1.273/sql/field.cc 2005-06-22 16:12:28 +02:00
+++ 1.274/sql/field.cc 2005-07-13 22:33:31 +02:00
@@ -6298,7 +6298,7 @@
}
-int Field_varstring::cmp(const char *a_ptr, const char *b_ptr)
+int Field_varstring::cmp(const char *a_ptr, const char *b_ptr, uint max_len)
{
uint a_length, b_length;
int diff;
@@ -6313,6 +6313,8 @@
a_length= uint2korr(a_ptr);
b_length= uint2korr(b_ptr);
}
+ set_if_smaller(a_length, max_len);
+ set_if_smaller(b_length, max_len);
diff= field_charset->coll->strnncollsp(field_charset,
(const uchar*) a_ptr+
length_bytes,
@@ -6938,13 +6940,16 @@
}
-int Field_blob::cmp(const char *a_ptr, const char *b_ptr)
+int Field_blob::cmp(const char *a_ptr, const char *b_ptr,
+ uint max_length)
{
char *blob1,*blob2;
memcpy_fixed(&blob1,a_ptr+packlength,sizeof(char*));
memcpy_fixed(&blob2,b_ptr+packlength,sizeof(char*));
- return Field_blob::cmp(blob1,get_length(a_ptr),
- blob2,get_length(b_ptr));
+ uint a_len= get_length(a_ptr), b_len= get_length(b_ptr);
+ set_if_smaller(a_len, max_length);
+ set_if_smaller(b_len, max_length);
+ return Field_blob::cmp(blob1,a_len,blob2,b_len);
}
@@ -7958,6 +7963,35 @@
{
int2my_decimal(E_DEC_FATAL_ERROR, val_int(), 1, deciaml_value);
return deciaml_value;
+}
+
+
+/*
+ Compare two bit fields using pointers within the record.
+ SYNOPSIS
+ cmp()
+ a Pointer to field->ptr in first record
+ b Pointer to field->ptr in second record
+ max_len Maximum length used in index
+ DESCRIPTION
+ This method is used from key_rec_cmp used by merge sorts used
+ by partitioned index read and later other similar places.
+ The a and b pointer must be pointers to the field in a record
+ (not the table->record[0] necessarily)
+*/
+int Field_bit::cmp(const char *a, const char *b, uint max_len)
+{
+ my_ptrdiff_t a_diff= a - ptr;
+ my_ptrdiff_t b_diff= b - ptr;
+ if (bit_len)
+ {
+ int flag;
+ uchar bits_a= get_rec_bits(bit_ptr+a_diff, bit_ofs, bit_len);
+ uchar bits_b= get_rec_bits(bit_ptr+b_diff, bit_ofs, bit_len);
+ if ((flag= (int) (bits_a - bits_b)))
+ return flag;
+ }
+ return memcmp(a, b, field_length);
}
--- 1.163/sql/field.h 2005-06-21 07:52:30 +02:00
+++ 1.164/sql/field.h 2005-07-13 22:33:32 +02:00
@@ -86,7 +86,7 @@
utype unireg_check;
uint32 field_length; // Length of field
- uint16 flags;
+ uint32 flags;
/* fieldnr is the id of the field (first field = 1) as is also
used in key_part.
*/
@@ -153,6 +153,8 @@
virtual enum_field_types type() const =0;
virtual enum_field_types real_type() const { return type(); }
inline int cmp(const char *str) { return cmp(ptr,str); }
+ virtual int cmp(const char *a, const char *b, uint max_len)
+ { return cmp(a, b); }
virtual int cmp(const char *,const char *)=0;
virtual int cmp_binary(const char *a,const char *b, uint32 max_length=~0L)
{ return memcmp(a,b,pack_length()); }
@@ -1058,7 +1060,11 @@
longlong val_int(void);
String *val_str(String*,String *);
my_decimal *val_decimal(my_decimal *);
- int cmp(const char *,const char*);
+ int cmp(const char *, const char *, uint max_length);
+ int cmp(const char *a,const char*b)
+ {
+ return cmp(a, b, ~0);
+ }
void sort_string(char *buff,uint length);
void get_key_image(char *buff,uint length, imagetype type);
void set_key_image(char *buff,uint length);
@@ -1114,7 +1120,9 @@
longlong val_int(void);
String *val_str(String*,String *);
my_decimal *val_decimal(my_decimal *);
- int cmp(const char *,const char*);
+ int cmp(const char *, const char *, uint max_length);
+ int cmp(const char *a,const char*b)
+ { return cmp(a, b, ~0); }
int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
int cmp_binary(const char *a,const char *b, uint32 max_length=~0L);
int key_cmp(const byte *,const byte*);
@@ -1138,6 +1146,10 @@
{
memcpy_fixed(str,ptr+packlength,sizeof(char*));
}
+ inline void get_ptr(char **str, uint row_offset)
+ {
+ memcpy_fixed(str,ptr+packlength+row_offset,sizeof(char*));
+ }
inline void set_ptr(char *length,char *data)
{
memcpy(ptr,length,packlength);
@@ -1306,6 +1318,7 @@
my_decimal *val_decimal(my_decimal *);
int cmp(const char *a, const char *b)
{ return cmp_binary(a, b); }
+ int cmp(const char *a, const char *b, uint max_length);
int key_cmp(const byte *a, const byte *b)
{ return cmp_binary((char *) a, (char *) b); }
int key_cmp(const byte *str, uint length);
--- 1.151/sql/ha_berkeley.cc 2005-06-09 15:48:47 +02:00
+++ 1.152/sql/ha_berkeley.cc 2005-07-13 22:33:32 +02:00
@@ -1360,7 +1360,7 @@
}
-int ha_berkeley::index_init(uint keynr)
+int ha_berkeley::index_init(uint keynr, bool sorted)
{
int error;
DBUG_ENTER("ha_berkeley::index_init");
@@ -1638,7 +1638,7 @@
{
DBUG_ENTER("rnd_init");
current_row.flags=DB_DBT_REALLOC;
- DBUG_RETURN(index_init(primary_key));
+ DBUG_RETURN(index_init(primary_key, 0));
}
int ha_berkeley::rnd_end()
@@ -2146,7 +2146,7 @@
(void) ha_berkeley::extra(HA_EXTRA_KEYREAD);
/* Set 'active_index' */
- ha_berkeley::index_init(table->s->next_number_index);
+ ha_berkeley::index_init(table->s->next_number_index, 0);
if (!table->s->next_number_key_offset)
{ // Autoincrement at key-start
@@ -2485,7 +2485,7 @@
if (!(share->status & STATUS_PRIMARY_KEY_INIT))
{
(void) extra(HA_EXTRA_KEYREAD);
- index_init(primary_key);
+ index_init(primary_key, 0);
if (!index_last(table->record[1]))
share->auto_ident=uint5korr(current_ident);
index_end();
--- 1.70/sql/ha_berkeley.h 2005-05-09 11:26:46 +02:00
+++ 1.71/sql/ha_berkeley.h 2005-07-13 22:33:32 +02:00
@@ -98,7 +98,7 @@
const char **bas_ext() const;
ulong table_flags(void) const { return int_table_flags; }
uint max_supported_keys() const { return MAX_KEY-1; }
- uint extra_rec_buf_length() { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; }
+ uint extra_rec_buf_length() const { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; }
ha_rows estimate_rows_upper_bound();
const key_map *keys_to_use_for_scanning() { return &key_map_full; }
bool has_transactions() { return 1;}
@@ -109,7 +109,7 @@
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
- int index_init(uint index);
+ int index_init(uint index, bool sorted);
int index_end();
int index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
--- 1.177/sql/handler.cc 2005-06-18 09:21:47 +02:00
+++ 1.178/sql/handler.cc 2005-07-13 22:33:34 +02:00
@@ -34,6 +34,9 @@
#ifdef HAVE_EXAMPLE_DB
#include "examples/ha_example.h"
#endif
+#ifdef HAVE_PARTITION_DB
+#include "ha_partition.h"
+#endif
#ifdef HAVE_ARCHIVE_DB
#include "examples/ha_archive.h"
#endif
@@ -170,7 +173,13 @@
{
if (ha_storage_engine_is_enabled(database_type))
return database_type;
-
+#ifdef HAVE_PARTITION_DB
+ /*
+ Partition handler is not in the list of handlers shown since it is an internal
handler
+ */
+ if (database_type == DB_TYPE_PARTITION_DB)
+ return database_type;
+#endif
if (no_substitute)
{
if (report_error)
@@ -236,6 +245,13 @@
file= new ha_example(table);
break;
#endif
+#ifdef HAVE_PARTITION_DB
+ case DB_TYPE_PARTITION_DB:
+ {
+ file= new ha_partition(table);
+ break;
+ }
+#endif
#ifdef HAVE_ARCHIVE_DB
case DB_TYPE_ARCHIVE_DB:
file= new ha_archive(table);
@@ -290,6 +306,29 @@
return file;
}
+
+#ifdef HAVE_PARTITION_DB
+handler *get_ha_partition(partition_info *part_info)
+{
+ ha_partition *partition;
+ DBUG_ENTER("get_ha_partition");
+ if ((partition= new ha_partition(part_info)))
+ {
+ if (partition->ha_initialise())
+ {
+ delete partition;
+ partition= 0;
+ }
+ }
+ else
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(ha_partition));
+ }
+ DBUG_RETURN(((handler*) partition));
+}
+#endif
+
+
/*
Register handler error messages for use with my_error().
@@ -1406,27 +1445,41 @@
my_bool r;
#endif
DBUG_ENTER("ha_allocate_read_write_set");
- DBUG_PRINT("info", ("no_fields = %d", no_fields));
- read_set= (MY_BITMAP*)sql_alloc(sizeof(MY_BITMAP));
- write_set= (MY_BITMAP*)sql_alloc(sizeof(MY_BITMAP));
- read_buf= (uint32*)sql_alloc(bitmap_size);
- write_buf= (uint32*)sql_alloc(bitmap_size);
- if (!read_set || !write_set || !read_buf || !write_buf)
+ DBUG_PRINT("enter", ("no_fields = %d", no_fields));
+
+ if (table)
{
- ha_deallocate_read_write_set();
- DBUG_RETURN(TRUE);
- }
+ if (table->read_set == NULL)
+ {
+ read_set= (MY_BITMAP*)sql_alloc(sizeof(MY_BITMAP));
+ write_set= (MY_BITMAP*)sql_alloc(sizeof(MY_BITMAP));
+ read_buf= (uint32*)sql_alloc(bitmap_size);
+ write_buf= (uint32*)sql_alloc(bitmap_size);
+ if (!read_set || !write_set || !read_buf || !write_buf)
+ {
+ ha_deallocate_read_write_set();
+ DBUG_RETURN(TRUE);
+ }
#ifndef DEBUG_OFF
- r =
+ r =
#endif
- bitmap_init(read_set, read_buf, no_fields+1, FALSE);
- DBUG_ASSERT(!r /*bitmap_init(read_set...)*/);
+ bitmap_init(read_set, read_buf, no_fields+1, FALSE);
+ DBUG_ASSERT(!r /*bitmap_init(read_set...)*/);
#ifndef DEBUG_OFF
- r =
+ r =
#endif
- bitmap_init(write_set, write_buf, no_fields+1, FALSE);
- DBUG_ASSERT(!r /*bitmap_init(write_set...)*/);
- ha_clear_all_set();
+ bitmap_init(write_set, write_buf, no_fields+1, FALSE);
+ DBUG_ASSERT(!r /*bitmap_init(write_set...)*/);
+ table->read_set= read_set;
+ table->write_set= write_set;
+ ha_clear_all_set();
+ }
+ else
+ {
+ read_set= table->read_set;
+ write_set= table->write_set;
+ }
+ }
DBUG_RETURN(FALSE);
}
@@ -1476,6 +1529,8 @@
}
DBUG_VOID_RETURN;
}
+
+
/*
Read first row (only) from a table
This is never called for InnoDB or BDB tables, as these table types
@@ -1504,7 +1559,7 @@
else
{
/* Find the first row through the primary key */
- (void) ha_index_init(primary_key);
+ (void) ha_index_init(primary_key, 0);
error=index_first(buf);
(void) ha_index_end();
}
@@ -1688,7 +1743,7 @@
int error;
(void) extra(HA_EXTRA_KEYREAD);
- index_init(table->s->next_number_index);
+ index_init(table->s->next_number_index, 1);
if (!table->s->next_number_key_offset)
{ // Autoincrement at key-start
error=index_last(table->record[1]);
@@ -2519,7 +2574,7 @@
int handler::index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
- int error= ha_index_init(index);
+ int error= ha_index_init(index, 0);
if (!error)
error= index_read(buf, key, key_len, find_flag);
if (!error)
--- 1.146/sql/handler.h 2005-06-18 09:21:47 +02:00
+++ 1.147/sql/handler.h 2005-07-13 22:33:34 +02:00
@@ -89,6 +89,11 @@
#define HA_NEED_READ_RANGE_BUFFER (1 << 29) /* for read_multi_range */
#define HA_ANY_INDEX_MAY_BE_UNIQUE (1 << 30)
+/* Flags for partition handlers */
+#define HA_CAN_PARTITION (1 << 0) /* Partition support */
+#define HA_CAN_UPDATE_PARTITION_KEY (1 << 1)
+#define HA_CAN_PARTITION_UNIQUE (1 << 2)
+
/* bits in index_flags(index_number) for what you can do with index */
#define HA_READ_NEXT 1 /* TODO really use this flag */
@@ -172,6 +177,7 @@
DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB,
DB_TYPE_FEDERATED_DB,
DB_TYPE_BLACKHOLE_DB,
+ DB_TYPE_PARTITION_DB,
DB_TYPE_DEFAULT // Must be last
};
@@ -364,6 +370,206 @@
enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
ISO_REPEATABLE_READ, ISO_SERIALIZABLE};
+#ifdef HAVE_PARTITION_DB
+
+typedef struct {
+ uint32 start_part;
+ uint32 end_part;
+ bool use_bit_array;
+} part_id_range;
+/**
+ * An enum and a struct to handle partitioning and subpartitioning.
+ */
+enum partition_type {
+ NOT_A_PARTITION= 0,
+ RANGE_PARTITION,
+ HASH_PARTITION,
+ LIST_PARTITION
+};
+
+#define UNDEF_NODEGROUP 65535
+class Item;
+
+class partition_element :public Sql_alloc {
+public:
+ List<partition_element> subpartitions;
+ List<Item> list_expr_list;
+ ulonglong part_max_rows;
+ ulonglong part_min_rows;
+ char *partition_name;
+ char *tablespace_name;
+ Item* range_expr;
+ char* part_comment;
+ char* data_file_name;
+ char* index_file_name;
+ enum db_type engine_type;
+ uint16 nodegroup_id;
+
+ partition_element()
+ : part_max_rows(0), part_min_rows(0), partition_name(NULL),
+ tablespace_name(NULL), range_expr(NULL), part_comment(NULL),
+ data_file_name(NULL), index_file_name(NULL),
+ engine_type(DB_TYPE_UNKNOWN), nodegroup_id(UNDEF_NODEGROUP)
+ {
+ subpartitions.empty();
+ list_expr_list.empty();
+ }
+ ~partition_element() {}
+};
+
+typedef struct {
+ longlong list_value;
+ uint partition_id;
+} LIST_PART_ENTRY;
+enum Item_result;
+
+class partition_info;
+
+typedef bool (*get_part_id_func)(partition_info *part_info,
+ uint32 *part_id);
+typedef uint32 (*get_subpart_id_func)(partition_info *part_info);
+
+class partition_info :public Sql_alloc {
+public:
+ /*
+ * Here comes a set of definitions needed for partitioned table handlers.
+ */
+ List<partition_element> partitions;
+
+ List<char> part_field_list;
+ List<char> subpart_field_list;
+
+ get_part_id_func get_partition_id;
+ get_part_id_func get_part_partition_id;
+ get_subpart_id_func get_subpartition_id;
+
+ Field **part_field_array;
+ Field **subpart_field_array;
+ Field **full_part_field_array;
+
+ Item *part_expr;
+ Item *subpart_expr;
+
+ Item *item_free_list;
+
+ union {
+ longlong *range_int_array;
+ LIST_PART_ENTRY *list_array;
+ };
+ char* part_info_string;
+
+ char *part_func_string;
+ char *subpart_func_string;
+
+ partition_element *curr_part_elem;
+ partition_element *current_partition;
+ /*
+ These key_map's are used for Partitioning to enable quick decisions
+ on whether we can derive more information about which partition to
+ scan just by looking at what index is used.
+ */
+ key_map all_fields_in_PF, all_fields_in_PPF, all_fields_in_SPF;
+ key_map some_fields_in_PF;
+
+ enum db_type default_engine_type;
+ Item_result part_result_type;
+ partition_type part_type;
+ partition_type subpart_type;
+
+ uint part_info_len;
+ uint part_func_len;
+ uint subpart_func_len;
+
+ uint no_full_parts;
+ uint no_parts;
+ uint no_subparts;
+ uint count_curr_parts;
+ uint count_curr_subparts;
+
+ uint part_error_code;
+
+ uint no_list_values;
+
+ uint no_part_fields;
+ uint no_subpart_fields;
+ uint no_full_part_fields;
+
+ uint16 linear_hash_mask;
+
+ bool use_default_partitions;
+ bool use_default_subpartitions;
+ bool defined_max_value;
+ bool list_of_part_fields;
+ bool list_of_subpart_fields;
+ bool linear_hash_ind;
+
+ partition_info()
+ : get_partition_id(NULL), get_part_partition_id(NULL),
+ get_subpartition_id(NULL),
+ part_field_array(NULL), subpart_field_array(NULL),
+ full_part_field_array(NULL),
+ part_expr(NULL), subpart_expr(NULL), item_free_list(NULL),
+ list_array(NULL),
+ part_info_string(NULL),
+ part_func_string(NULL), subpart_func_string(NULL),
+ curr_part_elem(NULL), current_partition(NULL),
+ default_engine_type(DB_TYPE_UNKNOWN),
+ part_result_type(INT_RESULT),
+ part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
+ part_info_len(0), part_func_len(0), subpart_func_len(0),
+ no_full_parts(0), no_parts(0), no_subparts(0),
+ count_curr_parts(0), count_curr_subparts(0), part_error_code(0),
+ no_list_values(0), no_part_fields(0), no_subpart_fields(0),
+ no_full_part_fields(0), linear_hash_mask(0),
+ use_default_partitions(TRUE),
+ use_default_subpartitions(TRUE), defined_max_value(FALSE),
+ list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
+ linear_hash_ind(FALSE)
+ {
+ all_fields_in_PF.clear_all();
+ all_fields_in_PPF.clear_all();
+ all_fields_in_SPF.clear_all();
+ some_fields_in_PF.clear_all();
+ partitions.empty();
+ part_field_list.empty();
+ subpart_field_list.empty();
+ }
+ ~partition_info() {}
+};
+/*
+ Answers the question if subpartitioning is used for a certain table
+ SYNOPSIS
+ is_sub_partitioned()
+ part_info A reference to the partition_info struct
+ RETURN VALUE
+ Returns true if subpartitioning used and false otherwise
+ DESCRIPTION
+ A routine to check for subpartitioning for improved readability of code
+*/
+inline
+bool is_sub_partitioned(partition_info *part_info)
+{ return (part_info->subpart_type == NOT_A_PARTITION ? FALSE : TRUE); }
+
+
+/*
+ Returns the total number of partitions on the leaf level.
+ SYNOPSIS
+ get_tot_partitions()
+ part_info A reference to the partition_info struct
+ RETURN VALUE
+ Returns the number of partitions
+ DESCRIPTION
+ A routine to check for number of partitions for improved readability
+ of code
+*/
+inline
+uint get_tot_partitions(partition_info *part_info)
+{
+ return part_info->no_parts *
+ (is_sub_partitioned(part_info) ? part_info->no_subparts : 1);
+}
+#endif
+
typedef struct st_ha_create_information
{
CHARSET_INFO *table_charset, *default_table_charset;
@@ -412,6 +618,30 @@
} HA_CHECK_OPT;
+#ifdef HAVE_PARTITION_DB
+int get_parts_for_update(const byte *old_data, byte *new_data,
+ const byte *rec0, partition_info *part_info,
+ uint32 *old_part_id, uint32 *new_part_id);
+int get_part_for_delete(const byte *buf, const byte *rec0,
+ partition_info *part_info, uint32 *part_id);
+bool check_partition_info(partition_info *part_info,enum db_type eng_type,
+ handler *file, ulonglong max_rows);
+bool fix_partition_func(THD *thd, const char *name, TABLE *table);
+char *generate_partition_syntax(partition_info *part_info,
+ uint *buf_length, bool use_sql_alloc);
+bool partition_key_modified(TABLE *table, List<Item> &fields);
+void get_partition_set(const TABLE *table, byte *buf, const uint index,
+ const key_range *key_spec,
+ part_id_range *part_spec);
+void get_full_part_id_from_key(const TABLE *table, byte *buf,
+ KEY *key_info,
+ const key_range *key_spec,
+ part_id_range *part_spec);
+bool mysql_unpack_partition(File file, THD *thd, uint part_info_len,
+ TABLE *table);
+#endif
+
+
/*
This is a buffer area that the handler can use to store rows.
'end_of_used_area' should be kept updated after calls to
@@ -429,10 +659,13 @@
class handler :public Sql_alloc
{
+#ifdef HAVE_PARTITION_DB
+ friend class ha_partition;
+#endif
protected:
struct st_table *table; /* The table definition */
- virtual int index_init(uint idx) { active_index=idx; return 0; }
+ virtual int index_init(uint idx, bool sorted) { active_index=idx; return 0; }
virtual int index_end() { active_index=MAX_KEY; return 0; }
/*
rnd_init() can be called two times without rnd_end() in between
@@ -518,7 +751,7 @@
{ return rows2double(ranges+rows); }
virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; }
virtual bool has_transactions(){ return 0;}
- virtual uint extra_rec_buf_length() { return 0; }
+ virtual uint extra_rec_buf_length() const { return 0; }
/*
Return upper bound of current number of records in the table
@@ -537,12 +770,12 @@
virtual const char *index_type(uint key_number) { DBUG_ASSERT(0); return "";}
- int ha_index_init(uint idx)
+ int ha_index_init(uint idx, bool sorted)
{
DBUG_ENTER("ha_index_init");
DBUG_ASSERT(inited==NONE);
inited=INDEX;
- DBUG_RETURN(index_init(idx));
+ DBUG_RETURN(index_init(idx, sorted));
}
int ha_index_end()
{
@@ -902,6 +1135,10 @@
virtual const char *table_type() const =0;
virtual const char **bas_ext() const =0;
virtual ulong table_flags(void) const =0;
+#ifdef HAVE_PARTITION_DB
+ virtual ulong partition_flags(void) const { return 0;}
+ virtual int get_default_no_partitions(ulonglong max_rows) { return 1;}
+#endif
virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0;
virtual ulong index_ddl_flags(KEY *wanted_index) const
{ return (HA_DDL_SUPPORT); }
@@ -941,6 +1178,7 @@
virtual int delete_table(const char *name);
virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
+ virtual int create_handler_files(const char *name) { return FALSE;}
/* lock_count() can be more than one if the table is a MERGE */
virtual uint lock_count(void) const { return 1; }
--- 1.34/sql/key.cc 2005-05-06 12:46:02 +02:00
+++ 1.35/sql/key.cc 2005-07-13 22:33:34 +02:00
@@ -429,3 +429,86 @@
}
return 0; // Keys are equal
}
+
+
+/*
+ Compare two records in index order
+ SYNOPSIS
+ key_rec_cmp()
+ key Index information
+ rec0 Pointer to table->record[0]
+ first_rec Pointer to record compare with
+ second_rec Pointer to record compare against first_rec
+ DESCRIPTION
+ This method is set-up such that it can be called directly from the
+ priority queue and it is attempted to be optimised as much as possible
+ since this will be called O(N * log N) times while performing a merge
+ sort in various places in the code.
+
+ We retrieve the pointer to table->record[0] using the fact that key_parts
+ have an offset making it possible to calculate the start of the record.
+ We need to get the diff to the compared record since none of the records
+ being compared are stored in table->record[0].
+
+ We first check for NULL values, if there are no NULL values we use
+ a compare method that gets two field pointers and a max length
+ and return the result of the comparison.
+*/
+
+int key_rec_cmp(void *key, byte *first_rec, byte *second_rec)
+{
+ KEY *key_info= (KEY*)key;
+ uint key_parts= key_info->key_parts, i= 0;
+ KEY_PART_INFO *key_part= key_info->key_part;
+ char *rec0= key_part->field->ptr - key_part->offset;
+ my_ptrdiff_t first_diff= first_rec - rec0, sec_diff= second_rec - rec0;
+ int result= 0;
+ DBUG_ENTER("key_rec_cmp");
+
+ do
+ {
+ Field *field= key_part->field;
+ uint length;
+
+ if (key_part->null_bit)
+ {
+ /* The key_part can contain NULL values */
+ bool first_is_null= field->is_null(first_diff);
+ bool sec_is_null= field->is_null(sec_diff);
+ /*
+ NULL is smaller then everything so if first is NULL and the other
+ not then we know that we should return -1 and for the opposite
+ we should return +1. If both are NULL then we call it equality
+ although it is a strange form of equality, we have equally little
+ information of the real value.
+ */
+ if (!first_is_null)
+ {
+ if (!sec_is_null)
+ ; /* Fall through, no NULL fields */
+ else
+ {
+ DBUG_RETURN(+1);
+ }
+ }
+ else if (!sec_is_null)
+ {
+ DBUG_RETURN(-1);
+ }
+ else
+ goto next_loop; /* Both were NULL */
+ }
+ /*
+ No null values in the fields
+ We use the virtual method cmp with a max length parameter.
+ For most field types this translates into a cmp without
+ max length. The exceptions are the BLOB and VARCHAR field types
+ that take the max length into account.
+ */
+ result= field->cmp(field->ptr+first_diff, field->ptr+sec_diff,
+ key_part->length);
+next_loop:
+ key_part++;
+ } while (!result && ++i < key_parts);
+ DBUG_RETURN(result);
+}
--- 1.136/sql/lex.h 2005-02-25 19:19:00 +01:00
+++ 1.137/sql/lex.h 2005-07-13 22:33:34 +02:00
@@ -269,11 +269,14 @@
{ "LEAVE", SYM(LEAVE_SYM)},
{ "LEAVES", SYM(LEAVES)},
{ "LEFT", SYM(LEFT)},
+ { "LESS", SYM(LESS_SYM)},
{ "LEVEL", SYM(LEVEL_SYM)},
{ "LIKE", SYM(LIKE)},
{ "LIMIT", SYM(LIMIT)},
+ { "LINEAR", SYM(LINEAR_SYM)},
{ "LINES", SYM(LINES)},
{ "LINESTRING", SYM(LINESTRING)},
+ { "LIST", SYM(LIST_SYM)},
{ "LOAD", SYM(LOAD)},
{ "LOCAL", SYM(LOCAL_SYM)},
{ "LOCALTIME", SYM(NOW_SYM)},
@@ -307,6 +310,7 @@
{ "MAX_ROWS", SYM(MAX_ROWS)},
{ "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR)},
{ "MAX_USER_CONNECTIONS", SYM(MAX_USER_CONNECTIONS_SYM)},
+ { "MAXVALUE", SYM(MAX_VALUE_SYM)},
{ "MEDIUM", SYM(MEDIUM_SYM)},
{ "MEDIUMBLOB", SYM(MEDIUMBLOB)},
{ "MEDIUMINT", SYM(MEDIUMINT)},
@@ -338,6 +342,7 @@
{ "NEW", SYM(NEW_SYM)},
{ "NEXT", SYM(NEXT_SYM)},
{ "NO", SYM(NO_SYM)},
+ { "NODEGROUP", SYM(NODEGROUP_SYM)},
{ "NONE", SYM(NONE_SYM)},
{ "NOT", SYM(NOT_SYM)},
{ "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)},
@@ -360,6 +365,10 @@
{ "OUTFILE", SYM(OUTFILE)},
{ "PACK_KEYS", SYM(PACK_KEYS_SYM)},
{ "PARTIAL", SYM(PARTIAL)},
+#ifdef HAVE_PARTITION_DB
+ { "PARTITION", SYM(PARTITION_SYM)},
+#endif
+ { "PARTITIONS", SYM(PARTITIONS_SYM)},
{ "PASSWORD", SYM(PASSWORD)},
{ "PHASE", SYM(PHASE_SYM)},
{ "POINT", SYM(POINT_SYM)},
@@ -380,6 +389,7 @@
{ "RAID_CHUNKS", SYM(RAID_CHUNKS)},
{ "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE)},
{ "RAID_TYPE", SYM(RAID_TYPE)},
+ { "RANGE", SYM(RANGE_SYM)},
{ "READ", SYM(READ_SYM)},
{ "READS", SYM(READS_SYM)},
{ "REAL", SYM(REAL)},
@@ -471,6 +481,8 @@
{ "STRING", SYM(STRING_SYM)},
{ "STRIPED", SYM(RAID_STRIPED_SYM)},
{ "SUBJECT", SYM(SUBJECT_SYM)},
+ { "SUBPARTITION", SYM(SUBPARTITION_SYM)},
+ { "SUBPARTITIONS", SYM(SUBPARTITIONS_SYM)},
{ "SUPER", SYM(SUPER_SYM)},
{ "SUSPEND", SYM(SUSPEND_SYM)},
{ "TABLE", SYM(TABLE_SYM)},
@@ -480,6 +492,7 @@
{ "TEMPTABLE", SYM(TEMPTABLE_SYM)},
{ "TERMINATED", SYM(TERMINATED)},
{ "TEXT", SYM(TEXT_SYM)},
+ { "THAN", SYM(THAN_SYM)},
{ "THEN", SYM(THEN_SYM)},
{ "TIME", SYM(TIME_SYM)},
{ "TIMESTAMP", SYM(TIMESTAMP)},
--- 1.312/sql/mysql_priv.h 2005-06-21 17:51:22 +02:00
+++ 1.313/sql/mysql_priv.h 2005-07-13 22:33:35 +02:00
@@ -614,6 +614,18 @@
bool no_errors);
bool check_global_access(THD *thd, ulong want_access);
+/*
+ General routine to change field->ptr of a NULL-terminated array of Field
+ objects. Useful when needed to call val_int, val_str or similar and the
+ field data is not in table->record[0] but in some other structure.
+ set_key_field_ptr changes all fields of an index using a key_info object.
+ All methods presume that there is at least one field to change.
+*/
+
+void set_field_ptr(Field **ptr, const byte *new_buf, const byte *old_buf);
+void set_key_field_ptr(KEY *key_info, const byte *new_buf,
+ const byte *old_buf);
+
bool mysql_backup_table(THD* thd, TABLE_LIST* table_list);
bool mysql_restore_table(THD* thd, TABLE_LIST* table_list);
@@ -769,6 +781,9 @@
find_field_in_real_table(THD *thd, TABLE *table, const char *name,
uint length, bool check_grants, bool allow_rowid,
uint *cached_field_index_ptr);
+Field *
+find_field_in_table_sef(TABLE *table, const char *name);
+
#ifdef HAVE_OPENSSL
#include <openssl/des.h>
struct st_des_keyblock
@@ -1003,6 +1018,7 @@
void key_unpack(String *to,TABLE *form,uint index);
bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields);
int key_cmp(KEY_PART_INFO *key_part, const byte *key, uint key_length);
+int key_rec_cmp(void *key_info, byte *a, byte *b);
bool init_errmessage(void);
void sql_perror(const char *message);
@@ -1171,6 +1187,7 @@
extern SHOW_COMP_OPTION have_geometry, have_rtree_keys;
extern SHOW_COMP_OPTION have_crypt;
extern SHOW_COMP_OPTION have_compress;
+extern SHOW_COMP_OPTION have_partition_db;
#ifndef __WIN__
extern pthread_t signal_thread;
@@ -1221,7 +1238,7 @@
uint key_count,KEY *key_info,handler *db_type);
int rea_create_table(THD *thd, my_string file_name,HA_CREATE_INFO *create_info,
List<create_field> &create_field,
- uint key_count,KEY *key_info);
+ uint key_count,KEY *key_info, handler *file);
int format_number(uint inputflag,uint max_length,my_string pos,uint length,
my_string *errpos);
int openfrm(THD *thd, const char *name,const char *alias,uint filestat,
--- 1.466/sql/mysqld.cc 2005-06-22 16:12:29 +02:00
+++ 1.467/sql/mysqld.cc 2005-07-13 22:33:35 +02:00
@@ -324,6 +324,7 @@
ulong opt_ndb_cache_check_time;
const char *opt_ndb_mgmd;
ulong opt_ndb_nodeid;
+bool opt_ndb_linear_hash;
#endif
my_bool opt_readonly, use_temp_pool, relay_log_purge;
my_bool opt_sync_frm, opt_allow_suspicious_udfs;
@@ -429,6 +430,7 @@
SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam, have_ndbcluster,
have_example_db, have_archive_db, have_csv_db;
SHOW_COMP_OPTION have_federated_db;
+SHOW_COMP_OPTION have_partition_db;
SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache;
SHOW_COMP_OPTION have_geometry, have_rtree_keys;
SHOW_COMP_OPTION have_crypt, have_compress;
@@ -4233,6 +4235,7 @@
OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION, OPT_NDB_CACHE_CHECK_TIME,
OPT_NDB_MGMD, OPT_NDB_NODEID,
+ OPT_NDB_LINEAR_HASH,
OPT_SKIP_SAFEMALLOC,
OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
@@ -4798,6 +4801,16 @@
(gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz,
(gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz,
0, GET_ULONG, REQUIRED_ARG, 32, 1, 256, 0, 0, 0},
+ {"ndb-use-linear-hash", OPT_NDB_LINEAR_HASH,
+ "Flag to indicate whether to use linear hash for default in new tables"
+ (gptr*) &opt_ndb_linear_hash,
+ (gptr*) &opt_ndb_linear_hash,
+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
+ {"ndb_use_linear_hash", OPT_NDB_LINEAR_HASH,
+ "Flag to indicate whether to use linear hash for default in new tables"
+ (gptr*) &opt_ndb_linear_hash,
+ (gptr*) &opt_ndb_linear_hash,
+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
{"ndb-force-send", OPT_NDB_FORCE_SEND,
"Force send of buffers to ndb immediately without waiting for "
"other threads.",
@@ -6052,6 +6065,11 @@
have_example_db= SHOW_OPTION_YES;
#else
have_example_db= SHOW_OPTION_NO;
+#endif
+#ifdef HAVE_PARTITION_DB
+ have_partition_db= SHOW_OPTION_YES;
+#else
+ have_partition_db= SHOW_OPTION_NO;
#endif
#ifdef HAVE_ARCHIVE_DB
have_archive_db= SHOW_OPTION_YES;
--- 1.173/sql/opt_range.cc 2005-06-23 09:48:17 +02:00
+++ 1.174/sql/opt_range.cc 2005-07-13 22:33:35 +02:00
@@ -751,7 +751,7 @@
DBUG_ENTER("QUICK_RANGE_SELECT::init");
if (file->inited == handler::NONE)
- DBUG_RETURN(error= file->ha_index_init(index));
+ DBUG_RETURN(error= file->ha_index_init(index, 1));
error= 0;
DBUG_RETURN(0);
}
@@ -6254,7 +6254,7 @@
(byte*) range->min_key,
range->min_length,
(ha_rkey_function)(range->flag ^ GEOM_FLAG));
- if (result != HA_ERR_KEY_NOT_FOUND)
+ if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE)
DBUG_RETURN(result);
range=0; // Not found, to next range
}
@@ -6397,7 +6397,7 @@
}
if (result)
{
- if (result != HA_ERR_KEY_NOT_FOUND)
+ if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE)
DBUG_RETURN(result);
range=0; // Not found, to next range
continue;
@@ -8029,7 +8029,7 @@
DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::reset");
file->extra(HA_EXTRA_KEYREAD); /* We need only the key attributes */
- result= file->ha_index_init(index);
+ result= file->ha_index_init(index, 1);
result= file->index_last(record);
if (result == HA_ERR_END_OF_FILE)
DBUG_RETURN(0);
@@ -8103,10 +8103,12 @@
is_last_prefix= key_cmp(index_info->key_part, last_prefix,
group_prefix_len);
DBUG_ASSERT(is_last_prefix <= 0);
- if (result == HA_ERR_KEY_NOT_FOUND)
- continue;
- else if (result)
+ if (result)
+ {
+ if (result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE)
+ continue;
break;
+ }
if (have_min)
{
@@ -8135,10 +8137,11 @@
HA_READ_KEY_EXACT);
result= have_min ? min_res : have_max ? max_res : result;
- }
- while (result == HA_ERR_KEY_NOT_FOUND && is_last_prefix != 0);
+ } while ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
+ is_last_prefix != 0);
if (result == 0)
+ {
/*
Partially mimic the behavior of end_select_send. Copy the
field data from Item_field::field into Item_field::result_field
@@ -8146,6 +8149,7 @@
other fields in non-ANSI SQL mode).
*/
copy_fields(&join->tmp_table_param);
+ }
else if (result == HA_ERR_KEY_NOT_FOUND)
result= HA_ERR_END_OF_FILE;
@@ -8172,6 +8176,7 @@
RETURN
0 on success
HA_ERR_KEY_NOT_FOUND if no MIN key was found that fulfills all conditions.
+ HA_ERR_END_OF_FILE - "" -
other if some error occurred
*/
@@ -8225,7 +8230,7 @@
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
key_restore(record, tmp_record, index_info, 0);
}
- else if (result == HA_ERR_KEY_NOT_FOUND)
+ else if (result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE)
result= 0; /* There is a result in any case. */
}
}
@@ -8250,6 +8255,7 @@
RETURN
0 on success
HA_ERR_KEY_NOT_FOUND if no MAX key was found that fulfills all conditions.
+ HA_ERR_END_OF_FILE - "" -
other if some error occurred
*/
@@ -8350,6 +8356,7 @@
0 on success
HA_ERR_KEY_NOT_FOUND if there is no key with the given prefix in any of
the ranges
+ HA_ERR_END_OF_FILE - "" -
other if some error
*/
@@ -8394,11 +8401,12 @@
result= file->index_read(record, group_prefix, search_prefix_len,
find_flag);
- if ((result == HA_ERR_KEY_NOT_FOUND) &&
- (cur_range->flag & (EQ_RANGE | NULL_RANGE)))
- continue; /* Check the next range. */
- else if (result)
+ if (result)
{
+ if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
+ (cur_range->flag & (EQ_RANGE | NULL_RANGE)))
+ continue; /* Check the next range. */
+
/*
In all other cases (HA_ERR_*, HA_READ_KEY_EXACT with NO_MIN_RANGE,
HA_READ_AFTER_KEY, HA_READ_KEY_OR_NEXT) if the lookup failed for this
@@ -8425,7 +8433,7 @@
/* Check if record belongs to the current group. */
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
{
- result = HA_ERR_KEY_NOT_FOUND;
+ result= HA_ERR_KEY_NOT_FOUND;
continue;
}
@@ -8443,7 +8451,7 @@
if (!((cur_range->flag & NEAR_MAX) && (cmp_res == -1) ||
(cmp_res <= 0)))
{
- result = HA_ERR_KEY_NOT_FOUND;
+ result= HA_ERR_KEY_NOT_FOUND;
continue;
}
}
@@ -8482,6 +8490,7 @@
0 on success
HA_ERR_KEY_NOT_FOUND if there is no key with the given prefix in any of
the ranges
+ HA_ERR_END_OF_FILE - "" -
other if some error
*/
@@ -8527,23 +8536,27 @@
result= file->index_read(record, group_prefix, search_prefix_len,
find_flag);
- if ((result == HA_ERR_KEY_NOT_FOUND) && (cur_range->flag & EQ_RANGE))
- continue; /* Check the next range. */
- else if (result)
+ if (result)
+ {
+ if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
+ (cur_range->flag & EQ_RANGE))
+ continue; /* Check the next range. */
+
/*
In no key was found with this upper bound, there certainly are no keys
in the ranges to the left.
*/
return result;
+ }
/* A key was found. */
if (cur_range->flag & EQ_RANGE)
- return result; /* No need to perform the checks below for equal keys. */
+ return 0; /* No need to perform the checks below for equal keys. */
/* Check if record belongs to the current group. */
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
{
- result = HA_ERR_KEY_NOT_FOUND;
+ result= HA_ERR_KEY_NOT_FOUND;
continue;
}
--- 1.44/sql/opt_sum.cc 2005-06-06 13:03:28 +02:00
+++ 1.45/sql/opt_sum.cc 2005-07-13 22:33:35 +02:00
@@ -181,7 +181,7 @@
const_result= 0;
break;
}
- error= table->file->ha_index_init((uint) ref.key);
+ error= table->file->ha_index_init((uint) ref.key, 1);
if (!ref.key_length)
error= table->file->index_first(table->record[0]);
@@ -253,7 +253,7 @@
const_result= 0;
break;
}
- error= table->file->ha_index_init((uint) ref.key);
+ error= table->file->ha_index_init((uint) ref.key, 1);
if (!ref.key_length)
error= table->file->index_last(table->record[0]);
--- 1.40/sql/records.cc 2005-04-07 18:24:08 +02:00
+++ 1.41/sql/records.cc 2005-07-13 22:33:36 +02:00
@@ -31,6 +31,74 @@
/* init struct for read with info->read_record */
+/*
+ init_read_record is used to scan by using a number of different methods.
+ Which method to use is set-up in this call so that later calls to
+ the info->read_record will call the appropriate method using a function
+ pointer.
+
+ There are five methods that relate completely to the sort function
+ filesort. The result of a filesort is retrieved using read_record
+ calls. The other two methods are used for normal table access.
+
+ The filesort will produce references to the records sorted, these
+ references can be stored in memory or in a temporary file.
+
+ The temporary file is normally used when the references doesn't fit into
+ a properly sized memory buffer. For most small queries the references
+ are stored in the memory buffer.
+
+ The temporary file is also used when performing an update where a key is
+ modified.
+
+ Methods used when ref's are in memory (using rr_from_pointers):
+ rr_unpack_from_buffer:
+ ----------------------
+ This method is used when table->sort.addon_field is allocated.
+ This is allocated for most SELECT queries not involving any BLOB's.
+ In this case the records are fetched from a memory buffer.
+ rr_from_pointers:
+ -----------------
+ Used when the above is not true, UPDATE, DELETE and so forth and
+ SELECT's involving BLOB's. It is also used when the addon_field
+ buffer is not allocated due to that its size was bigger than the
+ session variable max_length_for_sort_data.
+ In this case the record data is fetched from the handler using the
+ saved reference using the rnd_pos handler call.
+
+ Methods used when ref's are in a temporary file (using rr_from_tempfile)
+ rr_unpack_from_tempfile:
+ ------------------------
+ Same as rr_unpack_from_buffer except that references are fetched from
+ temporary file. Should obviously not really happen other than in
+ strange configurations.
+
+ rr_from_tempfile:
+ -----------------
+ Same as rr_from_pointers except that references are fetched from
+ temporary file instead of from
+ rr_from_cache:
+ --------------
+ This is a special variant of rr_from_tempfile that can be used for
+ handlers that is not using the HA_FAST_KEY_READ table flag. Instead
+ of reading the references one by one from the temporary file it reads
+ a set of them, sorts them and reads all of them into a buffer which
+ is then used for a number of subsequent calls to rr_from_cache.
+ It is only used for SELECT queries and a number of other conditions
+ on table size.
+
+ All other accesses use either index access methods (rr_quick) or a full
+ table scan (rr_sequential).
+ rr_quick:
+ ---------
+ rr_quick uses one of the QUICK_SELECT classes in opt_range.cc to
+ perform an index scan. There are loads of functionality hidden
+ in these quick classes. It handles all index scans of various kinds.
+ rr_sequential:
+ --------------
+ This is the most basic access method of a table using rnd_init,
+ rnd_next and rnd_end. No indexes are used.
+*/
void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
SQL_SELECT *select,
int use_record_cache, bool print_error)
--- 1.147/sql/sql_acl.cc 2005-06-22 16:12:29 +02:00
+++ 1.148/sql/sql_acl.cc 2005-07-13 22:33:37 +02:00
@@ -2047,7 +2047,7 @@
key_copy(key, col_privs->record[0], col_privs->key_info, key_prefix_len);
col_privs->field[4]->store("",0, &my_charset_latin1);
- col_privs->file->ha_index_init(0);
+ col_privs->file->ha_index_init(0, 1);
if (col_privs->file->index_read(col_privs->record[0],
(byte*) key,
key_prefix_len, HA_READ_KEY_EXACT))
@@ -2192,7 +2192,7 @@
List_iterator <LEX_COLUMN> iter(columns);
class LEX_COLUMN *column;
- table->file->ha_index_init(0);
+ table->file->ha_index_init(0, 1);
while ((column= iter++))
{
ulong privileges= column->rights;
@@ -3168,8 +3168,8 @@
t_table = tables[0].table; c_table = tables[1].table;
p_table= tables[2].table;
- t_table->file->ha_index_init(0);
- p_table->file->ha_index_init(0);
+ t_table->file->ha_index_init(0, 1);
+ p_table->file->ha_index_init(0, 1);
if (!t_table->file->index_first(t_table->record[0]))
{
/* Will be restored by org_thd->store_globals() */
@@ -4474,7 +4474,7 @@
user_key, key_prefix_length,
HA_READ_KEY_EXACT)))
{
- if (error != HA_ERR_KEY_NOT_FOUND)
+ if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
{
table->file->print_error(error, MYF(0));
result= -1;
--- 1.256/sql/sql_base.cc 2005-06-23 12:19:59 +02:00
+++ 1.257/sql/sql_base.cc 2005-07-13 22:33:37 +02:00
@@ -2507,6 +2507,42 @@
/*
+ Find field in table, no side effects, only purpose is to check for field
+ in table object and get reference to the field if found.
+
+ SYNOPSIS
+ find_field_in_table_sef()
+
+ table table where to find
+ name Name of field searched for
+
+ RETURN
+ 0 field is not found
+ # pointer to field
+*/
+
+Field *find_field_in_table_sef(TABLE *table, const char *name)
+{
+ Field **field_ptr;
+ if (table->s->name_hash.records)
+ field_ptr= (Field**)hash_search(&table->s->name_hash,(byte*) name,
+ strlen(name));
+ else
+ {
+ if (!(field_ptr= table->field))
+ return (Field *)0;
+ for (; *field_ptr; ++field_ptr)
+ if (!my_strcasecmp(system_charset_info, (*field_ptr)->field_name, name))
+ break;
+ }
+ if (field_ptr)
+ return *field_ptr;
+ else
+ return (Field *)0;
+}
+
+
+/*
Find field in table
SYNOPSIS
@@ -2569,13 +2605,16 @@
(bool)(thd->set_query_id-1));
if (field->query_id != thd->query_id)
{
+ if (table->get_fields_in_item_tree)
+ field->flags|= GET_FIXED_FIELDS_FLAG;
field->query_id=thd->query_id;
table->used_fields++;
table->used_keys.intersect(field->part_of_key);
}
else
thd->dupp_field=field;
- }
+ } else if (table->get_fields_in_item_tree)
+ field->flags|= GET_FIXED_FIELDS_FLAG;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_grants && check_grant_column(thd, &table->grant,
table->s->db,
--- 1.151/sql/sql_lex.cc 2005-06-17 23:13:35 +02:00
+++ 1.152/sql/sql_lex.cc 2005-07-13 22:33:38 +02:00
@@ -155,6 +155,9 @@
lex->yylineno = 1;
lex->in_comment=0;
lex->length=0;
+#ifdef HAVE_PARTITION_DB
+ lex->part_info= 0;
+#endif
lex->select_lex.in_sum_expr=0;
lex->select_lex.expr_list.empty();
lex->select_lex.ftfunc_list_alloc.empty();
--- 1.185/sql/sql_lex.h 2005-06-21 17:51:22 +02:00
+++ 1.186/sql/sql_lex.h 2005-07-13 22:33:38 +02:00
@@ -25,6 +25,9 @@
class sp_name;
class sp_instr;
class sp_pcontext;
+#ifdef HAVE_PARTITION_DB
+class partition_info;
+#endif
/*
The following hack is needed because mysql_yacc.cc does not define
@@ -732,6 +735,10 @@
TABLE_LIST *proc_table; /* refer to mysql.proc if it was opened by VIEW */
/* store original leaf_tables for INSERT SELECT and PS/SP */
TABLE_LIST *leaf_tables_insert;
+#ifdef HAVE_PARTITION_DB
+ /* Partition info structure filled in by PARTITION BY parse part */
+ partition_info *part_info;
+#endif
List<key_part_spec> col_list;
List<key_part_spec> ref_list;
--- 1.346/sql/sql_select.cc 2005-06-23 12:20:00 +02:00
+++ 1.347/sql/sql_select.cc 2005-07-13 22:33:38 +02:00
@@ -1279,6 +1279,8 @@
/* Copy data to the temporary table */
thd->proc_info= "Copying to tmp table";
DBUG_PRINT("info", ("%s", thd->proc_info));
+ if (!curr_join->sort_and_group)
+ curr_join->join_tab[curr_join->const_tables].sorted= 0;
if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
{
error= tmp_error;
@@ -1425,6 +1427,8 @@
1, TRUE))
DBUG_VOID_RETURN;
curr_join->group_list= 0;
+ if (!curr_join->sort_and_group)
+ curr_join->join_tab[curr_join->const_tables].sorted= 0;
if (setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
(tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
0)))
@@ -1610,6 +1614,14 @@
(select_options & OPTION_FOUND_ROWS ?
HA_POS_ERROR : unit->select_limit_cnt)))
DBUG_VOID_RETURN;
+ if (!curr_join->join_tab[curr_join->const_tables].table->sort.io_cache)
+ {
+ /*
+ If no IO cache exists for the first table then we are using an
+ INDEX SCAN and no filesort. Thus we should not remove the sorted
+ attribute on the INDEX SCAN.
+ */
+ skip_sort_order= 1;
}
}
/* XXX: When can we have here thd->net.report_error not zero? */
@@ -5669,6 +5681,7 @@
uint i;
bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
+ bool sorted= 1;
DBUG_ENTER("make_join_readinfo");
for (i=join->const_tables ; i < join->tables ; i++)
@@ -5678,6 +5691,8 @@
tab->read_record.table= table;
tab->read_record.file=table->file;
tab->next_select=sub_select; /* normal select */
+ tab->sorted= sorted;
+ sorted= 0; // only first must be sorted
switch (tab->type) {
case JT_SYSTEM: // Only happens with left join
table->status=STATUS_NO_RECORD;
@@ -8890,7 +8905,12 @@
new_table.file->extra(HA_EXTRA_WRITE_CACHE);
#endif
- /* copy all old rows */
+ /*
+ copy all old rows from heap table to MyISAM table
+ This is the only code that uses record[1] to read/write but this
+ is safe as this is a temporary MyISAM table without timestamp/autoincrement
+ or partitioning.
+ */
while (!table->file->rnd_next(new_table.record[1]))
{
if ((write_err=new_table.file->write_row(new_table.record[1])))
@@ -9021,7 +9041,7 @@
empty_record(table);
if (table->group && join->tmp_table_param.sum_func_count &&
table->s->keys && !table->file->inited)
- table->file->ha_index_init(0);
+ table->file->ha_index_init(0, 0);
}
/* Set up select_end */
join->join_tab[join->tables-1].next_select= setup_end_select_func(join);
@@ -9635,7 +9655,13 @@
table->file->extra(HA_EXTRA_KEYREAD);
tab->index= tab->ref.key;
}
- if ((error=join_read_const(tab)))
+ error=join_read_const(tab);
+ if (table->key_read)
+ {
+ table->key_read=0;
+ table->file->extra(HA_EXTRA_NO_KEYREAD);
+ }
+ if (error)
{
tab->info="unique row not found";
/* Mark for EXPLAIN that the row was not found */
@@ -9643,11 +9669,6 @@
if (!table->maybe_null || error > 0)
DBUG_RETURN(error);
}
- if (table->key_read)
- {
- table->key_read=0;
- table->file->extra(HA_EXTRA_NO_KEYREAD);
- }
}
if (*tab->on_expr_ref && !table->null_row)
{
@@ -9719,7 +9740,7 @@
table->status= STATUS_NOT_FOUND;
mark_as_null_row(tab->table);
empty_record(table);
- if (error != HA_ERR_KEY_NOT_FOUND)
+ if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
return report_error(table, error);
return -1;
}
@@ -9742,7 +9763,9 @@
TABLE *table= tab->table;
if (!table->file->inited)
- table->file->ha_index_init(tab->ref.key);
+ {
+ table->file->ha_index_init(tab->ref.key, tab->sorted);
+ }
if (cmp_buffer_with_ref(tab) ||
(table->status & (STATUS_GARBAGE | STATUS_NO_PARENT | STATUS_NULL_ROW)))
{
@@ -9754,7 +9777,7 @@
error=table->file->index_read(table->record[0],
tab->ref.key_buff,
tab->ref.key_length,HA_READ_KEY_EXACT);
- if (error && error != HA_ERR_KEY_NOT_FOUND)
+ if (error && error != HA_ERR_KEY_NOT_FOUND && error !=
HA_ERR_END_OF_FILE)
return report_error(table, error);
}
table->null_row=0;
@@ -9769,14 +9792,16 @@
TABLE *table= tab->table;
if (!table->file->inited)
- table->file->ha_index_init(tab->ref.key);
+ {
+ table->file->ha_index_init(tab->ref.key, tab->sorted);
+ }
if (cp_buffer_from_ref(tab->join->thd, &tab->ref))
return -1;
if ((error=table->file->index_read(table->record[0],
tab->ref.key_buff,
tab->ref.key_length,HA_READ_KEY_EXACT)))
{
- if (error != HA_ERR_KEY_NOT_FOUND)
+ if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
return report_error(table, error);
return -1; /* purecov: inspected */
}
@@ -9796,14 +9821,14 @@
TABLE *table= tab->table;
if (!table->file->inited)
- table->file->ha_index_init(tab->ref.key);
+ table->file->ha_index_init(tab->ref.key, tab->sorted);
if (cp_buffer_from_ref(tab->join->thd, &tab->ref))
return -1;
if ((error=table->file->index_read_last(table->record[0],
tab->ref.key_buff,
tab->ref.key_length)))
{
- if (error != HA_ERR_KEY_NOT_FOUND)
+ if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
return report_error(table, error);
return -1; /* purecov: inspected */
}
@@ -9906,7 +9931,7 @@
tab->read_record.index=tab->index;
tab->read_record.record=table->record[0];
if (!table->file->inited)
- table->file->ha_index_init(tab->index);
+ table->file->ha_index_init(tab->index, tab->sorted);
if ((error=tab->table->file->index_first(tab->table->record[0])))
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
@@ -9945,7 +9970,7 @@
tab->read_record.index=tab->index;
tab->read_record.record=table->record[0];
if (!table->file->inited)
- table->file->ha_index_init(tab->index);
+ table->file->ha_index_init(tab->index, 1);
if ((error= tab->table->file->index_last(tab->table->record[0])))
return report_error(table, error);
return 0;
@@ -9969,7 +9994,7 @@
TABLE *table= tab->table;
if (!table->file->inited)
- table->file->ha_index_init(tab->ref.key);
+ table->file->ha_index_init(tab->ref.key, 1);
#if NOT_USED_YET
if (cp_buffer_from_ref(tab->join->thd, &tab->ref)) // as ft-key doesn't
use store_key's
return -1; // see also FT_SELECT::init()
@@ -10355,7 +10380,7 @@
error, 0))
DBUG_RETURN(NESTED_LOOP_ERROR); // Not a table_is_full error
/* Change method to update rows */
- table->file->ha_index_init(0);
+ table->file->ha_index_init(0, 0);
join->join_tab[join->tables-1].next_select=end_unique_update;
}
join->send_records++;
--- 1.88/sql/sql_select.h 2005-06-22 09:59:07 +02:00
+++ 1.89/sql/sql_select.h 2005-07-13 22:33:38 +02:00
@@ -133,6 +133,7 @@
uint used_fields,used_fieldlength,used_blobs;
enum join_type type;
bool cached_eq_ref_table,eq_ref_table,not_used_in_distinct;
+ bool sorted;
TABLE_REF ref;
JOIN_CACHE cache;
JOIN *join;
--- 1.254/sql/sql_show.cc 2005-06-22 11:08:22 +02:00
+++ 1.255/sql/sql_show.cc 2005-07-13 22:33:39 +02:00
@@ -960,11 +960,14 @@
packet->append("\n)", 2);
if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) &&
!foreign_db_mode)
{
- if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
- packet->append(" TYPE=", 6);
- else
- packet->append(" ENGINE=", 8);
- packet->append(file->table_type());
+ if (!table->s->part_info)
+ {
+ if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
+ packet->append(" TYPE=", 6);
+ else
+ packet->append(" ENGINE=", 8);
+ packet->append(file->table_type());
+ }
if (share->table_charset &&
!(thd->variables.sql_mode & MODE_MYSQL323) &&
@@ -1031,6 +1034,22 @@
append_directory(thd, packet, "DATA", create_info.data_file_name);
append_directory(thd, packet, "INDEX", create_info.index_file_name);
}
+#ifdef HAVE_PARTITION_DB
+ {
+ /*
+ Partition syntax for CREATE TABLE is at the end of the syntax.
+ */
+ uint part_syntax_len;
+ char *part_syntax;
+ if (table->s->part_info &&
+ ((part_syntax= generate_partition_syntax(table->s->part_info,
+ &part_syntax_len,
+ FALSE))))
+ {
+ packet->append(part_syntax, part_syntax_len);
+ my_free(part_syntax, MYF(0));
+ }
+ }
DBUG_RETURN(0);
}
@@ -2719,7 +2738,7 @@
{
DBUG_RETURN(1);
}
- proc_table->file->ha_index_init(0);
+ proc_table->file->ha_index_init(0, 1);
if ((res= proc_table->file->index_first(proc_table->record[0])))
{
res= (res == HA_ERR_END_OF_FILE) ? 0 : 1;
--- 1.253/sql/sql_table.cc 2005-07-11 11:23:41 +02:00
+++ 1.254/sql/sql_table.cc 2005-07-13 22:33:39 +02:00
@@ -1508,7 +1508,65 @@
if (create_info->row_type == ROW_TYPE_DYNAMIC)
db_options|=HA_OPTION_PACK_RECORD;
alias= table_case_name(create_info, table_name);
- file=get_new_handler((TABLE*) 0, create_info->db_type);
+ if (!(file=get_new_handler((TABLE*) 0, create_info->db_type)))
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), 128);//128 bytes invented
+ DBUG_RETURN(TRUE);
+ }
+#ifdef HAVE_PARTITION_DB
+ partition_info *part_info= thd->lex->part_info;
+ if (part_info)
+ {
+ /*
+ The table has been specified as a partitioned table.
+ If this is part of an ALTER TABLE the handler will be the partition
+ handler but we need to specify the default handler to use for
+ partitions also in the call to check_partition_info. We transport
+ this information in the default_db_type variable, it is either
+ DB_TYPE_DEFAULT or the engine set in the ALTER TABLE command.
+ */
+ enum db_type part_engine_type= create_info->db_type;
+ char *part_syntax_buf;
+ uint syntax_len;
+ if (part_engine_type == DB_TYPE_PARTITION_DB)
+ {
+ /*
+ This only happens at ALTER TABLE.
+ default_engine_type was assigned from the engine set in the ALTER
+ TABLE command.
+ */
+ part_engine_type= ha_checktype(part_info->default_engine_type);
+ }
+ if (check_partition_info(part_info, part_engine_type,
+ file, create_info->max_rows))
+ DBUG_RETURN(TRUE);
+ /*
+ We reverse the partitioning parser and generate a standard format
+ for syntax stored in frm file.
+ */
+ if (!(part_syntax_buf= generate_partition_syntax(part_info,
+ &syntax_len,
+ TRUE)))
+ DBUG_RETURN(TRUE);
+ part_info->part_info_string= part_syntax_buf;
+ part_info->part_info_len= syntax_len;
+ if ((!(file->partition_flags() & HA_CAN_PARTITION)) ||
+ create_info->db_type == DB_TYPE_PARTITION_DB)
+ {
+ /*
+ The handler assigned to the table cannot handle partitioning.
+ Assign the partition handler as the handler of the table.
+ */
+ DBUG_PRINT("info", ("db_type= %d, part_flag= %d",
create_info->db_type,file->partition_flags()));
+ delete file;
+ create_info->db_type= DB_TYPE_PARTITION_DB;
+ if (!(file= get_ha_partition(part_info)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+#endif
#ifdef NOT_USED
/*
@@ -1522,7 +1580,7 @@
(file->table_flags() & HA_NO_TEMP_TABLES))
{
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
- DBUG_RETURN(TRUE);
+ goto err;
}
#endif
@@ -1545,7 +1603,7 @@
&keys, internal_tmp_table, &db_options, file,
&key_info_buffer, &key_count,
select_field_count))
- DBUG_RETURN(TRUE);
+ goto err;
/* Check if table exists */
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -1569,13 +1627,13 @@
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
{
create_info->table_existed= 1; // Mark that table existed
- DBUG_RETURN(FALSE);
+ goto no_err;
}
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
- DBUG_RETURN(TRUE);
+ goto err;
}
if (wait_if_global_read_lock(thd, 0, 1))
- DBUG_RETURN(error);
+ goto err;
VOID(pthread_mutex_lock(&LOCK_open));
if (!internal_tmp_table && !(create_info->options &
HA_LEX_CREATE_TMP_TABLE))
{
@@ -1629,7 +1687,7 @@
create_info->table_options=db_options;
if (rea_create_table(thd, path, create_info, fields, key_count,
- key_info_buffer))
+ key_info_buffer, file))
{
/* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */
goto end;
@@ -1658,6 +1716,13 @@
delete file;
thd->proc_info="After create";
DBUG_RETURN(error);
+
+err:
+ delete file;
+ DBUG_RETURN(TRUE);
+no_err:
+ delete file;
+ DBUG_RETURN(FALSE);
}
/*
@@ -3120,6 +3185,58 @@
old_db_type= table->s->db_type;
if (create_info->db_type == DB_TYPE_DEFAULT)
create_info->db_type= old_db_type;
+#ifdef HAVE_PARTITION_DB
+ /*
+ When thd->lex->part_info has a reference to a partition_info the
+ ALTER TABLE contained a definition of a partitioning.
+
+ Case I:
+ If there was a partition before and there is a new one defined.
+ We use the new partitioning. The new partitioning is already
+ defined in the correct variable so no work is needed to
+ accomplish this.
+
+ Case IIa:
+ There was a partitioning before and there is no new one defined.
+ Also the user has not specified an explicit engine to use.
+
+ We use the old partitioning also for the new table. We do this
+ by assigning the partition_info from the table loaded in
+ open_ltable to the partition_info struct used by mysql_create_table
+ later in this method.
+
+ Case IIb:
+ There was a partitioning before and there is no new one defined.
+ The user has specified an explicit engine to use.
+
+ Since the user has specified an explicit engine to use we override
+ the old partitioning info and create a new table using the specified
+ engine. This is the reason for the extra check if old and new engine
+ is equal.
+
+ Case III:
+ There was no partitioning before altering the table, there is
+ partitioning defined in the altered table. Use the new partitioning.
+ No work needed since the partitioning info is already in the
+ correct variable.
+
+ Case IV:
+ There was no partitioning before and no partitioning defined. Obviously
+ no work needed.
+ */
+ if (table->s->part_info)
+ if (!thd->lex->part_info &&
+ create_info->db_type == old_db_type)
+ thd->lex->part_info= table->s->part_info;
+ if (thd->lex->part_info)
+ {
+ /*
+ Need to cater for engine types that can handle partition without
+ using the partition handler.
+ */
+ thd->lex->part_info->default_engine_type= create_info->db_type;
+ create_info->db_type= DB_TYPE_PARTITION_DB;
+ }
if (check_engine(thd, new_name, &create_info->db_type))
DBUG_RETURN(TRUE);
new_db_type= create_info->db_type;
--- 1.162/sql/sql_update.cc 2005-06-06 23:36:59 +02:00
+++ 1.163/sql/sql_update.cc 2005-07-13 22:33:39 +02:00
@@ -146,7 +146,7 @@
/* pass counter value */
thd->lex->table_count= table_count;
/* convert to multiupdate */
- return 2;
+ DBUG_RETURN(2);
}
if (lock_tables(thd, table_list, table_count) ||
@@ -269,6 +269,10 @@
else
used_key_is_modified=0;
+#ifdef HAVE_PARTITION_DB
+ if (used_key_is_modified || order ||
+ partition_key_modified(table, fields))
+#else
if (used_key_is_modified || order)
{
/*
@@ -454,8 +458,8 @@
call then it should be included in the count of dup_key_found
and error should be set to 0 (only if these errors are ignored).
*/
- error= table->file->bulk_update_row(table->record[0],
- table->record[1],
+ error= table->file->bulk_update_row(table->record[1],
+ table->record[0],
&dup_key_found);
limit+= dup_key_found;
updated-= dup_key_found;
--- 1.394/sql/sql_yacc.yy 2005-06-23 12:20:00 +02:00
+++ 1.395/sql/sql_yacc.yy 2005-07-13 22:33:39 +02:00
@@ -356,13 +356,16 @@
%token LEAVES
%token LEAVE_SYM
%token LEFT
+%token LESS_SYM
%token LEVEL_SYM
%token LEX_HOSTNAME
%token LIKE
%token LIMIT
+%token LINEAR_SYM
%token LINEFROMTEXT
%token LINES
%token LINESTRING
+%token LIST_SYM
%token LOAD
%token LOCAL_SYM
%token LOCATE
@@ -402,6 +405,7 @@
%token MAX_SYM
%token MAX_UPDATES_PER_HOUR
%token MAX_USER_CONNECTIONS_SYM
+%token MAX_VALUE_SYM
%token MEDIUMBLOB
%token MEDIUMINT
%token MEDIUMTEXT
@@ -436,6 +440,7 @@
%token NE
%token NEW_SYM
%token NEXT_SYM
+%token NODEGROUP_SYM
%token NONE_SYM
%token NOT2_SYM
%token NOT_SYM
@@ -464,6 +469,8 @@
%token OUT_SYM
%token PACK_KEYS_SYM
%token PARTIAL
+%token PARTITION_SYM
+%token PARTITIONS_SYM
%token PASSWORD
%token PHASE_SYM
%token POINTFROMTEXT
@@ -489,6 +496,7 @@
%token RAID_STRIPED_SYM
%token RAID_TYPE
%token RAND
+%token RANGE_SYM
%token READS_SYM
%token READ_SYM
%token REAL
@@ -574,6 +582,8 @@
%token STRING_SYM
%token SUBDATE_SYM
%token SUBJECT_SYM
+%token SUBPARTITION_SYM
+%token SUBPARTITIONS_SYM
%token SUBSTRING
%token SUBSTRING_INDEX
%token SUM_SYM
@@ -594,6 +604,7 @@
%token TINYBLOB
%token TINYINT
%token TINYTEXT
+%token THAN_SYM
%token TO_SYM
%token TRAILING
%token TRANSACTION_SYM
@@ -617,11 +628,8 @@
%token UNIX_TIMESTAMP
%token UNKNOWN_SYM
%token UNLOCK_SYM
-%token UNLOCK_SYM
%token UNSIGNED
%token UNTIL_SYM
-%token UNTIL_SYM
-%token UPDATE_SYM
%token UPDATE_SYM
%token USAGE
%token USER
@@ -820,6 +828,7 @@
statement sp_suid opt_view_list view_list or_replace algorithm
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
+ partition_entry
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -885,6 +894,7 @@
| lock
| optimize
| keycache
+ | partition_entry
| preload
| prepare
| purge
@@ -2528,7 +2538,9 @@
create2:
'(' create2a {}
- | opt_create_table_options create3 {}
+ | opt_create_table_options
+ opt_partitioning {}
+ create3 {}
| LIKE table_ident
{
LEX *lex=Lex;
@@ -2544,8 +2556,12 @@
;
create2a:
- field_list ')' opt_create_table_options create3 {}
- | create_select ')' { Select->set_braces(1);} union_opt {}
+ field_list ')' opt_create_table_options
+ opt_partitioning {}
+ create3 {}
+ | opt_partitioning {}
+ create_select ')'
+ { Select->set_braces(1);} union_opt {}
;
create3:
@@ -2556,6 +2572,403 @@
{ Select->set_braces(1);} union_opt {}
;
+/*
+ This part of the parser is about handling of the partition information.
+
+ It's first version was written by Mikael Ronström with lots of answers to
+ questions provided by Antony Curtis.
+
+ The partition grammar can be called from three places.
+ 1) CREATE TABLE ... PARTITION ..
+ 2) ALTER TABLE table_name PARTITION ...
+ 3) PARTITION ...
+
+ The first place is called when a new table is created from a MySQL client.
+ The second place is called when a table is altered with the ALTER TABLE
+ command from a MySQL client.
+ The third place is called when opening an frm file and finding partition
+ info in the .frm file. It is necessary to avoid allowing PARTITION to be
+ an allowed entry point for SQL client queries. This is arranged by setting
+ some state variables before arriving here.
+
+ To be able to handle errors we will only set error code in this code
+ and handle the error condition in the function calling the parser. This
+ is necessary to ensure we can also handle errors when calling the parser
+ from the openfrm function.
+*/
+opt_partitioning:
+ /* empty */ {}
+ | partitioning
+ ;
+
+partitioning:
+ PARTITION_SYM
+ { Lex->part_info= new partition_info(); }
+ partition
+ ;
+
+partition_entry:
+ PARTITION_SYM
+ {
+ LEX *lex= Lex;
+ if (lex->part_info)
+ {
+ /*
+ We enter here when opening the frm file to translate
+ partition info string into part_info data structure.
+ */
+ lex->part_info= new partition_info();
+ }
+ else
+ {
+ yyerror(ER(ER_PARTITION_ENTRY_ERROR));
+ YYABORT;
+ }
+ }
+ partition {};
+
+partition:
+ BY part_type_def opt_no_parts {} opt_sub_part {} part_defs;
+
+part_type_def:
+ opt_linear KEY_SYM '(' part_field_list ')'
+ {
+ LEX *lex= Lex;
+ lex->part_info->list_of_part_fields= TRUE;
+ lex->part_info->part_type= HASH_PARTITION;
+ }
+ | opt_linear HASH_SYM
+ { Lex->part_info->part_type= HASH_PARTITION; }
+ part_func {}
+ | RANGE_SYM
+ { Lex->part_info->part_type= RANGE_PARTITION; }
+ part_func {}
+ | LIST_SYM
+ { Lex->part_info->part_type= LIST_PARTITION; }
+ part_func {};
+
+opt_linear:
+ /* empty */ {}
+ | LINEAR_SYM
+ { Lex->part_info->linear_hash_ind= TRUE;};
+
+part_field_list:
+ part_field_item {}
+ | part_field_list ',' part_field_item {};
+
+part_field_item:
+ ident
+ {
+ Lex->part_info->part_field_list.push_back($1.str);
+ };
+
+part_func:
+ '(' remember_name part_func_expr remember_end ')'
+ {
+ LEX *lex= Lex;
+ uint expr_len= (uint)($4 - $2) - 1;
+ lex->part_info->list_of_part_fields= FALSE;
+ lex->part_info->part_expr= $3;
+ lex->part_info->part_func_string= $2+1;
+ lex->part_info->part_func_len= expr_len;
+ };
+
+sub_part_func:
+ '(' remember_name part_func_expr remember_end ')'
+ {
+ LEX *lex= Lex;
+ uint expr_len= (uint)($4 - $2) - 1;
+ lex->part_info->list_of_subpart_fields= FALSE;
+ lex->part_info->subpart_expr= $3;
+ lex->part_info->subpart_func_string= $2+1;
+ lex->part_info->subpart_func_len= expr_len;
+ };
+
+
+opt_no_parts:
+ /* empty */ {}
+ | PARTITIONS_SYM ulong_num
+ {
+ uint no_parts= $2;
+ if (no_parts == 0)
+ {
+ my_error(ER_NO_PARTS_ERROR, MYF(0), "partitions");
+ YYABORT;
+ }
+ Lex->part_info->no_parts= no_parts;
+ };
+
+opt_sub_part:
+ /* empty */ {}
+ | SUBPARTITION_SYM BY opt_linear HASH_SYM sub_part_func
+ { Lex->part_info->subpart_type= HASH_PARTITION; }
+ opt_no_subparts {}
+ | SUBPARTITION_SYM BY opt_linear KEY_SYM
+ '(' sub_part_field_list ')'
+ {
+ LEX *lex= Lex;
+ lex->part_info->subpart_type= HASH_PARTITION;
+ lex->part_info->list_of_subpart_fields= TRUE;
+ }
+ opt_no_subparts {};
+
+sub_part_field_list:
+ sub_part_field_item {}
+ | sub_part_field_list ',' sub_part_field_item {};
+
+sub_part_field_item:
+ ident
+ { Lex->part_info->subpart_field_list.push_back($1.str); };
+
+part_func_expr:
+ bit_expr
+ {
+ LEX *lex= Lex;
+ bool not_corr_func;
+ not_corr_func= !lex->safe_to_cache_query;
+ lex->safe_to_cache_query= 1;
+ if (not_corr_func)
+ {
+ yyerror(ER(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR));
+ YYABORT;
+ }
+ $$=$1;
+ }
+
+opt_no_subparts:
+ /* empty */ {}
+ | SUBPARTITIONS_SYM ulong_num
+ {
+ uint no_parts= $2;
+ if (no_parts == 0)
+ {
+ my_error(ER_NO_PARTS_ERROR, MYF(0), "subpartitions");
+ YYABORT;
+ }
+ Lex->part_info->no_subparts= no_parts;
+ };
+
+part_defs:
+ /* empty */
+ {}
+ | '(' part_def_list ')'
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ if (part_info->no_parts != 0)
+ {
+ if (part_info->no_parts !=
+ part_info->count_curr_parts)
+ {
+ yyerror(ER(ER_PARTITION_WRONG_NO_PART_ERROR));
+ YYABORT;
+ }
+ }
+ else if (part_info->count_curr_parts > 0)
+ {
+ part_info->no_parts= part_info->count_curr_parts;
+ }
+ part_info->count_curr_subparts= 0;
+ part_info->count_curr_parts= 0;
+ };
+
+part_def_list:
+ part_definition {}
+ | part_def_list ',' part_definition {};
+
+part_definition:
+ PARTITION_SYM
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ partition_element *p_elem= new partition_element();
+ if (!p_elem)
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_element));
+ YYABORT;
+ }
+ part_info->curr_part_elem= p_elem;
+ part_info->current_partition= p_elem;
+ part_info->use_default_partitions= FALSE;
+ part_info->partitions.push_back(p_elem);
+ p_elem->engine_type= DB_TYPE_UNKNOWN;
+ part_info->count_curr_parts++;
+ }
+ part_name {}
+ opt_part_values {}
+ opt_part_options {}
+ opt_sub_partition {};
+
+part_name:
+ ident_or_text
+ { Lex->part_info->curr_part_elem->partition_name= $1.str; };
+
+opt_part_values:
+ /* empty */
+ {
+ LEX *lex= Lex;
+ if (lex->part_info->part_type == RANGE_PARTITION)
+ {
+ my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN");
+ YYABORT;
+ }
+ if (lex->part_info->part_type == LIST_PARTITION)
+ {
+ my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "LIST", "IN");
+ YYABORT;
+ }
+ }
+ | VALUES LESS_SYM THAN_SYM part_func_max
+ {
+ if (Lex->part_info->part_type != RANGE_PARTITION)
+ {
+ my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN");
+ YYABORT;
+ }
+ }
+ | VALUES IN_SYM '(' part_list_func ')'
+ {
+ if (Lex->part_info->part_type != LIST_PARTITION)
+ {
+ my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "LIST", "IN");
+ YYABORT;
+ }
+ };
+
+part_func_max:
+ MAX_VALUE_SYM
+ {
+ LEX *lex= Lex;
+ if (lex->part_info->defined_max_value)
+ {
+ yyerror(ER(ER_PARTITION_MAXVALUE_ERROR));
+ YYABORT;
+ }
+ lex->part_info->defined_max_value= TRUE;
+ }
+ | part_range_func
+ {
+ if (Lex->part_info->defined_max_value)
+ {
+ yyerror(ER(ER_PARTITION_MAXVALUE_ERROR));
+ YYABORT;
+ }
+ };
+
+part_range_func:
+ '(' part_bit_expr ')'
+ {
+ Lex->part_info->curr_part_elem->range_expr= $2;
+ };
+
+part_list_func:
+ part_list_item {}
+ | part_list_func ',' part_list_item {};
+
+part_list_item:
+ part_bit_expr
+ {
+ Lex->part_info->curr_part_elem->list_expr_list.push_back($1);
+ };
+
+part_bit_expr:
+ bit_expr
+ {
+ bool not_corr_func;
+ $1->fix_fields(YYTHD, (TABLE_LIST*)0, (Item**)0);
+ not_corr_func= !$1->const_item() || !Lex->safe_to_cache_query;
+ Lex->safe_to_cache_query= 1;
+ if (not_corr_func)
+ {
+ yyerror(ER(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR));
+ YYABORT;
+ }
+ $$= $1;
+ }
+
+opt_sub_partition:
+ /* empty */ {}
+ | '(' sub_part_list ')'
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ if (part_info->no_subparts != 0)
+ {
+ if (part_info->no_subparts !=
+ part_info->count_curr_subparts)
+ {
+ yyerror(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR));
+ YYABORT;
+ }
+ }
+ else if (part_info->count_curr_subparts > 0)
+ {
+ part_info->no_subparts= part_info->count_curr_subparts;
+ }
+ part_info->count_curr_subparts= 0;
+ };
+
+sub_part_list:
+ sub_part_definition {}
+ | sub_part_list ',' sub_part_definition {};
+
+sub_part_definition:
+ SUBPARTITION_SYM
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ partition_element *p_elem= new partition_element();
+ if (!p_elem)
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_element));
+ YYABORT;
+ }
+ part_info->curr_part_elem= p_elem;
+ part_info->current_partition->subpartitions.push_back(p_elem);
+ part_info->use_default_subpartitions= FALSE;
+ part_info->count_curr_subparts++;
+ p_elem->engine_type= DB_TYPE_UNKNOWN;
+ }
+ sub_name opt_part_options {};
+
+sub_name:
+ ident_or_text
+ { Lex->part_info->curr_part_elem->partition_name= $1.str; };
+
+opt_part_options:
+ /* empty */ {}
+ | opt_part_option_list {};
+
+opt_part_option_list:
+ opt_part_option_list opt_part_option {}
+ | opt_part_option {};
+
+opt_part_option:
+ TABLESPACE opt_equal ident_or_text
+ { Lex->part_info->curr_part_elem->tablespace_name= $3.str; }
+ | opt_storage ENGINE_SYM opt_equal storage_engines
+ { Lex->part_info->curr_part_elem->engine_type= $4; }
+ | NODEGROUP_SYM opt_equal ulong_num
+ { Lex->part_info->curr_part_elem->nodegroup_id= $3; }
+ | MAX_ROWS opt_equal ulonglong_num
+ { Lex->part_info->curr_part_elem->part_max_rows= $3; }
+ | MIN_ROWS opt_equal ulonglong_num
+ { Lex->part_info->curr_part_elem->part_min_rows= $3; }
+ | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
+ { Lex->part_info->curr_part_elem->data_file_name= $4.str; }
+ | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
+ { Lex->part_info->curr_part_elem->index_file_name= $4.str; }
+ | COMMENT_SYM opt_equal TEXT_STRING_sys
+ { Lex->part_info->curr_part_elem->part_comment= $3.str; };
+
+/*
+ End of partition parser part
+*/
+
create_select:
SELECT_SYM
{
@@ -3328,7 +3741,7 @@
lex->alter_info.reset();
lex->alter_info.flags= 0;
}
- alter_list
+ alter_commands
{}
| ALTER DATABASE ident_or_empty
{
@@ -3395,11 +3808,18 @@
/* empty */ { $$= 0; }
| ident { $$= $1.str; };
-alter_list:
+alter_commands:
| DISCARD TABLESPACE { Lex->alter_info.tablespace_op= DISCARD_TABLESPACE; }
| IMPORT TABLESPACE { Lex->alter_info.tablespace_op= IMPORT_TABLESPACE; }
- | alter_list_item
- | alter_list ',' alter_list_item;
+ | alter_list
+ opt_partitioning
+ | partitioning
+ ;
+
+alter_list:
+ alter_list_item
+ | alter_list ',' alter_list_item
+ ;
add_column:
ADD opt_column
--- 1.171/sql/table.cc 2005-06-22 16:12:31 +02:00
+++ 1.172/sql/table.cc 2005-07-13 22:33:40 +02:00
@@ -70,7 +70,7 @@
int j,error, errarg= 0;
uint rec_buff_length,n_length,int_length,records,key_parts,keys,
interval_count,interval_parts,read_length,db_create_options;
- uint key_info_length, com_length;
+ uint key_info_length, com_length, part_info_len, extra_rec_buf_length;
ulong pos;
char index_file[FN_REFLEN], *names, *keynames, *comment_pos;
uchar head[288],*disk_buff,new_field_pack_flag;
@@ -153,6 +153,7 @@
goto err; /* purecov: inspected */
*fn_ext(index_file)='\0'; // Remove .frm extension
+ part_info_len= uint4korr(head+55);
share->frm_version= head[2];
/*
Check if .frm file created by MySQL 5.0. In this case we want to
@@ -300,10 +301,6 @@
}
#endif
- /* Allocate handler */
- if (!(outparam->file= get_new_handler(outparam, share->db_type)))
- goto err;
-
error=4;
outparam->reginfo.lock_type= TL_UNLOCK;
outparam->current_lock=F_UNLCK;
@@ -314,8 +311,9 @@
if (prgflag & (READ_ALL+EXTRA_RECORD))
records++;
/* QQ: TODO, remove the +1 from below */
+ extra_rec_buf_length= uint2korr(head+59);
rec_buff_length= ALIGN_SIZE(share->reclength + 1 +
- outparam->file->extra_rec_buf_length());
+ extra_rec_buf_length);
share->rec_buff_length= rec_buff_length;
if (!(record= (char *) alloc_root(&outparam->mem_root,
rec_buff_length * records)))
@@ -435,9 +433,20 @@
if (keynames)
fix_type_pointers(&int_array, &share->keynames, 1, &keynames);
+ if (part_info_len > 0) {
+#ifdef HAVE_PARTITION_DB
+ if (mysql_unpack_partition(file, thd, part_info_len, outparam))
+ goto err;
+#else
+ goto err;
+#endif
VOID(my_close(file,MYF(MY_WME)));
file= -1;
+ /* Allocate handler */
+ if (!(outparam->file= get_new_handler(outparam, share->db_type)))
+ goto err;
+
record= (char*) outparam->record[0]-1; /* Fieldstart = 1 */
if (null_field_first)
{
@@ -857,6 +866,13 @@
if (outparam->file->ha_allocate_read_write_set(share->fields))
goto err;
+ /* Fix the partition functions and ensure they are not constant functions*/
+ if (part_info_len > 0)
+#ifdef HAVE_PARTITION_DB
+ if (fix_partition_func(thd,name,outparam))
+#endif
+ goto err;
+
/* The table struct is now initialized; Open the table */
error=2;
if (db_stat)
@@ -914,6 +930,13 @@
if (! error_reported)
frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG, errarg);
delete outparam->file;
+#ifdef HAVE_PARTITION_DB
+ if (outparam->s->part_info)
+ {
+ free_items(outparam->s->part_info->item_free_list);
+ outparam->s->part_info->item_free_list= 0;
+ }
+#endif
outparam->file=0; // For easier errorchecking
outparam->db_stat=0;
hash_free(&share->name_hash);
@@ -940,6 +963,13 @@
table->field= 0;
}
delete table->file;
+#ifdef HAVE_PARTITION_DB
+ if (table->s->part_info)
+ {
+ free_items(table->s->part_info->item_free_list);
+ table->s->part_info->item_free_list= 0;
+ }
+#endif
table->file= 0; /* For easier errorchecking */
hash_free(&table->s->name_hash);
free_root(&table->mem_root, MYF(0));
--- 1.100/sql/table.h 2005-06-01 15:35:04 +02:00
+++ 1.101/sql/table.h 2005-07-13 22:33:40 +02:00
@@ -21,6 +21,7 @@
class GRANT_TABLE;
class st_select_lex_unit;
class st_select_lex;
+class partition_info;
class COND_EQUAL;
/* Order clause list element */
@@ -96,6 +97,9 @@
typedef struct st_table_share
{
+#ifdef HAVE_PARTITION_DB
+ partition_info *part_info; /* Partition related information */
+#endif
/* hash of field names (contains pointers to elements of field array) */
HASH name_hash; /* hash of field names */
MEM_ROOT mem_root;
@@ -196,6 +200,8 @@
ORDER *group;
const char *alias; /* alias or table name */
uchar *null_flags;
+ MY_BITMAP *read_set;
+ MY_BITMAP *write_set;
query_id_t query_id;
ha_rows quick_rows[MAX_KEY];
@@ -249,6 +255,7 @@
my_bool auto_increment_field_not_null;
my_bool insert_or_update; /* Can be used by the handler */
my_bool alias_name_used; /* true if table_name is alias */
+ my_bool get_fields_in_item_tree; /* Signal to fix_field */
REGINFO reginfo; /* field connections */
MEM_ROOT mem_root;
--- 1.61/sql/unireg.cc 2005-06-18 09:21:48 +02:00
+++ 1.62/sql/unireg.cc 2005-07-13 22:33:41 +02:00
@@ -46,7 +46,8 @@
static bool make_empty_rec(THD *thd, int file, enum db_type table_type,
uint table_options,
List<create_field> &create_fields,
- uint reclength, ulong data_offset);
+ uint reclength, ulong data_offset,
+ handler *handler);
/*
Create a frm (table definition) file
@@ -79,13 +80,18 @@
uchar fileinfo[64],forminfo[288],*keybuff;
TYPELIB formnames;
uchar *screen_buff;
+#ifdef HAVE_PARTITION_DB
+ partition_info *part_info= thd->lex->part_info;
+#endif
DBUG_ENTER("mysql_create_frm");
+#ifdef HAVE_PARTITION_DB
+ thd->lex->part_info= NULL;
+#endif
formnames.type_names=0;
if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0)))
DBUG_RETURN(1);
- if (db_file == NULL)
- db_file= get_new_handler((TABLE*) 0, create_info->db_type);
+ DBUG_ASSERT(db_file != NULL);
/* If fixed row records, we need one bit to check for deleted rows */
if (!(create_info->table_options & HA_OPTION_PACK_RECORD))
@@ -136,6 +142,13 @@
60);
forminfo[46]=(uchar) strlen((char*)forminfo+47); // Length of comment
+#ifdef HAVE_PARTITION_DB
+ if (part_info)
+ {
+ int4store(fileinfo+55,part_info->part_info_len);
+ }
+#endif
+ int2store(fileinfo+59,db_file->extra_rec_buf_length());
if (my_pwrite(file,(byte*) fileinfo,64,0L,MYF_RW) ||
my_pwrite(file,(byte*) keybuff,key_info_length,
(ulong) uint2korr(fileinfo+6),MYF_RW))
@@ -144,7 +157,7 @@
(ulong) uint2korr(fileinfo+6)+ (ulong) key_buff_length,
MY_SEEK_SET,MYF(0)));
if (make_empty_rec(thd,file,create_info->db_type,create_info->table_options,
- create_fields,reclength, data_offset))
+ create_fields,reclength, data_offset, db_file))
goto err;
VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
@@ -153,6 +166,14 @@
pack_fields(file, create_fields, data_offset))
goto err;
+#ifdef HAVE_PARTITION_DB
+ if (part_info)
+ {
+ if (my_write(file, (byte*) part_info->part_info_string,
+ part_info->part_info_len, MYF_RW))
+ goto err;
+ }
+#endif
#ifdef HAVE_CRYPTED_FRM
if (create_info->password)
{
@@ -211,15 +232,14 @@
Create a frm (table definition) file and the tables
SYNOPSIS
- mysql_create_frm()
+ rea_create_table()
thd Thread handler
file_name Name of file (including database and .frm)
create_info create info parameters
create_fields Fields to create
keys number of keys to create
key_info Keys to create
- db_file Handler to use. May be zero, in which case we use
- create_info->db_type
+ file Handler to use.
RETURN
0 ok
1 error
@@ -228,19 +248,21 @@
int rea_create_table(THD *thd, my_string file_name,
HA_CREATE_INFO *create_info,
List<create_field> &create_fields,
- uint keys, KEY *key_info)
+ uint keys, KEY *key_info, handler *file)
{
DBUG_ENTER("rea_create_table");
if (mysql_create_frm(thd, file_name, create_info,
- create_fields, keys, key_info, NULL))
+ create_fields, keys, key_info, file))
DBUG_RETURN(1);
+ if (file->create_handler_files(file_name))
+ goto err_handler;
if (!create_info->frm_only && ha_create_table(file_name,create_info,0))
- {
- my_delete(file_name,MYF(0));
- DBUG_RETURN(1);
- }
+ goto err_handler;
DBUG_RETURN(0);
+err_handler:
+ my_delete(file_name, MYF(0));
+ DBUG_RETURN(1);
} /* rea_create_table */
@@ -664,7 +686,8 @@
uint table_options,
List<create_field> &create_fields,
uint reclength,
- ulong data_offset)
+ ulong data_offset,
+ handler *handler)
{
int error;
Field::utype type;
@@ -672,19 +695,15 @@
uchar *buff,*null_pos;
TABLE table;
create_field *field;
- handler *handler;
enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
DBUG_ENTER("make_empty_rec");
/* We need a table to generate columns for default values */
bzero((char*) &table,sizeof(table));
table.s= &table.share_not_to_be_used;
- handler= get_new_handler((TABLE*) 0, table_type);
- if (!handler ||
- !(buff=(uchar*) my_malloc((uint) reclength,MYF(MY_WME | MY_ZEROFILL))))
+ if (!(buff=(uchar*) my_malloc((uint) reclength,MYF(MY_WME | MY_ZEROFILL))))
{
- delete handler;
DBUG_RETURN(1);
}
@@ -771,7 +790,6 @@
err:
my_free((gptr) buff,MYF(MY_FAE));
- delete handler;
thd->count_cuted_fields= old_count_cuted_fields;
DBUG_RETURN(error);
} /* make_empty_rec */
--- 1.39/sql/unireg.h 2005-02-07 18:38:45 +01:00
+++ 1.40/sql/unireg.h 2005-07-13 22:33:41 +02:00
@@ -80,6 +80,7 @@
#define PSEUDO_TABLE_BITS (PARAM_TABLE_BIT | OUTER_REF_TABLE_BIT | \
RAND_TABLE_BIT)
#define MAX_FIELDS 4096 /* Limit in the .frm file */
+#define MAX_PARTITIONS 1024
#define MAX_SORT_MEMORY (2048*1024-MALLOC_OVERHEAD)
#define MIN_SORT_MEMORY (32*1024-MALLOC_OVERHEAD)
--- 1.34/sql/share/errmsg.txt 2005-06-20 13:38:09 +02:00
+++ 1.35/sql/share/errmsg.txt 2005-07-13 22:33:36 +02:00
@@ -5358,3 +5358,81 @@
eng "The statement (%lu) has no open cursor."
ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
eng "Explicit or implicit commit is not allowed in stored function or trigger."
+ER_PARTITION_REQUIRES_VALUES_ERROR
+ eng "%s PARTITIONING requires definition of VALUES %s for each partition"
+ swe "%s PARTITIONering kräver definition av VALUES %s för varje partition"
+ER_PARTITION_WRONG_VALUES_ERROR
+ eng "Only %s PARTITIONING can use VALUES %s in partition definition"
+ swe "Endast %s partitionering kan använda VALUES %s i definition av partitionen"
+ER_PARTITION_MAXVALUE_ERROR
+ eng "MAXVALUE can only be used in last partition definition"
+ swe "MAXVALUE kan bara användas i definitionen av den sista partitionen"
+ER_PARTITION_SUBPARTITION_ERROR
+ eng "Subpartitions can only be hash partitions and by key"
+ swe "Subpartitioner kan bara vara hash och key partitioner"
+ER_PARTITION_WRONG_NO_PART_ERROR
+ eng "Wrong number of partitions defined, mismatch with previous setting"
+ swe "Antal partitioner definierade och antal partitioner är inte lika"
+ER_PARTITION_WRONG_NO_SUBPART_ERROR
+ eng "Wrong number of subpartitions defined, mismatch with previous setting"
+ swe "Antal subpartitioner definierade och antal subpartitioner är inte lika"
+ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR
+ eng "Constant/Random expression in (sub)partitioning function is not allowed"
+ swe "Konstanta uttryck eller slumpmässiga uttryck är inte tillåtna
(sub)partitioneringsfunktioner"
+ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR
+ eng "Expression in RANGE/LIST VALUES must be constant"
+ swe "Uttryck i RANGE/LIST VALUES måste vara ett konstant uttryck"
+ER_FIELD_NOT_FOUND_PART_ERROR
+ eng "Field in list of fields for partition function not found in table"
+ swe "Fält i listan av fält för partitionering med key inte funnen i tabellen"
+ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR
+ eng "List of fields is only allowed in KEY partitions"
+ swe "En lista av fält är endast tillåtet för KEY partitioner"
+ER_INCONSISTENT_PARTITION_INFO_ERROR
+ eng "The partition info in the frm file is not consistent with what can be
written into the frm file"
+ swe "Partitioneringsinformationen i frm-filen är inte konsistent med vad som kan
skrivas i frm-filen"
+ER_PARTITION_FUNC_NOT_ALLOWED_ERROR
+ eng "The %s function returns the wrong type"
+ swe "%s-funktionen returnerar felaktig typ"
+ER_PARTITIONS_MUST_BE_DEFINED_ERROR
+ eng "For %s partitions each partition must be defined"
+ swe "För %s partitionering så måste varje partition definieras"
+ER_RANGE_NOT_INCREASING_ERROR
+ eng "VALUES LESS THAN value must be strictly increasing for each partition"
+ swe "Värden i VALUES LESS THAN måste vara strikt växande för varje partition"
+ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR
+ eng "VALUES %s value must be of same type as partition function"
+ swe "Värden i VALUES %s måste vara av samma typ som partitioneringsfunktionen"
+ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR
+ eng "Multiple definition of same constant in list partitioning"
+ swe "Multipel definition av samma konstant i list partitionering"
+ER_PARTITION_ENTRY_ERROR
+ eng "Partitioning can not be used stand-alone in query"
+ swe "Partitioneringssyntax kan inte användas på egen hand i en SQL-fråga"
+ER_MIX_HANDLER_ERROR
+ eng "The mix of handlers in the partitions is not allowed in this version in
MySQL"
+ swe "Denna mix av lagringsmotorer är inte tillåten i denna version av MySQL"
+ER_PARTITION_NOT_DEFINED_ERROR
+ eng "For the partitioned engine it is necessary to define all %s"
+ swe "För partitioneringsmotorn så är det nödvändigt att definiera alla %s"
+ER_TOO_MANY_PARTITIONS_ERROR
+ eng "Too many partitions were defined"
+ swe "För många partitioner definierades"
+ER_SUBPARTITION_ERROR
+ eng "It is only possible to mix RANGE/LIST partitioning with HASH/KEY
partitioning for subpartitioning"
+ swe "Det är endast möjligt att blanda RANGE/LIST partitionering med HASH/KEY
partitionering för subpartitionering"
+ER_CANT_CREATE_HANDLER_FILE
+ eng "Failed to create specific handler file"
+ swe "Misslyckades med att skapa specifik fil i lagringsmotor"
+ER_BLOB_FIELD_IN_PART_FUNC_ERROR
+ eng "A BLOB field is not allowed in partition function"
+ swe "Ett BLOB-fält är inte tillåtet i partitioneringsfunktioner"
+ER_CHAR_SET_IN_PART_FIELD_ERROR
+ eng "VARCHAR only allowed if binary collation for partition functions"
+ swe "VARCHAR endast tillåten med binär collation för partitioneringsfunktion"
+ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF
+ eng "A %s need to include all fields in the partition function"
+ swe "En %s behöver inkludera alla fält i partitioneringsfunktionen för denna
lagringsmotor"
+ER_NO_PARTS_ERROR
+ eng "Number of %s = 0 is not an allowed value"
+ swe "Antal %s = 0 är inte ett tillåten värde"
--- 1.110/sql/item_subselect.cc 2005-06-15 19:58:21 +02:00
+++ 1.111/sql/item_subselect.cc 2005-07-13 22:33:34 +02:00
@@ -1495,7 +1495,7 @@
}
if (!table->file->inited)
- table->file->ha_index_init(tab->ref.key);
+ table->file->ha_index_init(tab->ref.key, 0);
error= table->file->index_read(table->record[0],
tab->ref.key_buff,
tab->ref.key_length,HA_READ_KEY_EXACT);
@@ -1548,7 +1548,7 @@
}
if (!table->file->inited)
- table->file->ha_index_init(tab->ref.key);
+ table->file->ha_index_init(tab->ref.key, 1);
error= table->file->index_read(table->record[0],
tab->ref.key_buff,
tab->ref.key_length,HA_READ_KEY_EXACT);
--- 1.6/config/ac-macros/ha_ndbcluster.m4 2005-04-27 04:04:31 +02:00
+++ 1.7/config/ac-macros/ha_ndbcluster.m4 2005-07-13 22:33:29 +02:00
@@ -128,8 +128,9 @@
ndb_mgmclient_libs=
case "$ndbcluster" in
yes )
- AC_MSG_RESULT([Using NDB Cluster])
+ AC_MSG_RESULT([Using NDB Cluster and Partitioning])
AC_DEFINE([HAVE_NDBCLUSTER_DB], [1], [Using Ndb Cluster DB])
+ AC_DEFINE([HAVE_PARTITION_DB], [1], [Builds Partition DB])
have_ndbcluster="yes"
ndbcluster_includes="-I\$(top_builddir)/storage/ndb/include
-I\$(top_builddir)/storage/ndb/include/ndbapi"
ndbcluster_libs="\$(top_builddir)/storage/ndb/src/.libs/libndbclient.a"
--- 1.24/sql/tztime.cc 2005-06-06 20:21:28 +02:00
+++ 1.25/sql/tztime.cc 2005-07-13 22:33:40 +02:00
@@ -1623,7 +1623,7 @@
mysql.time_zone* tables are MyISAM and these operations always succeed
for MyISAM.
*/
- (void)table->file->ha_index_init(0);
+ (void)table->file->ha_index_init(0, 1);
tz_leapcnt= 0;
res= table->file->index_first(table->record[0]);
@@ -1800,7 +1800,7 @@
mysql.time_zone* tables are MyISAM and these operations always succeed
for MyISAM.
*/
- (void)table->file->ha_index_init(0);
+ (void)table->file->ha_index_init(0, 1);
if (table->file->index_read(table->record[0],
(byte*)table->field[0]->ptr,
0, HA_READ_KEY_EXACT))
@@ -1827,7 +1827,7 @@
table= tz_tables->table;
tz_tables= tz_tables->next_local;
table->field[0]->store((longlong)tzid);
- (void)table->file->ha_index_init(0);
+ (void)table->file->ha_index_init(0, 1);
if (table->file->index_read(table->record[0],
(byte*)table->field[0]->ptr,
0, HA_READ_KEY_EXACT))
@@ -1854,7 +1854,7 @@
table= tz_tables->table;
tz_tables= tz_tables->next_local;
table->field[0]->store((longlong)tzid);
- (void)table->file->ha_index_init(0);
+ (void)table->file->ha_index_init(0, 1);
// FIXME Is there any better approach than explicitly specifying 4 ???
res= table->file->index_read(table->record[0],
(byte*)table->field[0]->ptr,
@@ -1926,7 +1926,7 @@
*/
table= tz_tables->table;
table->field[0]->store((longlong)tzid);
- (void)table->file->ha_index_init(0);
+ (void)table->file->ha_index_init(0, 1);
// FIXME Is there any better approach than explicitly specifying 4 ???
res= table->file->index_read(table->record[0],
(byte*)table->field[0]->ptr,
--- 1.31/mysys/my_bitmap.c 2005-06-02 22:10:51 +02:00
+++ 1.32/mysys/my_bitmap.c 2005-07-13 22:33:30 +02:00
@@ -20,20 +20,20 @@
API limitations (or, rather asserted safety assumptions,
to encourage correct programming)
- * the size of the used bitmap is less than ~(uint) 0
- * it's a multiple of 8 (for efficiency reasons)
- * when arguments are a bitmap and a bit number, the number
- must be within bitmap size
- * bitmap_set_prefix() is an exception - one can use ~0 to set all bits
- * when both arguments are bitmaps, they must be of the same size
- * bitmap_intersect() is an exception :)
- (for for Bitmap::intersect(ulonglong map2buff))
-
- If THREAD is defined all bitmap operations except bitmap_init/bitmap_free
- are thread-safe.
+ * the internal size is a set of 32 bit words
+ * the number of bits specified in creation can be any number > 0
+ * there are THREAD safe versions of most calls called bitmap_lock_*
+ many of those are not used and not compiled normally but the code
+ already exist for them in an #ifdef:ed part. These can only be used
+ if THREAD was specified in bitmap_init
TODO:
Make assembler THREAD safe versions of these using test-and-set instructions
+
+ Original version created by Sergei Golubchik 2001 - 2004.
+ New version written and test program added and some changes to the interface
+ was made by Mikael Ronström 2005, with assistance of Tomas Ulin and Mats
+ Kindahl.
*/
#include "mysys_priv.h"
@@ -1001,17 +1001,9 @@
}
/*
-This is the way the test part was compiled after a complete tree build with
-debug.
-
-gcc -DHAVE_CONFIG_H -I. -I. -I.. -I../include -I. -g -O -DDBUG_ON
--DSAFE_MUTEX -fno-omit-frame-pointer -DHAVE_DARWIN_THREADS
--D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DTEST_BITMAP
--DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT -MT
-my_bitmap.o -MD -MP -MF ".deps/my_bitmap.Tpo" -c -o my_bitmap.o my_bitmap.c
-
-gcc -o my_bitmap my_bitmap.o -L../mysys -lmysys -L../strings -lmystrings
--L../dbug -ldbug
+ In directory mysys:
+ make test_bitmap
+ will build the bitmap tests and ./test_bitmap will execute it
*/
#endif
--- 1.2/storage/ndb/test/run-test/README 2005-04-08 02:44:31 +02:00
+++ 1.3/storage/ndb/test/run-test/README 2005-07-13 22:33:46 +02:00
@@ -9,7 +9,7 @@
atrt has the following main loop:
/**
- * Psuedo code for atrt
+ * Pseudo code for atrt
*/
read config file (default d.txt)
contact each ndb_cpcd
@@ -36,7 +36,7 @@
done
/**
- * End of psuedo code
+ * End of pseudo code
*/
=================================
--- 1.8/storage/ndb/include/kernel/AttributeHeader.hpp 2005-04-08 02:43:49 +02:00
+++ 1.9/storage/ndb/include/kernel/AttributeHeader.hpp 2005-07-13 22:33:41 +02:00
@@ -30,9 +30,9 @@
public:
/**
- * Psuedo columns
+ * Pseudo columns
*/
- STATIC_CONST( PSUEDO = 0x8000 );
+ STATIC_CONST( PSEUDO = 0x8000 );
STATIC_CONST( FRAGMENT = 0xFFFE ); // Read fragment no
STATIC_CONST( ROW_COUNT = 0xFFFD ); // Read row count (committed)
STATIC_CONST( COMMIT_COUNT = 0xFFFC ); // Read commit count
--- 1.8/storage/ndb/include/kernel/GlobalSignalNumbers.h 2005-04-08 02:43:49 +02:00
+++ 1.9/storage/ndb/include/kernel/GlobalSignalNumbers.h 2005-07-13 22:33:41 +02:00
@@ -944,6 +944,6 @@
#define GSN_TUX_BOUND_INFO 710
#define GSN_ACC_LOCKREQ 711
-#define GSN_READ_PSUEDO_REQ 712
+#define GSN_READ_PSEUDO_REQ 712
#endif
--- 1.17/storage/ndb/include/kernel/ndb_limits.h 2005-05-20 06:25:00 +02:00
+++ 1.18/storage/ndb/include/kernel/ndb_limits.h 2005-07-13 22:33:41 +02:00
@@ -63,6 +63,7 @@
#define MAX_FRM_DATA_SIZE 6000
#define MAX_NULL_BITS 4096
#define MAX_FRAGMENT_DATA_BYTES (4+(2 * 8 * MAX_REPLICAS * MAX_NDB_NODES))
+#define MAX_NDB_PARTITIONS 1024
#define MIN_ATTRBUF ((MAX_ATTRIBUTES_IN_TABLE/24) + 1)
/*
--- 1.3/storage/ndb/include/kernel/signaldata/CreateFragmentation.hpp 2005-04-08 02:43:50
+02:00
+++ 1.4/storage/ndb/include/kernel/signaldata/CreateFragmentation.hpp 2005-07-13 22:33:42
+02:00
@@ -33,14 +33,13 @@
friend bool printCREATE_FRAGMENTATION_REQ(FILE *,
const Uint32 *, Uint32, Uint16);
public:
- STATIC_CONST( SignalLength = 6 );
+ STATIC_CONST( SignalLength = 5 );
private:
Uint32 senderRef;
Uint32 senderData;
Uint32 fragmentationType;
Uint32 noOfFragments;
- Uint32 fragmentNode;
Uint32 primaryTableId; // use same fragmentation as this table if not RNIL
};
--- 1.18/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp 2005-04-08 02:43:50 +02:00
+++ 1.19/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp 2005-07-13 22:33:42 +02:00
@@ -151,7 +151,10 @@
AllNodesSmallTable = 0,
AllNodesMediumTable = 1,
AllNodesLargeTable = 2,
- SingleFragment = 3
+ SingleFragment = 3,
+ DistrKeyHash = 4,
+ DistrKeyLin = 5,
+ UserDefined = 6
};
// TableType constants + objects
--- 1.2/storage/ndb/include/kernel/signaldata/FireTrigOrd.hpp 2005-04-08 02:43:50 +02:00
+++ 1.3/storage/ndb/include/kernel/signaldata/FireTrigOrd.hpp 2005-07-13 22:33:42 +02:00
@@ -52,9 +52,9 @@
friend bool printFIRE_TRIG_ORD(FILE * output, const Uint32 * theData, Uint32 len,
Uint16 receiverBlockNo);
public:
- STATIC_CONST( SignalLength = 7 );
- STATIC_CONST( SignalWithGCILength = 8 );
- STATIC_CONST( SignalWithHashValueLength = 9 );
+ STATIC_CONST( SignalLength = 8 );
+ STATIC_CONST( SignalWithGCILength = 9 );
+ STATIC_CONST( SignalWithHashValueLength = 10 );
private:
Uint32 m_connectionPtr;
@@ -64,6 +64,7 @@
Uint32 m_noPrimKeyWords;
Uint32 m_noBeforeValueWords;
Uint32 m_noAfterValueWords;
+ Uint32 fragId;
Uint32 m_gci;
Uint32 m_hashValue;
// Public methods
--- 1.50/storage/ndb/include/ndbapi/NdbDictionary.hpp 2005-05-02 13:18:23 +02:00
+++ 1.51/storage/ndb/include/ndbapi/NdbDictionary.hpp 2005-07-13 22:33:42 +02:00
@@ -614,6 +614,12 @@
const void* getFrmData() const;
Uint32 getFrmLength() const;
+ /**
+ * Get Node Group and Tablespace id's for fragments in table
+ */
+ const void *getNodeGroupIds() const;
+ Uint32 getNodeGroupIdsLength() const;
+
/** @} *******************************************************************/
/**
@@ -711,6 +717,11 @@
* Set frm file to store with this table
*/
void setFrm(const void* data, Uint32 len);
+
+ /**
+ * Set node group for fragments
+ */
+ void setNodeGroupIds(const void *data, Uint32 len);
/**
* Set table object type
--- 1.3/storage/ndb/src/common/debugger/signaldata/CreateFragmentation.cpp 2005-04-08
02:43:55 +02:00
+++ 1.4/storage/ndb/src/common/debugger/signaldata/CreateFragmentation.cpp 2005-07-13
22:33:43 +02:00
@@ -24,7 +24,6 @@
fprintf(output, " senderData: %x\n", sig->senderData);
fprintf(output, " fragmentationType: %x\n", sig->fragmentationType);
fprintf(output, " noOfFragments: %x\n", sig->noOfFragments);
- fprintf(output, " fragmentNode: %x\n", sig->fragmentNode);
if (sig->primaryTableId == RNIL)
fprintf(output, " primaryTableId: none\n");
else
--- 1.26/storage/ndb/tools/restore/Restore.cpp 2005-06-13 15:16:12 +02:00
+++ 1.27/storage/ndb/tools/restore/Restore.cpp 2005-07-13 22:33:47 +02:00
@@ -226,7 +226,7 @@
return false;
debug << "parseTableInfo " << tableImpl->getName() << " done"
<< endl;
-
+ tableImpl->m_ng.clear();
TableS * table = new TableS(m_fileHeader.NdbVersion, tableImpl);
if(table == NULL) {
return false;
--- 1.20/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp 2005-04-27 04:07:09 +02:00
+++ 1.21/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp 2005-07-13 22:33:43 +02:00
@@ -889,7 +889,7 @@
void execACC_OVER_REC(Signal* signal);
void execACC_SAVE_PAGES(Signal* signal);
void execNEXTOPERATION(Signal* signal);
- void execREAD_PSUEDO_REQ(Signal* signal);
+ void execREAD_PSEUDO_REQ(Signal* signal);
// Received signals
void execSTTOR(Signal* signal);
--- 1.14/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp 2005-05-02 13:19:45 +02:00
+++ 1.15/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp 2005-07-13 22:33:43 +02:00
@@ -165,7 +165,7 @@
addRecSignal(GSN_ACC_OVER_REC, &Dbacc::execACC_OVER_REC);
addRecSignal(GSN_ACC_SAVE_PAGES, &Dbacc::execACC_SAVE_PAGES);
addRecSignal(GSN_NEXTOPERATION, &Dbacc::execNEXTOPERATION);
- addRecSignal(GSN_READ_PSUEDO_REQ, &Dbacc::execREAD_PSUEDO_REQ);
+ addRecSignal(GSN_READ_PSEUDO_REQ, &Dbacc::execREAD_PSEUDO_REQ);
// Received signals
addRecSignal(GSN_STTOR, &Dbacc::execSTTOR);
--- 1.53/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp 2005-06-13 15:16:11 +02:00
+++ 1.54/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp 2005-07-13 22:33:43 +02:00
@@ -11788,7 +11788,7 @@
}//execSET_VAR_REQ()
void
-Dbacc::execREAD_PSUEDO_REQ(Signal* signal){
+Dbacc::execREAD_PSEUDO_REQ(Signal* signal){
jamEntry();
fragrecptr.i = signal->theData[0];
Uint32 attrId = signal->theData[1];
--- 1.45/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2005-05-17 10:10:43 +02:00
+++ 1.46/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2005-07-13 22:33:44 +02:00
@@ -271,7 +271,6 @@
req->senderData = RNIL;
req->fragmentationType = tablePtr.p->fragmentType;
req->noOfFragments = 0;
- req->fragmentNode = 0;
req->primaryTableId = tablePtr.i;
EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
CreateFragmentationReq::SignalLength);
@@ -1492,8 +1491,11 @@
tablePtr.p->gciTableCreated = 0;
tablePtr.p->noOfAttributes = ZNIL;
tablePtr.p->noOfNullAttr = 0;
+ tablePtr.p->ngLen = 0;
+ memset(tablePtr.p->ngData, 0, sizeof(tablePtr.p->ngData));
tablePtr.p->frmLen = 0;
memset(tablePtr.p->frmData, 0, sizeof(tablePtr.p->frmData));
+ tablePtr.p->fragmentCount = 0;
/*
tablePtr.p->lh3PageIndexBits = 0;
tablePtr.p->lh3DistrBits = 0;
@@ -2919,14 +2921,16 @@
createTabPtr.p->m_fragmentsPtrI = RNIL;
createTabPtr.p->m_dihAddFragPtr = RNIL;
- Uint32 * theData = signal->getDataPtrSend();
+ Uint32 *theData = signal->getDataPtrSend(), i;
+ Uint16 *node_group= (Uint16*)&signal->theData[25];
CreateFragmentationReq * const req = (CreateFragmentationReq*)theData;
req->senderRef = reference();
req->senderData = createTabPtr.p->key;
req->fragmentationType = parseRecord.tablePtr.p->fragmentType;
- req->noOfFragments = 0;
- req->fragmentNode = 0;
req->primaryTableId = RNIL;
+ req->noOfFragments = parseRecord.tablePtr.p->ngLen >> 1;
+ for (i = 0; i < req->noOfFragments; i++)
+ node_group[i] = parseRecord.tablePtr.p->ngData[i];
if (parseRecord.tablePtr.p->isOrderedIndex()) {
// ordered index has same fragmentation as the table
const Uint32 primaryTableId = parseRecord.tablePtr.p->primaryTableId;
@@ -2936,8 +2940,15 @@
req->fragmentationType = primaryTablePtr.p->fragmentType;
req->primaryTableId = primaryTableId;
}
- sendSignal(DBDIH_REF, GSN_CREATE_FRAGMENTATION_REQ, signal,
- CreateFragmentationReq::SignalLength, JBB);
+ EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
+ CreateFragmentationReq::SignalLength);
+ jamEntry();
+ if (signal->theData[0] != 0)
+ {
+ jam();
+ parseRecord.errorCode= signal->theData[0];
+ break;
+ }
c_blockState = BS_CREATE_TAB;
return;
@@ -4884,6 +4895,10 @@
tablePtr.p->frmLen = tableDesc.FrmLen;
memcpy(tablePtr.p->frmData, tableDesc.FrmData, tableDesc.FrmLen);
+ tablePtr.p->ngLen = tableDesc.FragmentDataLen;
+ memcpy(tablePtr.p->ngData, tableDesc.FragmentData,
+ tableDesc.FragmentDataLen);
+
if(tableDesc.PrimaryTableId != RNIL) {
tablePtr.p->primaryTableId = tableDesc.PrimaryTableId;
@@ -6645,7 +6660,7 @@
w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
- w.add(DictTabInfo::AttributeExtLength, tablePtr.p->tupKeyLength);
+ w.add(DictTabInfo::AttributeExtLength, tablePtr.p->tupKeyLength+1);
w.add(DictTabInfo::AttributeEnd, (Uint32)true);
}
if (indexPtr.p->isOrderedIndex()) {
@@ -11834,11 +11849,19 @@
* MODULE: Support routines for index and trigger.
*/
+/*
+ This routine is used to set-up the primary key attributes of the unique
+ hash index. Since we store fragment id as part of the primary key here
+ we insert the pseudo column for getting fragment id first in the array.
+ This routine is used as part of the building of the index.
+*/
+
void
Dbdict::getTableKeyList(TableRecordPtr tablePtr, AttributeList& list)
{
jam();
list.sz = 0;
+ list.id[list.sz++] = AttributeHeader::FRAGMENT;
for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
if (aRec->tupleKey)
--- 1.12/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp 2005-05-17 10:10:43 +02:00
+++ 1.13/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp 2005-07-13 22:33:44 +02:00
@@ -232,6 +232,10 @@
/** TODO Could preferrably be made dynamic size */
Uint32 frmLen;
char frmData[MAX_FRM_DATA_SIZE];
+ /** Node Group and Tablespace id for this table */
+ /** TODO Could preferrably be made dynamic size */
+ Uint32 ngLen;
+ Uint16 ngData[MAX_NDB_PARTITIONS];
Uint32 fragmentCount;
};
--- 1.9/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp 2005-04-08 02:44:03 +02:00
+++ 1.10/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp 2005-07-13 22:33:44 +02:00
@@ -469,8 +469,10 @@
TS_DROPPING = 3
};
enum Method {
- HASH = 0,
- NOTDEFINED = 1
+ LINEAR_HASH = 0,
+ NOTDEFINED = 1,
+ NORMAL_HASH = 2,
+ USER_HANDLED = 3
};
CopyStatus tabCopyStatus;
UpdateState tabUpdateState;
--- 1.29/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp 2005-06-13 15:16:11 +02:00
+++ 1.30/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp 2005-07-13 22:33:44 +02:00
@@ -6158,97 +6158,87 @@
3.7.1 A D D T A B L E M A I N L Y
***************************************
*/
-void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal){
+#define UNDEF_NODEGROUP 65535
+void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal)
+{
+ Uint16 node_group_id[MAX_NDB_PARTITIONS];
jamEntry();
CreateFragmentationReq * const req =
(CreateFragmentationReq*)signal->getDataPtr();
const Uint32 senderRef = req->senderRef;
const Uint32 senderData = req->senderData;
- const Uint32 fragmentNode = req->fragmentNode;
const Uint32 fragmentType = req->fragmentationType;
- //const Uint32 fragmentCount = req->noOfFragments;
+ const Uint32 fragmentCount = req->noOfFragments;
const Uint32 primaryTableId = req->primaryTableId;
Uint32 err = 0;
do {
- Uint32 noOfFragments = 0;
- Uint32 noOfReplicas = cnoReplicas;
- switch(fragmentType){
- case DictTabInfo::AllNodesSmallTable:
- jam();
- noOfFragments = csystemnodes;
- break;
- case DictTabInfo::AllNodesMediumTable:
- jam();
- noOfFragments = 2 * csystemnodes;
- break;
- case DictTabInfo::AllNodesLargeTable:
- jam();
- noOfFragments = 4 * csystemnodes;
- break;
- case DictTabInfo::SingleFragment:
+ Uint16 noOfFragments = 0;
+ if (fragmentCount == 0)
+ {
jam();
- noOfFragments = 1;
- break;
+ switch(fragmentType){
+ case DictTabInfo::AllNodesSmallTable:
+ jam();
+ noOfFragments = (Uint16)csystemnodes;
+ break;
+ case DictTabInfo::AllNodesMediumTable:
+ jam();
+ noOfFragments = (Uint16)(2 * csystemnodes);
+ break;
+ case DictTabInfo::AllNodesLargeTable:
+ jam();
+ noOfFragments = (Uint16)(4 * csystemnodes);
+ break;
+ case DictTabInfo::SingleFragment:
+ jam();
+ noOfFragments = (Uint16)1;
+ break;
#if 0
- case DictTabInfo::SpecifiedFragmentCount:
- noOfFragments = (fragmentCount == 0 ? 1 : (fragmentCount + 1)/ 2);
- break;
+ case DictTabInfo::SpecifiedFragmentCount:
+ noOfFragments = (fragmentCount == 0 ? 1 : (fragmentCount + 1)/ 2);
+ break;
#endif
- default:
- jam();
- err = CreateFragmentationRef::InvalidFragmentationType;
- break;
+ default:
+ jam();
+ err = CreateFragmentationRef::InvalidFragmentationType;
+ break;
+ }
+ if(err)
+ break;
}
- if(err)
- break;
-
NodeGroupRecordPtr NGPtr;
TabRecordPtr primTabPtr;
if (primaryTableId == RNIL) {
- if(fragmentNode == 0){
+ if (noOfFragments == 1)
+ {
+ /*
+ With single fragment tables we spread those evenly among the
+ node groups with a simple round robin structure.
+ */
jam();
- NGPtr.i = 0;
- if(noOfFragments < csystemnodes)
- {
- NGPtr.i = c_nextNodeGroup;
- c_nextNodeGroup = (NGPtr.i + 1 == cnoOfNodeGroups ? 0 : NGPtr.i + 1);
- }
- } else if(! (fragmentNode < MAX_NDB_NODES)) {
+ NGPtr.i = c_nextNodeGroup;
+ c_nextNodeGroup = (NGPtr.i + 1 == cnoOfNodeGroups ? 0 : NGPtr.i + 1);
+ } else if (noOfFragments > 0) {
+ /*
+ All other fragmentation types spread the fragments over all the
+ node groups and we always start with the first.
+ */
jam();
- err = CreateFragmentationRef::InvalidNodeId;
+ NGPtr.i = 0;
} else {
jam();
- const Uint32 stat = Sysfile::getNodeStatus(fragmentNode,
- SYSFILE->nodeStatus);
- switch (stat) {
- case Sysfile::NS_Active:
- case Sysfile::NS_ActiveMissed_1:
- case Sysfile::NS_ActiveMissed_2:
- case Sysfile::NS_TakeOver:
- jam();
- break;
- case Sysfile::NS_NotActive_NotTakenOver:
- jam();
- break;
- case Sysfile::NS_HotSpare:
- jam();
- case Sysfile::NS_NotDefined:
- jam();
- default:
- jam();
- err = CreateFragmentationRef::InvalidNodeType;
- break;
- }
- if(err)
- break;
- NGPtr.i = Sysfile::getNodeGroup(fragmentNode,
- SYSFILE->nodeGroups);
- break;
+ /*
+ When we come here the user has specified the exact partition
+ and there is an array of node groups sent along as well.
+ */
+ memcpy(&node_group_id[0], &signal->theData[25], 2 * fragmentCount);
+ noOfFragments = (Uint16)fragmentCount;
}
} else {
+ ndbrequire(fragmentCount == 0);
if (primaryTableId >= ctabFileSize) {
jam();
err = CreateFragmentationRef::InvalidPrimaryTable;
@@ -6261,30 +6251,43 @@
err = CreateFragmentationRef::InvalidPrimaryTable;
break;
}
- if (noOfFragments != primTabPtr.p->totalfragments) {
- jam();
- err = CreateFragmentationRef::InvalidFragmentationType;
- break;
- }
}
-
Uint32 count = 2;
+ Uint16 noOfReplicas = cnoReplicas;
Uint16 *fragments = (Uint16*)(signal->theData+25);
if (primaryTableId == RNIL) {
jam();
- Uint8 next_replica_node[MAX_NDB_NODES];
+ Uint16 next_replica_node[MAX_NDB_NODES];
memset(next_replica_node,0,sizeof(next_replica_node));
- for(Uint32 fragNo = 0; fragNo<noOfFragments; fragNo++){
+ for(Uint32 fragNo = 0; fragNo<noOfFragments; fragNo++)
+ {
jam();
- ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
+ if (fragmentCount > 0)
+ {
+ jam();
+ NGPtr.i = node_group_id[fragNo];
+ if (NGPtr.i == UNDEF_NODEGROUP)
+ {
+ NGPtr.i = c_nextNodeGroup;
+ c_nextNodeGroup =
+ (NGPtr.i + 1 == cnoOfNodeGroups ? 0 : NGPtr.i + 1);
+ }
+ if (NGPtr.i > cnoOfNodeGroups)
+ {
+ jam();
+ err = CreateFragmentationRef::InvalidNodeGroup;
+ break;
+ }
+ }
+ ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
const Uint32 max = NGPtr.p->nodeCount;
Uint32 tmp= next_replica_node[NGPtr.i];
for(Uint32 replicaNo = 0; replicaNo<noOfReplicas; replicaNo++)
{
jam();
- const Uint32 nodeId = NGPtr.p->nodesInGroup[tmp++];
- fragments[count++] = nodeId;
+ const Uint16 nodeId = NGPtr.p->nodesInGroup[tmp++];
+ fragments[count++]= nodeId;
tmp = (tmp >= max ? 0 : tmp);
}
tmp++;
@@ -6296,14 +6299,17 @@
NGPtr.i++;
NGPtr.i = (NGPtr.i == cnoOfNodeGroups ? 0 : NGPtr.i);
}
+ if (err)
+ break;
} else {
+ noOfFragments= primTabPtr.p->totalfragments;
for (Uint32 fragNo = 0;
- fragNo < primTabPtr.p->totalfragments; fragNo++) {
+ fragNo < noOfFragments; fragNo++) {
jam();
FragmentstorePtr fragPtr;
ReplicaRecordPtr replicaPtr;
getFragstore(primTabPtr.p, fragNo, fragPtr);
- fragments[count++] = fragPtr.p->preferredPrimary;
+ fragments[count++]= fragPtr.p->preferredPrimary;
for (replicaPtr.i = fragPtr.p->storedReplicas;
replicaPtr.i != RNIL;
replicaPtr.i = replicaPtr.p->nextReplica) {
@@ -6311,9 +6317,9 @@
ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
if (replicaPtr.p->procNode != fragPtr.p->preferredPrimary) {
jam();
- fragments[count++] = replicaPtr.p->procNode;
- }//if
- }//for
+ fragments[count++]= replicaPtr.p->procNode;
+ }
+ }
for (replicaPtr.i = fragPtr.p->oldStoredReplicas;
replicaPtr.i != RNIL;
replicaPtr.i = replicaPtr.p->nextReplica) {
@@ -6321,25 +6327,26 @@
ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
if (replicaPtr.p->procNode != fragPtr.p->preferredPrimary) {
jam();
- fragments[count++] = replicaPtr.p->procNode;
- }//if
- }//for
+ fragments[count++]= replicaPtr.p->procNode;
+ }
+ }
}
}
- ndbrequire(count == (2 + noOfReplicas * noOfFragments));
+ ndbrequire(count == (2U + noOfReplicas * noOfFragments));
CreateFragmentationConf * const conf =
(CreateFragmentationConf*)signal->getDataPtrSend();
conf->senderRef = reference();
conf->senderData = senderData;
- conf->noOfReplicas = noOfReplicas;
- conf->noOfFragments = noOfFragments;
+ conf->noOfReplicas = (Uint32)noOfReplicas;
+ conf->noOfFragments = (Uint32)noOfFragments;
- fragments[0] = noOfReplicas;
- fragments[1] = noOfFragments;
+ fragments[0]= noOfReplicas;
+ fragments[1]= noOfFragments;
if(senderRef != 0)
{
+ jam();
LinearSectionPtr ptr[3];
ptr[0].p = (Uint32*)&fragments[0];
ptr[0].sz = (count + 1) / 2;
@@ -6351,33 +6358,18 @@
ptr,
1);
}
- else
- {
- // Execute direct
- signal->theData[0] = 0;
- }
+ // Always ACK/NACK (here ACK)
+ signal->theData[0] = 0;
return;
} while(false);
-
- if(senderRef != 0)
- {
- CreateFragmentationRef * const ref =
- (CreateFragmentationRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = senderData;
- ref->errorCode = err;
- sendSignal(senderRef, GSN_CREATE_FRAGMENTATION_REF, signal,
- CreateFragmentationRef::SignalLength, JBB);
- }
- else
- {
- // Execute direct
- signal->theData[0] = err;
- }
+ // Always ACK/NACK (here NACK)
+ ndbrequire(senderRef != 0);
+ signal->theData[0] = err;
}
void Dbdih::execDIADDTABREQ(Signal* signal)
{
+ Uint32 fragType;
jamEntry();
DiAddTabReq * const req = (DiAddTabReq*)signal->getDataPtr();
@@ -6402,6 +6394,7 @@
ptrCheckGuard(tabPtr, ctabFileSize, tabRecord);
tabPtr.p->connectrec = connectPtr.i;
tabPtr.p->tableType = req->tableType;
+ fragType= req->fragmentationType;
tabPtr.p->schemaVersion = req->schemaVersion;
tabPtr.p->primaryTableId = req->primaryTableId;
@@ -6438,9 +6431,31 @@
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
tabPtr.p->tabStatus = TabRecord::TS_CREATING;
tabPtr.p->storedTable = req->storedTable;
- tabPtr.p->method = TabRecord::HASH;
tabPtr.p->kvalue = req->kValue;
+ switch ((DictTabInfo::FragmentType)fragType)
+ {
+ case DictTabInfo::AllNodesSmallTable:
+ case DictTabInfo::AllNodesMediumTable:
+ case DictTabInfo::AllNodesLargeTable:
+ case DictTabInfo::SIngleFragment:
+ jam();
+ case DictTabInfo::DistrKeyLin:
+ jam();
+ tabptr.p->method= TabRecord::LINEAR_HASH;
+ break;
+ case DictTabInfo::DistrKeyHash:
+ jam();
+ tabptr.p->method= TabRecord::NORMAL_HASH;
+ break;
+ case DictTabInfo::UserDefined:
+ jam();
+ tabptr.p->method= TabRecord::USER_DEFINED;
+ break;
+ default:
+ ndbrequire(false);
+ }
+
union {
Uint16 fragments[2 + MAX_FRAG_PER_NODE*MAX_REPLICAS*MAX_NDB_NODES];
Uint32 align;
@@ -6878,12 +6893,33 @@
TabRecord* regTabDesc = tabRecord;
jamEntry();
ptrCheckGuard(tabPtr, ttabFileSize, regTabDesc);
- Uint32 fragId = hashValue & tabPtr.p->mask;
- ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_ACTIVE);
- if (fragId < tabPtr.p->hashpointer) {
+ if (tabPtr.p->method == TabRecord::LINEAR_HASH)
+ {
jam();
- fragId = hashValue & ((tabPtr.p->mask << 1) + 1);
- }//if
+ Uint32 fragId = hashValue & tabPtr.p->mask;
+ ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_ACTIVE);
+ if (fragId < tabPtr.p->hashpointer) {
+ jam();
+ fragId = hashValue & ((tabPtr.p->mask << 1) + 1);
+ }//if
+ }
+ else if (tabPtr.p->method == NORMAL_HASH)
+ {
+ jam();
+ fragId= hashValue % tabPtr.p->totalfragments;
+ }
+ else
+ {
+ jam();
+ ndbassert(tabPtr.p->method == TabRecord::USER_DEFINED);
+ fragId= hashValue;
+ if (fragId >= tabPtr.p->totalFragments)
+ {
+ jam();
+ conf->zero= 1; //Indicate error;
+ return;
+ }
+ }
getFragstore(tabPtr.p, fragId, fragPtr);
DiGetNodesConf * const conf = (DiGetNodesConf *)&signal->theData[0];
Uint32 nodeCount = extractNodeInfo(fragPtr.p, conf->nodes);
@@ -8410,8 +8446,7 @@
rf.rwfTabPtr.p->hashpointer = readPageWord(&rf);
rf.rwfTabPtr.p->kvalue = readPageWord(&rf);
rf.rwfTabPtr.p->mask = readPageWord(&rf);
- ndbrequire(readPageWord(&rf) == TabRecord::HASH);
- rf.rwfTabPtr.p->method = TabRecord::HASH;
+ rf.rwfTabPtr.p->method = readPageWord(&rf);
/* ---------------------------------- */
/* Type of table, 2 = temporary table */
/* ---------------------------------- */
@@ -8505,7 +8540,7 @@
writePageWord(&wf, tabPtr.p->hashpointer);
writePageWord(&wf, tabPtr.p->kvalue);
writePageWord(&wf, tabPtr.p->mask);
- writePageWord(&wf, TabRecord::HASH);
+ writePageWord(&wf, tabPtr.p->method);
writePageWord(&wf, tabPtr.p->storedTable);
signal->theData[0] = DihContinueB::ZPACK_FRAG_INTO_PAGES;
@@ -10947,6 +10982,7 @@
cnoHotSpare = 0;
cnoOfActiveTables = 0;
cnoOfNodeGroups = 0;
+ c_nextNodeGroup = 0;
cnoReplicas = 0;
coldgcp = 0;
coldGcpId = 0;
--- 1.34/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp 2005-05-02 13:19:45 +02:00
+++ 1.35/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp 2005-07-13 22:33:44 +02:00
@@ -2096,7 +2096,7 @@
void execSTART_EXEC_SR(Signal* signal);
void execEXEC_SRREQ(Signal* signal);
void execEXEC_SRCONF(Signal* signal);
- void execREAD_PSUEDO_REQ(Signal* signal);
+ void execREAD_PSEUDO_REQ(Signal* signal);
void execDUMP_STATE_ORD(Signal* signal);
void execACC_COM_BLOCK(Signal* signal);
--- 1.15/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp 2005-04-08 02:44:04 +02:00
+++ 1.16/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp 2005-07-13 22:33:45 +02:00
@@ -337,7 +337,7 @@
addRecSignal(GSN_TUX_ADD_ATTRCONF, &Dblqh::execTUX_ADD_ATTRCONF);
addRecSignal(GSN_TUX_ADD_ATTRREF, &Dblqh::execTUX_ADD_ATTRREF);
- addRecSignal(GSN_READ_PSUEDO_REQ, &Dblqh::execREAD_PSUEDO_REQ);
+ addRecSignal(GSN_READ_PSEUDO_REQ, &Dblqh::execREAD_PSEUDO_REQ);
initData();
--- 1.70/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2005-06-13 15:16:11 +02:00
+++ 1.71/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2005-07-13 22:33:45 +02:00
@@ -2613,7 +2613,7 @@
}//Dblqh::updatePackedList()
void
-Dblqh::execREAD_PSUEDO_REQ(Signal* signal){
+Dblqh::execREAD_PSEUDO_REQ(Signal* signal){
jamEntry();
TcConnectionrecPtr regTcPtr;
regTcPtr.i = signal->theData[0];
@@ -2627,7 +2627,7 @@
ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
signal->theData[0] = regFragptr.p->accFragptr[regTcPtr.p->localFragptr];
- EXECUTE_DIRECT(DBACC, GSN_READ_PSUEDO_REQ, signal, 2);
+ EXECUTE_DIRECT(DBACC, GSN_READ_PSEUDO_REQ, signal, 2);
}
else
{
--- 1.29/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp 2005-05-10 17:34:50 +02:00
+++ 1.30/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp 2005-07-13 22:33:45 +02:00
@@ -395,6 +395,13 @@
Uint32 fireingOperation;
/**
+ * The fragment id of the firing operation. This will be appended
+ * to the Primary Key such that the record can be found even in the
+ * case of user defined partitioning.
+ */
+ Uint32 fragId;
+
+ /**
* Used for scrapping in case of node failure
*/
Uint32 nodeId;
--- 1.81/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2005-06-14 10:11:20 +02:00
+++ 1.82/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2005-07-13 22:33:45 +02:00
@@ -11225,6 +11225,7 @@
c_firedTriggerHash.remove(trigPtr);
+ trigPtr.p->fragId= fireOrd->fragId;
bool ok = trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
@@ -12122,7 +12123,11 @@
Uint32 dataPos = 0;
TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
- Uint32 * dataPtr = &tcKeyReq->scanInfo;
+ /*
+ Data points to distrGroupHashValue since scanInfo is used to send
+ fragment id of receiving fragment
+ */
+ Uint32 * dataPtr = &tcKeyReq->distrGroupHashValue;
Uint32 tcKeyLength = TcKeyReq::StaticLength;
Uint32 tcKeyRequestInfo = tcIndxReq->requestInfo;
TcIndexData* indexData;
@@ -12161,11 +12166,16 @@
regApiPtr->executingIndexOp = indexOp->indexOpId;;
regApiPtr->noIndexOp++; // Increase count
- // Filter out AttributeHeader:s since this should not be in key
+ /*
+ Filter out AttributeHeader:s since this should not be in key.
+ Also filter out fragment id from primary key and handle that
+ separately by setting it as Distribution Key and set indicator.
+ */
+
AttributeHeader* attrHeader = (AttributeHeader *) aiIter.data;
Uint32 headerSize = attrHeader->getHeaderSize();
- Uint32 keySize = attrHeader->getDataSize();
+ Uint32 keySize = attrHeader->getDataSize() - 1;
TcKeyReq::setKeyLength(tcKeyRequestInfo, keySize);
// Skip header
if (headerSize == 1) {
@@ -12175,6 +12185,9 @@
jam();
moreKeyData = indexOp->transIdAI.next(aiIter, headerSize - 1);
}//if
+ tcKeyReq->scanInfo = *aiIter.data; //Fragment Id
+ moreKeyData = indexOp->transIdAI.next(aiIter);
+ TcKeyReq::setDistributionKeyFlag(tcKeyRequestInfo, 1U);
while(// If we have not read complete key
(keySize != 0) &&
(dataPos < keyBufSize)) {
@@ -12584,10 +12597,11 @@
moreAttrData = keyValues.next(iter, hops);
}
AttributeHeader pkAttrHeader(attrId, totalPrimaryKeyLength);
+ Uint32 attributesLength = afterValues.getSize() +
+ pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize() + 1;
TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
- tcKeyReq->attrLen = afterValues.getSize() +
- pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
+ tcKeyReq->attrLen = attributesLength;
tcKeyReq->tableId = indexData->indexId;
TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, true);
@@ -12637,8 +12651,11 @@
}
tcKeyLength += dataPos;
- Uint32 attributesLength = afterValues.getSize() +
- pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
+ /*
+ Size of attrinfo is unique index attributes one by one, header for each
+ of them (all contained in the afterValues data structure), plus a header,
+ the primary key (compacted) and the fragment id before the primary key
+ */
if (attributesLength <= attrBufSize) {
jam();
// ATTRINFO fits in TCKEYREQ
@@ -12655,6 +12672,10 @@
// as one attribute
pkAttrHeader.insertHeader(dataPtr);
dataPtr += pkAttrHeader.getHeaderSize();
+ /*
+ Insert fragment id before primary key as part of reference to tuple
+ */
+ *dataPtr++ = firedTriggerData->fragId;
moreAttrData = keyValues.first(iter);
while(moreAttrData) {
jam();
@@ -12819,6 +12840,29 @@
pkAttrHeader.insertHeader(dataPtr);
dataPtr += pkAttrHeader.getHeaderSize();
attrInfoPos += pkAttrHeader.getHeaderSize();
+ /*
+ Add fragment id before primary key
+ TODO: This code really needs to be made into a long signal
+ to remove this messy code.
+ */
+ if (attrInfoPos == AttrInfo::DataLength)
+ {
+ jam();
+ // Flush ATTRINFO
+#if INTERNAL_TRIGGER_TCKEYREQ_JBA
+ sendSignal(reference(), GSN_ATTRINFO, signal,
+ AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
+#else
+ EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
+ AttrInfo::HeaderLength + AttrInfo::DataLength);
+ jamEntry();
+#endif
+ dataPtr = (Uint32 *) &attrInfo->attrData;
+ attrInfoPos = 0;
+ }
+ attrInfoPos++;
+ *dataPtr++ = firedTriggerData->fragId;
+
moreAttrData = keyValues.first(iter);
while(moreAttrData) {
jam();
--- 1.24/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2005-05-02 13:19:46 +02:00
+++ 1.25/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2005-07-13 22:33:45 +02:00
@@ -1694,7 +1694,7 @@
//------------------------------------------------------------------
//------------------------------------------------------------------
bool nullFlagCheck(Uint32 attrDes2);
- Uint32 read_psuedo(Uint32 attrId, Uint32* outBuffer);
+ Uint32 read_pseudo(Uint32 attrId, Uint32* outBuffer);
//------------------------------------------------------------------
//------------------------------------------------------------------
--- 1.18/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp 2005-04-27 04:07:10 +02:00
+++ 1.19/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp 2005-07-13 22:33:46 +02:00
@@ -210,8 +210,8 @@
} else {
return -1;
}//if
- } else if(attributeId & AttributeHeader::PSUEDO){
- Uint32 sz = read_psuedo(attributeId,
+ } else if(attributeId & AttributeHeader::PSEUDO){
+ Uint32 sz = read_pseudo(attributeId,
outBuffer+tmpAttrBufIndex+1);
AttributeHeader::init(&outBuffer[tmpAttrBufIndex], attributeId, sz);
tOutBufIndex = tmpAttrBufIndex + 1 + sz;
@@ -995,7 +995,7 @@
}//Dbtup::updateDynSmallVarSize()
Uint32
-Dbtup::read_psuedo(Uint32 attrId, Uint32* outBuffer){
+Dbtup::read_pseudo(Uint32 attrId, Uint32* outBuffer){
Uint32 tmp[sizeof(SignalHeader)+25];
Signal * signal = (Signal*)&tmp;
switch(attrId){
@@ -1017,7 +1017,7 @@
signal->theData[0] = operPtr.p->userpointer;
signal->theData[1] = attrId;
- EXECUTE_DIRECT(DBLQH, GSN_READ_PSUEDO_REQ, signal, 2);
+ EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
outBuffer[0] = signal->theData[0];
outBuffer[1] = signal->theData[1];
return 2;
@@ -1025,7 +1025,7 @@
signal->theData[0] = operPtr.p->userpointer;
signal->theData[1] = attrId;
- EXECUTE_DIRECT(DBLQH, GSN_READ_PSUEDO_REQ, signal, 2);
+ EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
outBuffer[0] = signal->theData[0];
return 1;
default:
--- 1.8/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp 2005-04-27 04:07:10 +02:00
+++ 1.9/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp 2005-07-13 22:33:46 +02:00
@@ -887,6 +887,7 @@
fireTrigOrd->setConnectionPtr(regOperPtr->tcOpIndex);
fireTrigOrd->setTriggerId(trigPtr->triggerId);
+ fireTrigOrd->fragId= regOperPtr->fragId >> 1; //Handle two local frags
switch(regOperPtr->optype) {
case(ZINSERT):
--- 1.37/storage/ndb/src/ndbapi/NdbDictionary.cpp 2005-06-13 15:16:12 +02:00
+++ 1.38/storage/ndb/src/ndbapi/NdbDictionary.cpp 2005-07-13 22:33:46 +02:00
@@ -412,6 +412,22 @@
m_impl.m_frm.assign(data, len);
}
+const void*
+NdbDictionary::Table::getNodeGroupIds() const {
+ return m_impl.m_ng.get_data();
+}
+
+Uint32
+NdbDictionary::Table::getNodeGroupIdsLength() const {
+ return m_impl.m_ng.length();
+}
+
+void
+NdbDictionary::Table::setNodeGroupIds(const void* data, Uint32 noWords)
+{
+ m_impl.m_ng.assign(data, 2*noWords);
+}
+
NdbDictionary::Object::Status
NdbDictionary::Table::getObjectStatus() const {
return m_impl.m_status;
--- 1.84/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2005-06-17 23:13:36 +02:00
+++ 1.85/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2005-07-13 22:33:46 +02:00
@@ -233,7 +233,7 @@
}
NdbDictionary::Column *
-NdbColumnImpl::create_psuedo(const char * name){
+NdbColumnImpl::create_pseudo(const char * name){
NdbDictionary::Column * col = new NdbDictionary::Column();
col->setName(name);
if(!strcmp(name, "NDB$FRAGMENT")){
@@ -390,6 +390,7 @@
m_externalName.assign(org.m_externalName);
m_newExternalName.assign(org.m_newExternalName);
m_frm.assign(org.m_frm.get_data(), org.m_frm.length());
+ m_ng.assign(org.m_ng.get_data(), org.m_ng.length());
m_fragmentType = org.m_fragmentType;
m_fragmentCount = org.m_fragmentCount;
@@ -788,17 +789,17 @@
m_globalHash->lock();
if(f_dictionary_count++ == 0){
NdbDictionary::Column::FRAGMENT=
- NdbColumnImpl::create_psuedo("NDB$FRAGMENT");
+ NdbColumnImpl::create_pseudo("NDB$FRAGMENT");
NdbDictionary::Column::FRAGMENT_MEMORY=
- NdbColumnImpl::create_psuedo("NDB$FRAGMENT_MEMORY");
+ NdbColumnImpl::create_pseudo("NDB$FRAGMENT_MEMORY");
NdbDictionary::Column::ROW_COUNT=
- NdbColumnImpl::create_psuedo("NDB$ROW_COUNT");
+ NdbColumnImpl::create_pseudo("NDB$ROW_COUNT");
NdbDictionary::Column::COMMIT_COUNT=
- NdbColumnImpl::create_psuedo("NDB$COMMIT_COUNT");
+ NdbColumnImpl::create_pseudo("NDB$COMMIT_COUNT");
NdbDictionary::Column::ROW_SIZE=
- NdbColumnImpl::create_psuedo("NDB$ROW_SIZE");
+ NdbColumnImpl::create_pseudo("NDB$ROW_SIZE");
NdbDictionary::Column::RANGE_NO=
- NdbColumnImpl::create_psuedo("NDB$RANGE_NO");
+ NdbColumnImpl::create_pseudo("NDB$RANGE_NO");
}
m_globalHash->unlock();
return true;
@@ -1293,6 +1294,7 @@
impl->m_externalName.assign(externalName);
impl->m_frm.assign(tableDesc.FrmData, tableDesc.FrmLen);
+ impl->m_ng.assign(tableDesc.FragmentData, tableDesc.FragmentDataLen);
impl->m_fragmentType = (NdbDictionary::Object::FragmentType)
getApiConstant(tableDesc.FragmentType,
@@ -1406,12 +1408,12 @@
if(tableDesc.FragmentDataLen > 0)
{
- Uint32 replicaCount = tableDesc.FragmentData[0];
- Uint32 fragCount = tableDesc.FragmentData[1];
+ Uint16 replicaCount = tableDesc.FragmentData[0];
+ Uint16 fragCount = tableDesc.FragmentData[1];
impl->m_replicaCount = replicaCount;
impl->m_fragmentCount = fragCount;
-
+ DBUG_PRINT("info", ("replicaCount=%x , fragCount=%x",replicaCount,fragCount));
for(i = 0; i<(fragCount*replicaCount); i++)
{
impl->m_fragments.push_back(tableDesc.FragmentData[i+2]);
@@ -1615,6 +1617,10 @@
if (col->m_distributionKey)
distKeys++;
}
+ if (distKeys == impl.m_noOfKeys)
+ distKeys= 0;
+ impl.m_noOfDistributionKeys= distKeys;
+
// Check max length of frm data
if (impl.m_frm.length() > MAX_FRM_DATA_SIZE){
@@ -1623,6 +1629,8 @@
}
tmpTab.FrmLen = impl.m_frm.length();
memcpy(tmpTab.FrmData, impl.m_frm.get_data(), impl.m_frm.length());
+ tmpTab.FragmentDataLen = impl.m_ng.length();
+ memcpy(tmpTab.FragmentData, impl.m_ng.get_data(), impl.m_ng.length());
tmpTab.TableLoggedFlag = impl.m_logging;
tmpTab.TableKValue = impl.m_kvalue;
@@ -1646,6 +1654,8 @@
abort();
}
+ DBUG_PRINT("info",("impl.m_noOfDistributionKeys: %d impl.m_noOfKeys: %d distKeys: %d",
+ impl.m_noOfDistributionKeys, impl.m_noOfKeys, distKeys));
if (distKeys == impl.m_noOfKeys)
distKeys= 0;
impl.m_noOfDistributionKeys= distKeys;
@@ -1655,6 +1665,8 @@
if(col == 0)
continue;
+ DBUG_PRINT("info",("column: %s(%d) col->m_distributionKey: %d",
+ col->m_name.c_str(), i, col->m_distributionKey));
DictTabInfo::Attribute tmpAttr; tmpAttr.init();
BaseString::snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
col->m_name.c_str());
@@ -1685,8 +1697,14 @@
}
// distribution key not supported for Char attribute
if (distKeys && col->m_distributionKey && col->m_cs != NULL) {
- m_error.code= 745;
- DBUG_RETURN(-1);
+ // we can allow this for non-var char where strxfrm does nothing
+ if (col->m_type == NdbDictionary::Column::Char &&
+ (col->m_cs->state & MY_CS_BINSORT))
+ ;
+ else {
+ m_error.code= 745;
+ DBUG_RETURN(-1);
+ }
}
// charset in upper half of precision
if (col->getCharType()) {
--- 1.34/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2005-06-13 15:16:12 +02:00
+++ 1.35/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 2005-07-13 22:33:46 +02:00
@@ -90,7 +90,7 @@
static const NdbColumnImpl & getImpl(const NdbDictionary::Column & t);
NdbDictionary::Column * m_facade;
- static NdbDictionary::Column * create_psuedo(const char *);
+ static NdbDictionary::Column * create_pseudo(const char *);
};
class NdbTableImpl : public NdbDictionary::Table, public NdbDictObjectImpl {
@@ -109,6 +109,7 @@
BaseString m_externalName;
BaseString m_newExternalName; // Used for alter table
UtilBuffer m_frm;
+ UtilBuffer m_ng;
NdbDictionary::Object::FragmentType m_fragmentType;
/**
--- 1.194/sql/ha_ndbcluster.cc 2005-06-21 15:14:19 +02:00
+++ 1.195/sql/ha_ndbcluster.cc 2005-07-13 22:33:33 +02:00
@@ -34,6 +34,7 @@
// options from from mysqld.cc
extern my_bool opt_ndb_optimized_node_selection;
+extern my_bool opt_ndb_linear_hash;
extern const char *opt_ndbcluster_connectstring;
// Default value for parallelism
@@ -1348,7 +1349,8 @@
Read one record from NDB using primary key
*/
-int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf)
+int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf,
+ uint32 part_id)
{
uint no_fields= table->s->fields;
NdbConnection *trans= m_active_trans;
@@ -1366,6 +1368,8 @@
op->readTuple(lm) != 0)
ERR_RETURN(trans->getNdbError());
+ if (m_use_partition_function)
+ op->setPartitionId(part_id);
if (table->s->primary_key == MAX_KEY)
{
// This table has no primary key, use "hidden" primary key
@@ -1403,7 +1407,8 @@
Read one complementing record from NDB using primary key from old_data
*/
-int ha_ndbcluster::complemented_pk_read(const byte *old_data, byte *new_data)
+int ha_ndbcluster::complemented_pk_read(const byte *old_data, byte *new_data,
+ uint32 old_part_id)
{
uint no_fields= table->s->fields, i;
NdbTransaction *trans= m_active_trans;
@@ -1427,6 +1432,9 @@
int res;
if ((res= set_primary_key_from_old_data(op, old_data)))
ERR_RETURN(trans->getNdbError());
+
+ if (m_use_partition_function)
+ op->setPartitionId(old_part_id);
// Read all unreferenced non-key field(s)
for (i= 0; i < no_fields; i++)
@@ -1486,6 +1494,17 @@
if ((res= set_primary_key(op)))
ERR_RETURN(trans->getNdbError());
+ if (m_use_partition_function)
+ {
+ uint32 part_id;
+ int error;
+ if ((error= m_part_info->get_partition_id(m_part_info, &part_id)))
+ {
+ DBUG_RETURN(error);
+ }
+ op->setPartitionId(part_id);
+ }
+
if (execute_no_commit_ie(this,trans) != 0)
{
table->status= STATUS_NOT_FOUND;
@@ -1824,7 +1843,8 @@
int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
const key_range *end_key,
- bool sorted, bool descending, byte* buf)
+ bool sorted, bool descending,
+ byte* buf, part_id_range *part_spec)
{
int res;
bool restart;
@@ -1850,11 +1870,17 @@
(const NDBTAB *) m_table)) ||
op->readTuples(lm, 0, parallelism, sorted, descending))
ERR_RETURN(trans->getNdbError());
+ if (m_use_partition_function && part_spec != NULL &&
+ part_spec->start_part == part_spec->end_part)
+ op->setPartitionId(part_spec->start_part);
m_active_cursor= op;
} else {
restart= TRUE;
op= (NdbIndexScanOperation*)m_active_cursor;
+ if (m_use_partition_function && part_spec != NULL &&
+ part_spec->start_part == part_spec->end_part)
+ op->setPartitionId(part_spec->start_part);
DBUG_ASSERT(op->getSorted() == sorted);
DBUG_ASSERT(op->getLockMode() ==
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type));
@@ -1954,6 +1980,17 @@
if (res != 0)
ERR_RETURN(trans->getNdbError());
+ if (m_use_partition_function)
+ {
+ uint32 part_id;
+ int error;
+ if ((error= m_part_info->get_partition_id(m_part_info, &part_id)))
+ {
+ DBUG_RETURN(error);
+ }
+ op->setPartitionId(part_id);
+ }
+
if (table->s->primary_key == MAX_KEY)
{
// Table has hidden primary key
@@ -2113,6 +2150,8 @@
NdbScanOperation* cursor= m_active_cursor;
NdbOperation *op;
uint i;
+ uint32 old_part_id= 0, new_part_id= 0;
+ int error;
DBUG_ENTER("update_row");
m_write_op= TRUE;
@@ -2123,15 +2162,23 @@
ha_set_bit_in_write_set(table->timestamp_field->fieldnr);
}
+ if (m_use_partition_function &&
+ (error= get_parts_for_update(old_data, new_data, table->record[0],
+ m_part_info, &old_part_id, &new_part_id)))
+ {
+ DBUG_RETURN(error);
+ }
+
/* Check for update of primary key for special handling */
if ((table->s->primary_key != MAX_KEY) &&
- (key_cmp(table->s->primary_key, old_data, new_data)))
+ (key_cmp(table->s->primary_key, old_data, new_data)) ||
+ (old_part_id != new_part_id))
{
int read_res, insert_res, delete_res;
DBUG_PRINT("info", ("primary key update, doing pk read+delete+insert"));
// Get all old fields, since we optimize away fields not in query
- read_res= complemented_pk_read(old_data, new_data);
+ read_res= complemented_pk_read(old_data, new_data, old_part_id);
if (read_res)
{
DBUG_PRINT("info", ("pk read failed"));
@@ -2182,6 +2229,8 @@
m_ops_pending++;
if (uses_blob_value())
m_blobs_pending= TRUE;
+ if (m_use_partition_function)
+ cursor->setPartitionId(new_part_id);
}
else
{
@@ -2189,6 +2238,8 @@
op->updateTuple() != 0)
ERR_RETURN(trans->getNdbError());
+ if (m_use_partition_function)
+ op->setPartitionId(new_part_id);
if (table->s->primary_key == MAX_KEY)
{
// This table has no primary key, use "hidden" primary key
@@ -2244,12 +2295,21 @@
NdbTransaction *trans= m_active_trans;
NdbScanOperation* cursor= m_active_cursor;
NdbOperation *op;
+ uint32 part_id;
+ int error;
DBUG_ENTER("delete_row");
m_write_op= TRUE;
statistic_increment(thd->status_var.ha_delete_count,&LOCK_status);
m_rows_changed++;
+ if (m_use_partition_function &&
+ (error= get_part_for_delete(record, table->record[0], m_part_info,
+ &part_id)))
+ {
+ DBUG_RETURN(error);
+ }
+
if (cursor)
{
/*
@@ -2264,6 +2324,9 @@
ERR_RETURN(trans->getNdbError());
m_ops_pending++;
+ if (m_use_partition_function)
+ cursor->setPartitionId(part_id);
+
no_uncommitted_rows_update(-1);
if (!m_primary_key_update)
@@ -2277,6 +2340,9 @@
op->deleteTuple() != 0)
ERR_RETURN(trans->getNdbError());
+ if (m_use_partition_function)
+ op->setPartitionId(part_id);
+
no_uncommitted_rows_update(-1);
if (table->s->primary_key == MAX_KEY)
@@ -2462,11 +2528,13 @@
}
-int ha_ndbcluster::index_init(uint index)
+int ha_ndbcluster::index_init(uint index, bool sorted)
{
DBUG_ENTER("ha_ndbcluster::index_init");
- DBUG_PRINT("enter", ("index: %u", index));
- DBUG_RETURN(handler::index_init(index));
+ DBUG_PRINT("enter", ("index: %u sorted: %d", index, sorted));
+ active_index= index;
+ m_sorted= sorted;
+ DBUG_RETURN(0);
}
@@ -2503,56 +2571,16 @@
const byte *key, uint key_len,
enum ha_rkey_function find_flag)
{
+ key_range start_key;
+ bool descending= FALSE;
DBUG_ENTER("ha_ndbcluster::index_read");
DBUG_PRINT("enter", ("active_index: %u, key_len: %u, find_flag: %d",
active_index, key_len, find_flag));
- int error;
- ndb_index_type type= get_index_type(active_index);
- const KEY* key_info= table->key_info+active_index;
- m_write_op= FALSE;
- switch (type){
- case PRIMARY_KEY_ORDERED_INDEX:
- case PRIMARY_KEY_INDEX:
- if (find_flag == HA_READ_KEY_EXACT && key_info->key_length == key_len)
- {
- if(m_active_cursor && (error= close_scan()))
- DBUG_RETURN(error);
- DBUG_RETURN(pk_read(key, key_len, buf));
- }
- else if (type == PRIMARY_KEY_INDEX)
- {
- DBUG_RETURN(1);
- }
- break;
- case UNIQUE_ORDERED_INDEX:
- case UNIQUE_INDEX:
- if (find_flag == HA_READ_KEY_EXACT && key_info->key_length == key_len
&&
- !check_null_in_key(key_info, key, key_len))
- {
- if(m_active_cursor && (error= close_scan()))
- DBUG_RETURN(error);
- DBUG_RETURN(unique_index_read(key, key_len, buf));
- }
- else if (type == UNIQUE_INDEX)
- {
- DBUG_RETURN(1);
- }
- break;
- case ORDERED_INDEX:
- break;
- default:
- case UNDEFINED_INDEX:
- DBUG_ASSERT(FALSE);
- DBUG_RETURN(1);
- break;
- }
-
- key_range start_key;
start_key.key= key;
start_key.length= key_len;
start_key.flag= find_flag;
- bool descending= FALSE;
+ descending= FALSE;
switch (find_flag) {
case HA_READ_KEY_OR_PREV:
case HA_READ_BEFORE_KEY:
@@ -2563,8 +2591,8 @@
default:
break;
}
- error= ordered_index_scan(&start_key, 0, TRUE, descending, buf);
- DBUG_RETURN(error == HA_ERR_END_OF_FILE ? HA_ERR_KEY_NOT_FOUND : error);
+ DBUG_RETURN(read_range_first_to_buf(&start_key, 0, descending,
+ m_sorted, buf));
}
@@ -2575,7 +2603,7 @@
statistic_increment(current_thd->status_var.ha_read_key_count, &LOCK_status);
DBUG_ENTER("ha_ndbcluster::index_read_idx");
DBUG_PRINT("enter", ("index_no: %u, key_len: %u", index_no, key_len));
- index_init(index_no);
+ index_init(index_no, 0);
DBUG_RETURN(index_read(buf, key, key_len, find_flag));
}
@@ -2606,7 +2634,7 @@
// Start the ordered index scan and fetch the first row
// Only HA_READ_ORDER indexes get called by index_first
- DBUG_RETURN(ordered_index_scan(0, 0, TRUE, FALSE, buf));
+ DBUG_RETURN(ordered_index_scan(0, 0, TRUE, FALSE, buf, NULL));
}
@@ -2614,7 +2642,7 @@
{
DBUG_ENTER("ha_ndbcluster::index_last");
statistic_increment(current_thd->status_var.ha_read_last_count,&LOCK_status);
- DBUG_RETURN(ordered_index_scan(0, 0, TRUE, TRUE, buf));
+ DBUG_RETURN(ordered_index_scan(0, 0, TRUE, TRUE, buf, NULL));
}
int ha_ndbcluster::index_read_last(byte * buf, const byte * key, uint key_len)
@@ -2623,67 +2651,76 @@
DBUG_RETURN(index_read(buf, key, key_len, HA_READ_PREFIX_LAST));
}
-inline
int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
const key_range *end_key,
- bool eq_r, bool sorted,
+ bool desc, bool sorted,
byte* buf)
{
- KEY* key_info;
- int error= 1;
+ part_id_range part_spec;
+ ndb_index_type type= get_index_type(active_index);
+ const KEY* key_info= table->key_info+active_index;
+ int error;
DBUG_ENTER("ha_ndbcluster::read_range_first_to_buf");
- DBUG_PRINT("info", ("eq_r: %d, sorted: %d", eq_r, sorted));
+ DBUG_PRINT("info", ("desc: %d, sorted: %d", desc, sorted));
- switch (get_index_type(active_index)){
+ if (m_use_partition_function)
+ {
+ get_partition_set(table, buf, active_index, start_key, &part_spec);
+ if (part_spec.start_part > part_spec.end_part)
+ {
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
+ else if (part_spec.start_part == part_spec.end_part)
+ {
+ /*
+ Only one partition is required to scan, if sorted is required we
+ don't need it any more since output from one ordered partitioned
+ index is always sorted.
+ */
+ sorted= FALSE;
+ }
+ }
+ m_write_op= FALSE;
+ switch (type){
case PRIMARY_KEY_ORDERED_INDEX:
case PRIMARY_KEY_INDEX:
- key_info= table->key_info + active_index;
if (start_key &&
start_key->length == key_info->key_length &&
start_key->flag == HA_READ_KEY_EXACT)
{
if(m_active_cursor && (error= close_scan()))
DBUG_RETURN(error);
- error= pk_read(start_key->key, start_key->length, buf);
- DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error);
+ DBUG_RETURN(pk_read(start_key->key, start_key->length, buf,
+ part_spec.start_part));
}
break;
case UNIQUE_ORDERED_INDEX:
case UNIQUE_INDEX:
- key_info= table->key_info + active_index;
if (start_key && start_key->length == key_info->key_length &&
start_key->flag == HA_READ_KEY_EXACT &&
!check_null_in_key(key_info, start_key->key, start_key->length))
{
if(m_active_cursor && (error= close_scan()))
DBUG_RETURN(error);
- error= unique_index_read(start_key->key, start_key->length, buf);
- DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error);
+ DBUG_RETURN(unique_index_read(start_key->key, start_key->length, buf));
}
break;
default:
break;
}
-
// Start the ordered index scan and fetch the first row
- error= ordered_index_scan(start_key, end_key, sorted, FALSE, buf);
- DBUG_RETURN(error);
+ DBUG_RETURN(ordered_index_scan(start_key, end_key, sorted, desc, buf,
+ &part_spec));
}
-
int ha_ndbcluster::read_range_first(const key_range *start_key,
const key_range *end_key,
bool eq_r, bool sorted)
{
byte* buf= table->record[0];
DBUG_ENTER("ha_ndbcluster::read_range_first");
- m_write_op= FALSE;
-
- DBUG_RETURN(read_range_first_to_buf(start_key,
- end_key,
- eq_r,
- sorted,
- buf));
+ DBUG_RETURN(read_range_first_to_buf(start_key, end_key, FALSE,
+ sorted, buf));
}
int ha_ndbcluster::read_range_next()
@@ -2709,7 +2746,7 @@
DBUG_RETURN(-1);
}
}
- index_init(table->s->primary_key);
+ index_init(table->s->primary_key, 0);
DBUG_RETURN(0);
}
@@ -2776,7 +2813,20 @@
&LOCK_status);
// The primary key for the record is stored in pos
// Perform a pk_read using primary key "index"
- DBUG_RETURN(pk_read(pos, ref_length, buf));
+ {
+ part_id_range part_spec;
+ if (m_use_partition_function)
+ {
+ key_range key_spec;
+ KEY *key_info= table->key_info + active_index;
+ key_spec.key= pos;
+ key_spec.length= ref_length;
+ key_spec.flag= HA_READ_KEY_EXACT;
+ get_full_part_id_from_key(table, buf, key_info, &key_spec, &part_spec);
+ DBUG_ASSERT(part_spec.start_part == part_spec.end_part);
+ }
+ DBUG_RETURN(pk_read(pos, ref_length, buf, part_spec.start_part));
+ }
}
@@ -3708,56 +3758,6 @@
return 0;
}
-/*
- Create a table in NDB Cluster
- */
-
-static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length)
-{
- if (form->s->max_rows == (ha_rows) 0) /* default setting, don't set fragmentation
*/
- return;
- /**
- * get the number of fragments right
- */
- uint no_fragments;
- {
-#if MYSQL_VERSION_ID >= 50000
- uint acc_row_size= 25 + /*safety margin*/ 2;
-#else
- uint acc_row_size= pk_length*4;
- /* add acc overhead */
- if (pk_length <= 8) /* main page will set the limit */
- acc_row_size+= 25 + /*safety margin*/ 2;
- else /* overflow page will set the limit */
- acc_row_size+= 4 + /*safety margin*/ 4;
-#endif
- ulonglong acc_fragment_size= 512*1024*1024;
- ulonglong max_rows= form->s->max_rows;
-#if MYSQL_VERSION_ID >= 50100
- no_fragments= (max_rows*acc_row_size)/acc_fragment_size+1;
-#else
- no_fragments= ((max_rows*acc_row_size)/acc_fragment_size+1
- +1/*correct rounding*/)/2;
-#endif
- }
- {
- uint no_nodes= g_ndb_cluster_connection->no_db_nodes();
- NDBTAB::FragmentType ftype;
- if (no_fragments > 2*no_nodes)
- {
- ftype= NDBTAB::FragAllLarge;
- if (no_fragments > 4*no_nodes)
- push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
- "Ndb might have problems storing the max amount of rows specified");
- }
- else if (no_fragments > no_nodes)
- ftype= NDBTAB::FragAllMedium;
- else
- ftype= NDBTAB::FragAllSmall;
- tab.setFragmentType(ftype);
- }
-}
-
int ha_ndbcluster::create(const char *name,
TABLE *form,
HA_CREATE_INFO *info)
@@ -3860,7 +3860,22 @@
}
}
- ndb_set_fragmentation(tab, form, pk_length);
+ // Check partition info
+ partition_info *part_info= form->s->part_info;
+ if (part_info)
+ {
+ int error;
+ if ((error= set_up_partition_info(part_info, form, (void*)&tab)))
+ {
+ DBUG_RETURN(error);
+ }
+ }
+ else
+ {
+ ndb_set_fragmentation(tab, form, pk_length);
+ }
+
+
if ((my_errno= check_ndb_connection()))
DBUG_RETURN(my_errno);
@@ -4111,6 +4126,10 @@
HA_NEED_READ_RANGE_BUFFER |
HA_CAN_BIT_FIELD),
m_share(0),
+ m_part_info(NULL),
+ m_use_partition_function(FALSE),
+ m_read_multi_completed(FALSE),
+ m_sorted(FALSE),
m_use_write(FALSE),
m_ignore_dup_key(FALSE),
m_primary_key_update(FALSE),
@@ -4225,6 +4244,15 @@
if (!res)
info(HA_STATUS_VARIABLE | HA_STATUS_CONST);
+ if (table->s->part_info)
+ {
+ m_part_info= table->s->part_info;
+ if (!(m_part_info->part_type == HASH_PARTITION &&
+ m_part_info->list_of_part_fields &&
+ !is_sub_partitioned(m_part_info)))
+ m_use_partition_function= TRUE;
+ }
+
DBUG_RETURN(res);
}
@@ -5495,6 +5523,22 @@
for (; multi_range_curr<multi_range_end && curr+reclength <=
end_of_buffer;
multi_range_curr++)
{
+ part_id_range part_spec;
+ if (m_use_partition_function)
+ {
+ get_partition_set(table, curr, active_index,
+ &multi_range_curr->start_key,
+ &part_spec);
+ if (part_spec.start_part > part_spec.end_part)
+ {
+ /*
+ We can skip this partition since the key won't fit into any
+ partition
+ */
+ curr += reclength;
+ continue;
+ }
+ }
switch(index_type){
case PRIMARY_KEY_INDEX:
pk:
@@ -5504,7 +5548,9 @@
!op->readTuple(lm) &&
!set_primary_key(op, multi_range_curr->start_key.key) &&
!define_read_attrs(curr, op) &&
- (op->setAbortOption(AO_IgnoreError), TRUE))
+ (op->setAbortOption(AO_IgnoreError), TRUE) &&
+ (!m_use_partition_function ||
+ (op->setPartitionId(part_spec.start_part), true)))
curr += reclength;
else
ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError());
@@ -5590,10 +5636,12 @@
* the remaining ranges
*/
buffer->end_of_used_area= (byte*)buffer->buffer_end;
+ m_read_multi_completed= FALSE;
}
else
{
buffer->end_of_used_area= curr;
+ m_read_multi_completed= TRUE;
}
/**
@@ -5630,7 +5678,7 @@
int range_no;
ulong reclength= table->s->reclength;
const NdbOperation* op= m_current_multi_operation;
- for (;multi_range_curr < m_multi_range_defined; multi_range_curr++)
+ for (;multi_range_curr < m_multi_range_defined && op; multi_range_curr++)
{
if (multi_range_curr->range_flag & UNIQUE_RANGE)
{
@@ -5716,7 +5764,7 @@
}
}
- if (multi_range_curr == multi_range_end)
+ if (m_read_multi_completed)
DBUG_RETURN(HA_ERR_END_OF_FILE);
/**
@@ -7231,5 +7279,158 @@
DBUG_RETURN(0);
}
+
+
+int ha_ndbcluster::get_default_no_partitions(ulonglong max_rows)
+{
+ ulong no_fragments= get_no_fragments(max_rows);
+ uint no_nodes= g_ndb_cluster_connection->no_db_nodes();
+ if (no_fragments > no_nodes)
+ return no_fragments;
+ else
+ return no_nodes;
+}
+
+/*
+ User defined partitioning set-up. We need to check how many fragments the
+ user wants defined and which node groups to put those into. Later we also
+ want to attach those partitions to a tablespace.
+
+ All the functionality of the partition function, partition limits and so
+ forth are entirely handled by the MySQL Server. There is one exception to
+ this rule for PARTITION BY KEY where NDB handles the hash function and
+ this type can thus be handled transparently also by NDB API program.
+ For RANGE, HASH and LIST and subpartitioning the NDB API programs must
+ implement the function to map to a partition.
+*/
+uint ha_ndbcluster::set_up_partition_info(partition_info *part_info,
+ TABLE *table,
+ void *tab_par)
+{
+ DBUG_ENTER("ha_ndbcluster::set_up_partition_info");
+ ushort node_group[MAX_PARTITIONS];
+ ulong ng_index= 0, i, j;
+ NDBTAB *tab= (NDBTAB*)tab_par;
+ NDBTAB::FragmentType ftype= NDBTAB::UserDefined;
+ partition_element *part_elem;
+
+ if (part_info->part_type == HASH_PARTITION &&
+ part_info->list_of_part_fields == TRUE)
+ {
+ Field **fields= part_info->part_field_array;
+
+ if (part_info->linear_hash_ind)
+ ftype= NDBTAB::DistrKeyLin;
+ else
+ ftype= NDBTAB::DistrKeyHash;
+
+ for (i= 0; i < part_info->part_field_list.elements; i++)
+ {
+ NDBCOL *col= tab->getColumn(fields[i]->fieldnr - 1);
+ DBUG_PRINT("info",("setting dist key on %s", col->getName()));
+ col->setPartitionKey(TRUE);
+ }
+ DBUG_RETURN(FALSE);
+ }
+ List_iterator<partition_element> part_it(part_info->partitions);
+ for (i= 0; i < part_info->no_parts; i++)
+ {
+ part_elem= part_it++;
+ if (!is_sub_partitioned(part_info))
+ {
+ node_group[ng_index++]= part_elem->nodegroup_id;
+ //Here we should insert tablespace id based on tablespace name
+ }
+ else
+ {
+ List_iterator<partition_element> sub_it(part_elem->subpartitions);
+ for (j= 0; j < part_info->no_subparts; j++)
+ {
+ part_elem= sub_it++;
+ node_group[ng_index++]= part_elem->nodegroup_id;
+ //Here we should insert tablespace id based on tablespace name
+ }
+ }
+ }
+ tab->setNodeGroupIds(&node_group, ng_index);
+ tab->setFragmentType(ftype);
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Create a table in NDB Cluster
+ */
+static uint get_no_fragments(ulonglong max_rows)
+{
+#if MYSQL_VERSION_ID >= 50000
+ uint acc_row_size= 25 + /*safety margin*/ 2;
+#else
+ uint acc_row_size= pk_length*4;
+ /* add acc overhead */
+ if (pk_length <= 8) /* main page will set the limit */
+ acc_row_size+= 25 + /*safety margin*/ 2;
+ else /* overflow page will set the limit */
+ acc_row_size+= 4 + /*safety margin*/ 4;
+#endif
+ ulonglong acc_fragment_size= 512*1024*1024;
+#if MYSQL_VERSION_ID >= 50100
+ return (max_rows*acc_row_size)/acc_fragment_size+1;
+#else
+ return ((max_rows*acc_row_size)/acc_fragment_size+1
+ +1/*correct rounding*/)/2;
+#endif
+}
+
+
+/*
+ This routine is used to set-up fragmentation when the user has only specified
+ ENGINE = NDB and no user defined partitioning what so ever. Thus all values
+ will be based on default values. We will choose Linear Hash or Hash with
+ perfect spread dependent on a session variable defined in MySQL.
+*/
+static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length)
+{
+ NDBTAB::FragmentType ftype;
+ ushort node_group[MAX_PARTITIONS];
+ uint no_nodes= g_ndb_cluster_connection->no_db_nodes();
+ DBUG_ENTER("ndb_set_fragmentation");
+
+ if (form->s->max_rows == (ha_rows) 0)
+ {
+ no_fragments= no_nodes;
+ }
+ else
+ {
+ /*
+ Ensure that we get enough fragments to handle all rows and ensure that
+ the table is fully distributed by keeping the number of fragments a
+ multiple of the number of nodes.
+ */
+ uint fragments= get_no_fragments(form->s->max_rows);
+ no_fragments= no_nodes;
+ while (fragments > no_nodes)
+ {
+ fragments-= no_nodes;
+ no_fragments+= no_nodes;
+ if (no_fragments > MAX_PARTITIONS)
+ push_warning(current_thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "Ndb might have problems storing the max amount of rows specified");
+ no_fragments-= no_nodes;
+ break;
+ }
+ }
+ }
+ for (i= 0; i < no_fragments; i++)
+ node_group[i]= UNDEF_NODEGROUP;
+ if (opt_ndb_linear_hash)
+ ftype= NDBTAB::DistrKeyLin;
+ else
+ ftype= NDBTAB::DistrKeyHash;
+ tab.setFragmentType(ftype);
+ tab.setNodeGroupIds(&node_group, no_fragments);
+}
+
#endif /* HAVE_NDBCLUSTER_DB */
--- 1.87/sql/ha_ndbcluster.h 2005-06-04 19:23:34 +02:00
+++ 1.88/sql/ha_ndbcluster.h 2005-07-13 22:33:34 +02:00
@@ -420,7 +420,7 @@
int write_row(byte *buf);
int update_row(const byte *old_data, byte *new_data);
int delete_row(const byte *buf);
- int index_init(uint index);
+ int index_init(uint index, bool sorted);
int index_end();
int index_read(byte *buf, const byte *key, uint key_len,
enum ha_rkey_function find_flag);
@@ -462,6 +462,11 @@
const char * table_type() const;
const char ** bas_ext() const;
ulong table_flags(void) const;
+ ulong partition_flags(void) const
+ {
+ return (HA_CAN_PARTITION | HA_CAN_UPDATE_PARTITION_KEY |
+ HA_CAN_PARTITION_UNIQUE);
+ }
ulong index_flags(uint idx, uint part, bool all_parts) const;
uint max_supported_record_length() const;
uint max_supported_keys() const;
@@ -471,6 +476,7 @@
int rename_table(const char *from, const char *to);
int delete_table(const char *name);
int create(const char *name, TABLE *form, HA_CREATE_INFO *info);
+ int get_default_no_partitions(ulonglong max_rows);
THR_LOCK_DATA **store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
@@ -549,15 +555,21 @@
NDB_INDEX_TYPE get_index_type_from_table(uint index_no) const;
int check_index_fields_not_null(uint index_no);
- int pk_read(const byte *key, uint key_len, byte *buf);
- int complemented_pk_read(const byte *old_data, byte *new_data);
- int peek_row();
- int unique_index_read(const byte *key, uint key_len,
- byte *buf);
+ uint set_up_partition_info(partition_info *part_info,
+ TABLE *table,
+ void *tab);
+ int complemented_pk_read(const byte *old_data, byte *new_data,
+ uint32 old_part_id);
+ int pk_read(const byte *key, uint key_len, byte *buf, uint32 part_id);
int ordered_index_scan(const key_range *start_key,
const key_range *end_key,
- bool sorted, bool descending, byte* buf);
+ bool sorted, bool descending, byte* buf,
+ part_id_range *part_spec);
int full_table_scan(byte * buf);
+
+ int peek_row();
+ int unique_index_read(const byte *key, uint key_len,
+ byte *buf);
int fetch_next(NdbScanOperation* op);
int next_result(byte *buf);
int define_read_attrs(byte* buf, NdbOperation* op);
@@ -638,6 +650,12 @@
// NdbRecAttr has no reference to blob
typedef union { const NdbRecAttr *rec; NdbBlob *blob; void *ptr; } NdbValue;
NdbValue m_value[NDB_MAX_ATTRIBUTES_IN_TABLE];
+ partition_info *m_part_info;
+ byte *m_rec0;
+ Field **m_part_field_array;
+ bool m_use_partition_function;
+ bool m_read_multi_completed;
+ bool m_sorted;
bool m_use_write;
bool m_ignore_dup_key;
bool m_primary_key_update;
--- 1.218/sql/ha_innodb.cc 2005-06-21 15:14:19 +02:00
+++ 1.219/sql/ha_innodb.cc 2005-07-13 22:33:32 +02:00
@@ -3568,7 +3568,8 @@
ha_innobase::index_init(
/*====================*/
/* out: 0 or error number */
- uint keynr) /* in: key (index) number */
+ uint keynr, /* in: key (index) number */
+ bool sorted) /* in: 1 if result MUST be sorted according to index */
{
int error = 0;
DBUG_ENTER("index_init");
@@ -6609,7 +6610,7 @@
}
(void) extra(HA_EXTRA_KEYREAD);
- index_init(table->s->next_number_index);
+ index_init(table->s->next_number_index, 1);
/* We use an exclusive lock when we read the max key value from the
auto-increment column index. This is because then build_template will
--- 1.97/sql/ha_innodb.h 2005-06-21 08:49:13 +02:00
+++ 1.98/sql/ha_innodb.h 2005-07-13 22:33:33 +02:00
@@ -136,7 +136,7 @@
int delete_row(const byte * buf);
void unlock_row();
- int index_init(uint index);
+ int index_init(uint index, bool sorted);
int index_end();
int index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
--- 1.92/include/my_global.h 2005-06-10 03:00:45 +02:00
+++ 1.93/include/my_global.h 2005-07-13 22:33:29 +02:00
@@ -101,6 +101,94 @@
#define unlikely(x) __builtin_expect((x),0)
+/*
+ The macros below are useful in optimising places where it has been
+ discovered that cache misses stall the process and where a prefetch
+ of the cache line can improve matters. This is available in GCC 3.1.1
+ and later versions.
+ PREFETCH_READ says that addr is going to be used for reading and that
+ it is to be kept in caches if possible for a while
+ PREFETCH_WRITE also says that the item to be cached is likely to be
+ updated.
+ The *LOCALITY scripts are also available for experimentation purposes
+ mostly and should only be used if they are verified to improve matters.
+ For more input see GCC manual (available in GCC 3.1.1 and later)
+*/
+
+#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR > 10)
+#define PREFETCH_READ(addr) __builtin_prefetch(addr, 0, 3)
+#define PREFETCH_WRITE(addr) \
+ __builtin_prefetch(addr, 1, 3)
+#define PREFETCH_READ_LOCALITY(addr, locality) \
+ __builtin_prefetch(addr, 0, locality)
+#define PREFETCH_WRITE_LOCALITY(addr, locality) \
+ __builtin_prefetch(addr, 1, locality)
+#else
+#define PREFETCH_READ(addr)
+#define PREFETCH_READ_LOCALITY(addr, locality)
+#define PREFETCH_WRITE(addr)
+#define PREFETCH_WRITE_LOCALITY(addr, locality)
+#endif
+
+/*
+ The following macro is used to ensure that code often used in most
+ SQL statements and definitely for parts of the SQL processing are
+ kept in a code segment by itself. This has the advantage that the
+ risk of common code being overlapping in caches of the CPU is less.
+ This can be a cause of big performance problems.
+ Routines should be put in this category with care and when they are
+ put there one should also strive to make as much of the error handling
+ as possible (or uncommon code of the routine) to execute in a
+ separate method to avoid moving to much code to this code segment.
+
+ It is very easy to use, simply add HOT_METHOD at the end of the
+ function declaration.
+ For more input see GCC manual (available in GCC 2.95 and later)
+*/
+
+#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR > 94)
+#define HOT_METHOD \
+ __attribute__ ((section ("hot_code_section")))
+#else
+#define HOT_METHOD
+#endif
+
+/*
+ The following macro is used to ensure that popular global variables
+ are located next to each other to avoid that they contend for the
+ same cache lines.
+
+ It is very easy to use, simply add HOT_DATA at the end of the declaration
+ of the variable, the variable must be initialised because of the way
+ that linker works so a declaration using HOT_DATA should look like:
+ uint global_hot_data HOT_DATA = 0;
+ For more input see GCC manual (available in GCC 2.95 and later)
+*/
+
+#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR > 94)
+#define HOT_DATA \
+ __attribute__ ((section ("hot_data_section")))
+#else
+#define HOT_DATA
+#endif
+
+
+/*
+ The following macros are used to control inlining a bit more than
+ usual. These macros are used to ensure that inlining always or
+ never occurs (independent of compilation mode).
+ For more input see GCC manual (available in GCC 3.1.1 and later)
+*/
+
+#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR > 10)
+#define ALWAYS_INLINE __attribute__ ((always_inline))
+#define NEVER_INLINE __attribute__ ((noinline))
+#else
+#define ALWAYS_INLINE
+#define NEVER_INLINE
+#endif
+
+
/* Fix problem with S_ISLNK() on Linux */
#if defined(TARGET_OS_LINUX)
#undef _GNU_SOURCE
--- 1.121/sql/set_var.cc 2005-06-22 11:08:21 +02:00
+++ 1.122/sql/set_var.cc 2005-07-13 22:33:36 +02:00
@@ -786,6 +786,7 @@
{"have_isam", (char*) &have_isam, SHOW_HAVE},
{"have_ndbcluster", (char*) &have_ndbcluster, SHOW_HAVE},
{"have_openssl", (char*) &have_openssl, SHOW_HAVE},
+ {"have_partition_engine", (char*) &have_partition_db, SHOW_HAVE},
{"have_query_cache", (char*) &have_query_cache, SHOW_HAVE},
{"have_raid", (char*) &have_raid, SHOW_HAVE},
{"have_rtree_keys", (char*) &have_rtree_keys, SHOW_HAVE},
--- New file ---
+++ config/ac-macros/ha_partition.m4 05/07/11 14:56:03
dnl ---------------------------------------------------------------------------
dnl Macro: MYSQL_CHECK_PARTITIONDB
dnl Sets HAVE_PARTITION_DB if --with-partition is used
dnl ---------------------------------------------------------------------------
AC_DEFUN([MYSQL_CHECK_PARTITIONDB], [
AC_ARG_WITH([partition],
[
--with-partition
Enable the Partition Storage Engine],
[partitiondb="$withval"],
[partitiondb=no])
AC_MSG_CHECKING([for partition])
case "$partitiondb" in
yes )
AC_DEFINE([HAVE_PARTITION_DB], [1], [Builds Partition DB])
AC_MSG_RESULT([yes])
[partitiondb=yes]
;;
* )
AC_MSG_RESULT([no])
[partitiondb=no]
;;
esac
])
dnl ---------------------------------------------------------------------------
dnl END OF MYSQL_CHECK_PARTITION SECTION
dnl ---------------------------------------------------------------------------
--- New file ---
+++ mysql-test/include/have_partition.inc 05/07/12 10:10:29
#-- require r/have_partition.require
disable_query_log;
#show variables like "have_partition_engine";
enable_query_log;
--- New file ---
+++ mysql-test/r/have_partition.require 05/07/12 10:09:34
Variable_name Value
have_partition_engine YES
--- New file ---
+++ mysql-test/r/ndb_partition_key.result 05/07/11 18:21:34
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a int, b int, c int, d int, PRIMARY KEY(a,b,c))
ENGINE = NDB
PARTITION BY KEY (a,b);
insert into t1 values (1,1,1,1);
select * from t1;
a b c d
1 1 1 1
update t1 set d = 2 where a = 1 and b = 1 and c = 1;
select * from t1;
a b c d
1 1 1 2
delete from t1;
select * from t1;
a b c d
drop table t1;
CREATE TABLE t1 (a int, b int, c int, d int, PRIMARY KEY(a,b))
ENGINE = NDB
PARTITION BY KEY (c);
ERROR HY000: A PRIMARY KEY need to include all fields in the partition function
CREATE TABLE t1 (a int, b int, c int, PRIMARY KEY(a,b))
ENGINE = NDB
PARTITION BY KEY (a);
insert into t1 values
(1,1,3),(1,2,3),(1,3,3),(1,4,3),(1,5,3),(1,6,3),
(1,7,3),(1,8,3),(1,9,3),(1,10,3),(1,11,3),(1,12,3);
select * from t1 order by b;
a b c
1 1 3
1 2 3
1 3 3
1 4 3
1 5 3
1 6 3
1 7 3
1 8 3
1 9 3
1 10 3
1 11 3
1 12 3
DROP TABLE t1;
CREATE TABLE t1 (a INT, b CHAR(10) COLLATE latin1_bin, c INT, d INT,
PRIMARY KEY USING HASH (a,b,c))
ENGINE=NDB
DEFAULT CHARSET=latin1
PARTITION BY KEY (b);
insert into t1 values (1,"a",1,1),(2,"a",1,1),(3,"a",1,1);
-- t1 --
Fragment type: 2
K Value: 6
Min load factor: 78
Max load factor: 80
Temporary table: no
Number of attributes: 4
Number of primary keys: 3
Length of frm data: 295
TableStatus: Retrieved
-- Attributes --
a Int PRIMARY KEY
b Char(10;latin1_bin) PRIMARY KEY DISTRIBUTION KEY
c Int PRIMARY KEY
d Int NULL
-- Indexes --
PRIMARY KEY(a, b, c) - UniqueHashIndex
NDBT_ProgramExit: 0 - OK
DROP TABLE t1;
--- New file ---
+++ mysql-test/r/ndb_partition_range.result 05/07/11 18:21:28
drop table if exists t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b),
index (a))
engine = ndb
partition by range (a)
partitions 3
(partition x1 values less than (5),
partition x2 values less than (10),
partition x3 values less than (20));
INSERT into t1 values (1, 1, 1);
INSERT into t1 values (6, 1, 1);
INSERT into t1 values (10, 1, 1);
INSERT into t1 values (15, 1, 1);
select * from t1 order by a;
a b c
1 1 1
6 1 1
10 1 1
15 1 1
select * from t1 where a=1 order by a;
a b c
1 1 1
select * from t1 where a=15 and b=1 order by a;
a b c
15 1 1
select * from t1 where a=21 and b=1 order by a;
a b c
select * from t1 where a=21 order by a;
a b c
select * from t1 where a in (1,6,10,21) order by a;
a b c
select * from t1 where b=1 and a in (1,6,10,21) order by a;
a b c
1 1 1
6 1 1
10 1 1
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(b),
unique (a))
engine = ndb
partition by range (b)
partitions 3
(partition x1 values less than (5),
partition x2 values less than (10),
partition x3 values less than (20));
INSERT into t1 values (1, 1, 1);
INSERT into t1 values (2, 6, 1);
INSERT into t1 values (3, 10, 1);
INSERT into t1 values (4, 15, 1);
select * from t1 order by a;
a b c
1 1 1
2 6 1
3 10 1
4 15 1
UPDATE t1 set a = 5 WHERE b = 15;
select * from t1 order by a;
a b c
1 1 1
2 6 1
3 10 1
5 15 1
UPDATE t1 set a = 6 WHERE a = 5;
select * from t1 order by a;
a b c
1 1 1
2 6 1
3 10 1
6 15 1
select * from t1 where b=1 order by b;
a b c
1 1 1
select * from t1 where b=15 and a=1 order by b;
a b c
select * from t1 where b=21 and a=1 order by b;
a b c
select * from t1 where b=21 order by b;
a b c
select * from t1 where b in (1,6,10,21) order by b;
a b c
1 1 1
2 6 1
3 10 1
select * from t1 where a in (1,2,5,6) order by b;
a b c
1 1 1
2 6 1
6 15 1
select * from t1 where a=1 and b in (1,6,10,21) order by b;
a b c
1 1 1
DELETE from t1 WHERE b = 6;
DELETE from t1 WHERE a = 6;
drop table t1;
--- New file ---
+++ mysql-test/r/partition.result 05/07/11 18:20:53
drop table if exists t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a);
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a, b);
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition x1, partition x2, partition x3);
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition x1 nodegroup 0,
partition x2 nodegroup 1,
partition x3 nodegroup 2);
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition x1 engine myisam,
partition x2 engine myisam,
partition x3 engine myisam);
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 3
(partition x1 values in (1,2,9,4) tablespace ts1,
partition x2 values in (3, 11, 5, 7) tablespace ts2,
partition x3 values in (16, 8, 5+19, 70-43) tablespace ts3);
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (b*a)
partitions 3
(partition x1 values in (1,2,9,4) tablespace ts1,
partition x2 values in (3, 11, 5, 7) tablespace ts2,
partition x3 values in (16, 8, 5+19, 70-43) tablespace ts3);
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (b*a)
(partition x1 values in (1) tablespace ts1,
partition x2 values in (3, 11, 5, 7) tablespace ts2,
partition x3 values in (16, 8, 5+19, 70-43) tablespace ts3);
drop table t1;
partition by list (a)
partitions 3
(partition x1 values in (1,2,9,4) tablespace ts1,
partition x2 values in (3, 11, 5, 7) tablespace ts2,
partition x3 values in (16, 8, 5+19, 70-43) tablespace ts3);
ERROR 42000: Partitioning can not be used stand-alone in query near 'partition by list (a)
partitions 3
(partition x1 values in (1,2,9,4) tablespace ' at line 1
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2;
ERROR HY000: For LIST partitions each partition must be defined
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (sin(a))
partitions 3
(partition x1 values in (1,2,9,4) tablespace ts1,
partition x2 values in (3, 11, 5, 7) tablespace ts2,
partition x3 values in (16, 8, 5+19, 70-43) tablespace ts3);
ERROR HY000: The PARTITION function returns the wrong type
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a+2)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near '+2)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
part' at line 6
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near 'ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3)' at line 8
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a,d)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
ERROR HY000: Field in list of fields for partition function not found in table
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a + d)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
ERROR 42S22: Unknown column 'd' in 'field list'
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (sin(a))
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
ERROR HY000: The PARTITION function returns the wrong type
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition x1, partition x2);
ERROR 42000: Wrong number of partitions defined, mismatch with previous setting near ')'
at line 8
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (rand(a))
partitions 2
(partition x1, partition x2);
ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near
')
partitions 2
(partition x1, partition x2)' at line 6
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (rand(a))
partitions 2
(partition x1 values less than (0), partition x2 values less than (2));
ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near
')
partitions 2
(partition x1 values less than (0), partition x2 values less than' at line 6
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (rand(a))
partitions 2
(partition x1 values in (1), partition x2 values in (2));
ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near
')
partitions 2
(partition x1 values in (1), partition x2 values in (2))' at line 6
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a)
partitions 2
(partition x1 values less than (4),
partition x2 values less than (5));
ERROR HY000: Only RANGE PARTITIONING can use VALUES LESS THAN in partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a)
partitions 2
(partition x1 values in (4),
partition x2 values in (5));
ERROR HY000: Only LIST PARTITIONING can use VALUES IN in partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a)
partitions 2
(partition x1 values in (4,6),
partition x2 values in (5,7));
ERROR HY000: Only LIST PARTITIONING can use VALUES IN in partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by key (b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning
for subpartitioning
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by key (a, b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning
for subpartitioning
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by hash (a+b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning
for subpartitioning
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by key (b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning
for subpartitioning
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by key (a, b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning
for subpartitioning
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by hash (a+b);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning
for subpartitioning
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by hash (rand(a+b));
ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near
')' at line 7
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by hash (sin(a+b))
(partition x1 (subpartition x11, subpartition x12),
partition x2 (subpartition x21, subpartition x22));
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning
for subpartitioning
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by key (a+b)
(partition x1 values less than (1) (subpartition x11, subpartition x12),
partition x2 values less than (2) (subpartition x21, subpartition x22));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near '+b)
(partition x1 values less than (1) (subpartition x11, subpartition x12),
par' at line 7
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by key (a,d)
(partition x1 values less than (1) (subpartition x11, subpartition x12),
partition x2 values less than (2) (subpartition x21, subpartition x22));
ERROR HY000: Field in list of fields for partition function not found in table
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by hash (3+4);
ERROR HY000: It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning
for subpartitioning
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by hash (a+d)
(partition x1 values less than (1) (subpartition x11, subpartition x12),
partition x2 values less than (2) (subpartition x21, subpartition x22));
ERROR 42S22: Unknown column 'd' in 'field list'
--- New file ---
+++ mysql-test/r/partition_hash.result 05/07/11 18:21:12
drop table if exists t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a + 2)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
insert into t1 values (1,1,1);
insert into t1 values (2,1,1);
insert into t1 values (3,1,1);
insert into t1 values (4,1,1);
insert into t1 values (5,1,1);
select * from t1;
a b c
1 1 1
4 1 1
2 1 1
5 1 1
3 1 1
update t1 set c=3 where b=1;
select * from t1;
a b c
1 1 3
4 1 3
2 1 3
5 1 3
3 1 3
select b from t1 where a=3;
b
1
select b,c from t1 where a=1 AND b=1;
b c
1 3
delete from t1 where a=1;
delete from t1 where c=3;
select * from t1;
a b c
ALTER TABLE t1
partition by hash (a + 3)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
select * from t1;
a b c
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a)
(partition x1);
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
(partition x1);
drop table t1;
--- New file ---
+++ mysql-test/r/partition_list.result 05/07/11 18:21:05
drop table if exists t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null)
partition by list(a)
partitions 2
(partition x123 values in (1,5,6),
partition x234 values in (4,7,8));
INSERT into t1 VALUES (1,1,1);
INSERT into t1 VALUES (2,1,1);
ERROR HY000: Got error 1 from storage engine
INSERT into t1 VALUES (3,1,1);
ERROR HY000: Got error 1 from storage engine
INSERT into t1 VALUES (4,1,1);
INSERT into t1 VALUES (5,1,1);
INSERT into t1 VALUES (6,1,1);
INSERT into t1 VALUES (7,1,1);
INSERT into t1 VALUES (8,1,1);
INSERT into t1 VALUES (9,1,1);
ERROR HY000: Got error 1 from storage engine
INSERT into t1 VALUES (1,2,1);
INSERT into t1 VALUES (1,3,1);
INSERT into t1 VALUES (1,4,1);
INSERT into t1 VALUES (7,2,1);
INSERT into t1 VALUES (7,3,1);
INSERT into t1 VALUES (7,4,1);
SELECT * from t1;
a b c
1 1 1
5 1 1
6 1 1
1 2 1
1 3 1
1 4 1
4 1 1
7 1 1
8 1 1
7 2 1
7 3 1
7 4 1
SELECT * from t1 WHERE a=1;
a b c
1 1 1
1 2 1
1 3 1
1 4 1
SELECT * from t1 WHERE a=7;
a b c
7 1 1
7 2 1
7 3 1
7 4 1
SELECT * from t1 WHERE b=2;
a b c
1 2 1
7 2 1
UPDATE t1 SET a=8 WHERE a=7 AND b=3;
SELECT * from t1;
a b c
1 1 1
5 1 1
6 1 1
1 2 1
1 3 1
1 4 1
4 1 1
7 1 1
8 1 1
7 2 1
8 3 1
7 4 1
UPDATE t1 SET a=8 WHERE a=5 AND b=1;
SELECT * from t1;
a b c
1 1 1
6 1 1
1 2 1
1 3 1
1 4 1
4 1 1
7 1 1
8 1 1
7 2 1
8 3 1
7 4 1
8 1 1
DELETE from t1 WHERE a=8;
SELECT * from t1;
a b c
1 1 1
6 1 1
1 2 1
1 3 1
1 4 1
4 1 1
7 1 1
7 2 1
7 4 1
DELETE from t1 WHERE a=2;
SELECT * from t1;
a b c
1 1 1
6 1 1
1 2 1
1 3 1
1 4 1
4 1 1
7 1 1
7 2 1
7 4 1
DELETE from t1 WHERE a=5 OR a=6;
SELECT * from t1;
a b c
1 1 1
1 2 1
1 3 1
1 4 1
4 1 1
7 1 1
7 2 1
7 4 1
ALTER TABLE t1
partition by list(a)
partitions 2
(partition x123 values in (1,5,6),
partition x234 values in (4,7,8));
SELECT * from t1;
a b c
1 1 1
1 2 1
1 3 1
1 4 1
4 1 1
7 1 1
7 2 1
7 4 1
INSERT into t1 VALUES (6,2,1);
INSERT into t1 VALUES (2,2,1);
ERROR HY000: Got error 1 from storage engine
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by list (a)
subpartition by hash (a+b)
( partition x1 values in (1,2,3)
( subpartition x11 nodegroup 0,
subpartition x12 nodegroup 1),
partition x2 values in (4,5,6)
( subpartition x21 nodegroup 0,
subpartition x22 nodegroup 1)
);
INSERT into t1 VALUES (1,1,1);
INSERT into t1 VALUES (4,1,1);
INSERT into t1 VALUES (7,1,1);
ERROR HY000: Got error 1 from storage engine
UPDATE t1 SET a=5 WHERE a=1;
SELECT * from t1;
a b c
5 1 1
4 1 1
UPDATE t1 SET a=6 WHERE a=4;
SELECT * from t1;
a b c
5 1 1
6 1 1
DELETE from t1 WHERE a=6;
SELECT * from t1;
a b c
5 1 1
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by list (a)
subpartition by hash (a+b)
subpartitions 3
( partition x1 values in (1,2,4)
( subpartition x11 nodegroup 0,
subpartition x12 nodegroup 1),
partition x2 values in (3,5,6)
( subpartition x21 nodegroup 0,
subpartition x22 nodegroup 1)
);
ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setting near
'),
partition x2 values in (3,5,6)
( subpartition x21 nodegroup 0,
subpartition x' at line 11
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by list (a)
subpartition by hash (a+b)
( partition x1 values in (1)
( subpartition x11 nodegroup 0,
subpartition xextra,
subpartition x12 nodegroup 1),
partition x2 values in (2)
( subpartition x21 nodegroup 0,
subpartition x22 nodegroup 1)
);
ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setting near ')
)' at line 14
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by list (a+b)
( partition x1
( subpartition x11 engine myisam,
subpartition x12 engine myisam),
partition x2
( subpartition x21 engine myisam,
subpartition x22 engine myisam)
);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near 'list (a+b)
( partition x1
( subpartition x11 engine myisam,
subpartition x12 eng' at line 7
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by list (a+b)
( partition x1
( subpartition x11 engine myisam values in (0),
subpartition x12 engine myisam values in (1)),
partition x2
( subpartition x21 engine myisam values in (0),
subpartition x22 engine myisam values in (1))
);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near 'list (a+b)
( partition x1
( subpartition x11 engine myisam values in (0),
subpar' at line 7
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
(partition x1 values in (1,2,9,4) tablespace ts1);
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a);
ERROR HY000: For LIST partitions each partition must be defined
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (3+4)
partitions 2
(partition x1 values in (4) tablespace ts1,
partition x2 values in (8) tablespace ts2);
ERROR HY000: Constant/Random expression in (sub)partitioning function is not allowed
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a+d)
partitions 2
(partition x1 values in (4) tablespace ts1,
partition x2 values in (8) tablespace ts2);
ERROR 42S22: Unknown column 'd' in 'order clause'
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in (4),
partition x2);
ERROR HY000: LIST PARTITIONING requires definition of VALUES IN for each partition
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in (4),
partition x2 values less than (5));
ERROR HY000: Only RANGE PARTITIONING can use VALUES LESS THAN in partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in (4,6),
partition x2);
ERROR HY000: LIST PARTITIONING requires definition of VALUES IN for each partition
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in (4, 12+9),
partition x2 values in (3, 21));
ERROR HY000: Multiple definition of same constant in list partitioning
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in (4.0, 12+8),
partition x2 values in (3, 21));
ERROR HY000: VALUES IN value must be of same type as partition function
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in 4,
partition x2 values in (5));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near '4,
partition x2 values in (5))' at line 8
--- New file ---
+++ mysql-test/r/partition_order.result 05/07/11 18:20:59
drop table if exists t1;
CREATE TABLE t1 (
a int not null,
b int not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 order by b;
a b
1 1
35 2
30 4
2 5
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b int unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b tinyint not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b tinyint unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b smallint not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b smallint unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b mediumint not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b mediumint unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b bigint unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b bigint not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b bigint not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b float not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b double not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b double unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b float unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b double precision not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b double precision unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b decimal not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b char(10) not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > 0 order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b varchar(10) not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b varchar(10) not null,
primary key(a),
index (b(5)))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b varchar(10) binary not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b tinytext not null,
primary key(a),
index (b(10)))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b text not null,
primary key(a),
index (b(10)))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b mediumtext not null,
primary key(a),
index (b(10)))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b longtext not null,
primary key(a),
index (b(10)))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b enum('1','2', '4', '5') not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b >= '1' order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b set('1','2', '4', '5') not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b >= '1' order by b;
a b
1 1
35 2
30 4
2 5
drop table t1;
CREATE TABLE t1 (
a int not null,
b date not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '2001-01-01');
INSERT into t1 values (2, '2005-01-01');
INSERT into t1 values (30, '2004-01-01');
INSERT into t1 values (35, '2002-01-01');
select * from t1 force index (b) where b > '2000-01-01' order by b;
a b
1 2001-01-01
35 2002-01-01
30 2004-01-01
2 2005-01-01
drop table t1;
CREATE TABLE t1 (
a int not null,
b datetime not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '2001-01-01 00:00:00');
INSERT into t1 values (2, '2005-01-01 00:00:00');
INSERT into t1 values (30, '2004-01-01 00:00:00');
INSERT into t1 values (35, '2002-01-01 00:00:00');
select * from t1 force index (b) where b > '2000-01-01 00:00:00' order by b;
a b
1 2001-01-01 00:00:00
35 2002-01-01 00:00:00
30 2004-01-01 00:00:00
2 2005-01-01 00:00:00
drop table t1;
CREATE TABLE t1 (
a int not null,
b timestamp not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '2001-01-01 00:00:00');
INSERT into t1 values (2, '2005-01-01 00:00:00');
INSERT into t1 values (30, '2004-01-01 00:00:00');
INSERT into t1 values (35, '2002-01-01 00:00:00');
select * from t1 force index (b) where b > '2000-01-01 00:00:00' order by b;
a b
1 2001-01-01 00:00:00
35 2002-01-01 00:00:00
30 2004-01-01 00:00:00
2 2005-01-01 00:00:00
drop table t1;
CREATE TABLE t1 (
a int not null,
b time not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, '01:00:00');
INSERT into t1 values (2, '05:00:00');
INSERT into t1 values (30, '04:00:00');
INSERT into t1 values (35, '02:00:00');
select * from t1 force index (b) where b > '00:00:00' order by b;
a b
1 01:00:00
35 02:00:00
30 04:00:00
2 05:00:00
drop table t1;
CREATE TABLE t1 (
a int not null,
b year not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 2001);
INSERT into t1 values (2, 2005);
INSERT into t1 values (30, 2004);
INSERT into t1 values (35, 2002);
select * from t1 force index (b) where b > 2000 order by b;
a b
1 2001
35 2002
30 2004
2 2005
drop table t1;
CREATE TABLE t1 (
a int not null,
b bit(5) not null,
c int,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, b'00001', NULL);
INSERT into t1 values (2, b'00101', 2);
INSERT into t1 values (30, b'00100', 2);
INSERT into t1 values (35, b'00010', NULL);
select a from t1 force index (b) where b > b'00000' order by b;
a
1
35
30
2
drop table t1;
CREATE TABLE t1 (
a int not null,
b bit(15) not null,
c int,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, b'000000000000001', NULL);
INSERT into t1 values (2, b'001010000000101', 2);
INSERT into t1 values (30, b'001000000000100', 2);
INSERT into t1 values (35, b'000100000000010', NULL);
select a from t1 force index (b) where b > b'000000000000000' order by b;
a
1
35
30
2
drop table t1;
CREATE TABLE t1 (
a int not null,
b int,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
INSERT into t1 values (1, 1);
INSERT into t1 values (5, NULL);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
INSERT into t1 values (40, NULL);
select * from t1 force index (b) where b < 10 OR b IS NULL order by b;
a b
5 NULL
40 NULL
1 1
35 2
30 4
2 5
drop table t1;
--- New file ---
+++ mysql-test/r/partition_range.result 05/07/11 18:21:21
drop table if exists t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a)
partitions 3
(partition x1 values less than (5) tablespace ts1,
partition x2 values less than (10) tablespace ts2,
partition x3 values less than maxvalue tablespace ts3);
INSERT into t1 values (1, 1, 1);
INSERT into t1 values (6, 1, 1);
INSERT into t1 values (10, 1, 1);
INSERT into t1 values (15, 1, 1);
select * from t1;
a b c
1 1 1
6 1 1
10 1 1
15 1 1
ALTER TABLE t1
partition by range (a)
partitions 3
(partition x1 values less than (5) tablespace ts1,
partition x2 values less than (10) tablespace ts2,
partition x3 values less than maxvalue tablespace ts3);
select * from t1;
a b c
1 1 1
6 1 1
10 1 1
15 1 1
drop table if exists t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null)
partition by range (a)
partitions 3
(partition x1 values less than (5) tablespace ts1,
partition x2 values less than (10) tablespace ts2,
partition x3 values less than maxvalue tablespace ts3);
INSERT into t1 values (1, 1, 1);
INSERT into t1 values (6, 1, 1);
INSERT into t1 values (10, 1, 1);
INSERT into t1 values (15, 1, 1);
select * from t1;
a b c
1 1 1
6 1 1
10 1 1
15 1 1
ALTER TABLE t1
partition by range (a)
partitions 3
(partition x1 values less than (5) tablespace ts1,
partition x2 values less than (10) tablespace ts2,
partition x3 values less than maxvalue tablespace ts3);
select * from t1;
a b c
1 1 1
6 1 1
10 1 1
15 1 1
drop table if exists t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a)
partitions 3
(partition x1 values less than (5) tablespace ts1,
partition x2 values less than (10) tablespace ts2,
partition x3 values less than (15) tablespace ts3);
INSERT into t1 values (1, 1, 1);
INSERT into t1 values (6, 1, 1);
INSERT into t1 values (10, 1, 1);
INSERT into t1 values (15, 1, 1);
ERROR HY000: Got error 1 from storage engine
select * from t1;
a b c
1 1 1
6 1 1
10 1 1
ALTER TABLE t1
partition by range (a)
partitions 3
(partition x1 values less than (5) tablespace ts1,
partition x2 values less than (10) tablespace ts2,
partition x3 values less than (15) tablespace ts3);
select * from t1;
a b c
1 1 1
6 1 1
10 1 1
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a)
(partition x1 values less than (1));
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a);
ERROR HY000: For RANGE partitions each partition must be defined
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a+d)
partitions 2
(partition x1 values less than (4) tablespace ts1,
partition x2 values less than (8) tablespace ts2);
ERROR 42S22: Unknown column 'd' in 'order clause'
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a)
partitions 2
(partition x1 values less than (4.0) tablespace ts1,
partition x2 values less than (8) tablespace ts2);
ERROR HY000: VALUES LESS THAN value must be of same type as partition function
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (3+4)
partitions 2
(partition x1 values less than (4) tablespace ts1,
partition x2 values less than (8) tablespace ts2);
ERROR HY000: Constant/Random expression in (sub)partitioning function is not allowed
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a)
partitions 2
(partition x1 values less than (4),
partition x2);
ERROR HY000: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a)
partitions 2
(partition x1 values in (4),
partition x2);
ERROR HY000: Only LIST PARTITIONING can use VALUES IN in partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a)
partitions 2
(partition x1 values in (4),
partition x2 values less than (5));
ERROR HY000: Only LIST PARTITIONING can use VALUES IN in partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values less than 4,
partition x2 values less than (5));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near '4,
partition x2 values less than (5))' at line 8
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a)
partitions 2
(partition x1 values less than maxvalue,
partition x2 values less than (5));
ERROR 42000: MAXVALUE can only be used in last partition definition near '))' at line 9
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a)
partitions 2
(partition x1 values less than maxvalue,
partition x2 values less than maxvalue);
ERROR 42000: MAXVALUE can only be used in last partition definition near 'maxvalue)' at
line 9
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (a)
partitions 2
(partition x1 values less than (4),
partition x2 values less than (3));
ERROR HY000: VALUES LESS THAN value must be increasing for each partition
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (sin(a))
partitions 2
(partition x1 values less than (4),
partition x2 values less than (5));
ERROR HY000: The PARTITION function returns the wrong type
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by hash (a+b)
( partition x1 values less than (1)
( subpartition x11,
subpartition x12),
partition x2 values less than (5)
( subpartition x21,
subpartition x22)
);
SELECT * from t1;
a b c
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by hash (a+b)
( partition x1 values less than (1)
( subpartition x11 tablespace t1 engine myisam nodegroup 0,
subpartition x12 tablespace t2 engine myisam nodegroup 1),
partition x2 values less than (5)
( subpartition x21 tablespace t1 engine myisam nodegroup 0,
subpartition x22 tablespace t2 engine myisam nodegroup 1)
);
SELECT * from t1;
a b c
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by hash (a+b)
( partition x1 values less than (1)
( subpartition x11 tablespace t1 nodegroup 0,
subpartition x12 tablespace t2 nodegroup 1),
partition x2 values less than (5)
( subpartition x21 tablespace t1 nodegroup 0,
subpartition x22 tablespace t2 nodegroup 1)
);
SELECT * from t1;
a b c
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by hash (a+b)
( partition x1 values less than (1)
( subpartition x11 engine myisam nodegroup 0,
subpartition x12 engine myisam nodegroup 1),
partition x2 values less than (5)
( subpartition x21 engine myisam nodegroup 0,
subpartition x22 engine myisam nodegroup 1)
);
INSERT into t1 VALUES (1,1,1);
INSERT into t1 VALUES (4,1,1);
INSERT into t1 VALUES (5,1,1);
ERROR HY000: Got error 1 from storage engine
SELECT * from t1;
a b c
1 1 1
4 1 1
ALTER TABLE t1
partition by range (a)
subpartition by hash (a+b)
( partition x1 values less than (1)
( subpartition x11 engine myisam nodegroup 0,
subpartition x12 engine myisam nodegroup 1),
partition x2 values less than (5)
( subpartition x21 engine myisam nodegroup 0,
subpartition x22 engine myisam nodegroup 1)
);
SELECT * from t1;
a b c
1 1 1
4 1 1
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by hash (a+b)
( partition x1 values less than (1)
( subpartition x11 tablespace t1 engine myisam,
subpartition x12 tablespace t2 engine myisam),
partition x2 values less than (5)
( subpartition x21 tablespace t1 engine myisam,
subpartition x22 tablespace t2 engine myisam)
);
INSERT into t1 VALUES (1,1,1);
INSERT into t1 VALUES (4,1,1);
INSERT into t1 VALUES (5,1,1);
ERROR HY000: Got error 1 from storage engine
SELECT * from t1;
a b c
1 1 1
4 1 1
ALTER TABLE t1
partition by range (a)
subpartition by hash (a+b)
( partition x1 values less than (1)
( subpartition x11 tablespace t1 engine myisam,
subpartition x12 tablespace t2 engine myisam),
partition x2 values less than (5)
( subpartition x21 tablespace t1 engine myisam,
subpartition x22 tablespace t2 engine myisam)
);
SELECT * from t1;
a b c
1 1 1
4 1 1
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by hash (a+b)
( partition x1 values less than (1)
( subpartition x11 tablespace t1,
subpartition x12 tablespace t2),
partition x2 values less than (5)
( subpartition x21 tablespace t1,
subpartition x22 tablespace t2)
);
INSERT into t1 VALUES (1,1,1);
INSERT into t1 VALUES (4,1,1);
INSERT into t1 VALUES (5,1,1);
ERROR HY000: Got error 1 from storage engine
SELECT * from t1;
a b c
1 1 1
4 1 1
ALTER TABLE t1
partition by range (a)
subpartition by hash (a+b)
( partition x1 values less than (1)
( subpartition x11 tablespace t1 engine myisam,
subpartition x12 tablespace t2 engine myisam),
partition x2 values less than (5)
( subpartition x21 tablespace t1 engine myisam,
subpartition x22 tablespace t2 engine myisam)
);
SELECT * from t1;
a b c
1 1 1
4 1 1
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by hash (a+b)
( partition x1 values less than (1)
( subpartition x11 engine myisam,
subpartition x12 engine myisam),
partition x2 values less than (5)
( subpartition x21 engine myisam,
subpartition x22 engine myisam)
);
INSERT into t1 VALUES (1,1,1);
INSERT into t1 VALUES (4,1,1);
INSERT into t1 VALUES (5,1,1);
ERROR HY000: Got error 1 from storage engine
SELECT * from t1;
a b c
1 1 1
4 1 1
ALTER TABLE t1
partition by range (a)
subpartition by hash (a+b)
( partition x1 values less than (1)
( subpartition x11 engine myisam,
subpartition x12 engine myisam),
partition x2 values less than (5)
( subpartition x21 engine myisam,
subpartition x22 engine myisam)
);
SELECT * from t1;
a b c
1 1 1
4 1 1
drop table t1;
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a+b)
subpartition by key (a)
( partition x1
( subpartition x11 engine myisam,
subpartition x12 engine myisam),
partition x2
( subpartition x21 engine myisam,
subpartition x22 engine myisam)
);
ERROR HY000: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by range (a+b)
( partition x1
( subpartition x11 engine myisam values less than (0),
subpartition x12 engine myisam values less than (1)),
partition x2
( subpartition x21 engine myisam values less than (0),
subpartition x22 engine myisam values less than (1))
);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to
your MySQL server version for the right syntax to use near 'range (a+b)
( partition x1
( subpartition x11 engine myisam values less than (0)' at line 7
--- New file ---
+++ mysql-test/t/ndb_partition_key.test 05/07/11 18:20:14
-- source include/have_ndb.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
#
# Basic syntax test
#
# Support for partition key verified
CREATE TABLE t1 (a int, b int, c int, d int, PRIMARY KEY(a,b,c))
ENGINE = NDB
PARTITION BY KEY (a,b);
insert into t1 values (1,1,1,1);
select * from t1;
update t1 set d = 2 where a = 1 and b = 1 and c = 1;
select * from t1;
delete from t1;
select * from t1;
drop table t1;
# only support for partition key on primary key
--error 1449
CREATE TABLE t1 (a int, b int, c int, d int, PRIMARY KEY(a,b))
ENGINE = NDB
PARTITION BY KEY (c);
CREATE TABLE t1 (a int, b int, c int, PRIMARY KEY(a,b))
ENGINE = NDB
PARTITION BY KEY (a);
insert into t1 values
(1,1,3),(1,2,3),(1,3,3),(1,4,3),(1,5,3),(1,6,3),
(1,7,3),(1,8,3),(1,9,3),(1,10,3),(1,11,3),(1,12,3);
select * from t1 order by b;
DROP TABLE t1;
#
# Test partition and char support
#
CREATE TABLE t1 (a INT, b CHAR(10) COLLATE latin1_bin, c INT, d INT,
PRIMARY KEY USING HASH (a,b,c))
ENGINE=NDB
DEFAULT CHARSET=latin1
PARTITION BY KEY (b);
insert into t1 values (1,"a",1,1),(2,"a",1,1),(3,"a",1,1);
# should show only one attribute with DISTRIBUTION KEY
--exec $NDB_TOOLS_DIR/ndb_desc --no-defaults -d test t1 | sed 's/Version: [0-9]*//'
DROP TABLE t1;
--- New file ---
+++ mysql-test/t/ndb_partition_range.test 05/07/11 18:20:04
#--disable_abort_on_error
#
# Simple test for the partition storage engine
# Focuses on range partitioning tests
#
#-- source include/have_partition.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# Partition by range, basic
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b),
index (a))
engine = ndb
partition by range (a)
partitions 3
(partition x1 values less than (5),
partition x2 values less than (10),
partition x3 values less than (20));
# Simple insert and verify test
INSERT into t1 values (1, 1, 1);
INSERT into t1 values (6, 1, 1);
INSERT into t1 values (10, 1, 1);
INSERT into t1 values (15, 1, 1);
select * from t1 order by a;
select * from t1 where a=1 order by a;
select * from t1 where a=15 and b=1 order by a;
select * from t1 where a=21 and b=1 order by a;
select * from t1 where a=21 order by a;
select * from t1 where a in (1,6,10,21) order by a;
select * from t1 where b=1 and a in (1,6,10,21) order by a;
drop table t1;
#
# Partition by range, basic
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(b),
unique (a))
engine = ndb
partition by range (b)
partitions 3
(partition x1 values less than (5),
partition x2 values less than (10),
partition x3 values less than (20));
# Simple insert and verify test
INSERT into t1 values (1, 1, 1);
INSERT into t1 values (2, 6, 1);
INSERT into t1 values (3, 10, 1);
INSERT into t1 values (4, 15, 1);
select * from t1 order by a;
UPDATE t1 set a = 5 WHERE b = 15;
select * from t1 order by a;
UPDATE t1 set a = 6 WHERE a = 5;
select * from t1 order by a;
select * from t1 where b=1 order by b;
select * from t1 where b=15 and a=1 order by b;
select * from t1 where b=21 and a=1 order by b;
select * from t1 where b=21 order by b;
select * from t1 where b in (1,6,10,21) order by b;
select * from t1 where a in (1,2,5,6) order by b;
select * from t1 where a=1 and b in (1,6,10,21) order by b;
DELETE from t1 WHERE b = 6;
DELETE from t1 WHERE a = 6;
drop table t1;
--- New file ---
+++ mysql-test/t/partition.test 05/07/11 18:18:54
#--disable_abort_on_error
#
# Simple test for the partition storage engine
# Taken fromm the select test
#
#-- source include/have_partition.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# Partition by key no partition defined => OK
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a);
drop table t1;
#
# Partition by key no partition, list of fields
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a, b);
drop table t1;
#
# Partition by key specified 3 partitions and defined 3 => ok
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition x1, partition x2, partition x3);
drop table t1;
#
# Partition by key specifying nodegroup
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition x1 nodegroup 0,
partition x2 nodegroup 1,
partition x3 nodegroup 2);
drop table t1;
#
# Partition by key specifying engine
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition x1 engine myisam,
partition x2 engine myisam,
partition x3 engine myisam);
drop table t1;
#
# Partition by key specifying tablespace
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
drop table t1;
#
# Partition by key list, basic
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 3
(partition x1 values in (1,2,9,4) tablespace ts1,
partition x2 values in (3, 11, 5, 7) tablespace ts2,
partition x3 values in (16, 8, 5+19, 70-43) tablespace ts3);
drop table t1;
#
# Partition by key list, list function
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (b*a)
partitions 3
(partition x1 values in (1,2,9,4) tablespace ts1,
partition x2 values in (3, 11, 5, 7) tablespace ts2,
partition x3 values in (16, 8, 5+19, 70-43) tablespace ts3);
drop table t1;
#
# Partition by key list, list function, no spec of #partitions
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (b*a)
(partition x1 values in (1) tablespace ts1,
partition x2 values in (3, 11, 5, 7) tablespace ts2,
partition x3 values in (16, 8, 5+19, 70-43) tablespace ts3);
drop table t1;
#
# Partition by key stand-alone error
#
--error 1064
partition by list (a)
partitions 3
(partition x1 values in (1,2,9,4) tablespace ts1,
partition x2 values in (3, 11, 5, 7) tablespace ts2,
partition x3 values in (16, 8, 5+19, 70-43) tablespace ts3);
#
# Partition by key list, number of partitions defined, no partition defined
#
--error 1435
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2;
#
# Partition by key list, wrong result type
#
--error 1434
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (sin(a))
partitions 3
(partition x1 values in (1,2,9,4) tablespace ts1,
partition x2 values in (3, 11, 5, 7) tablespace ts2,
partition x3 values in (16, 8, 5+19, 70-43) tablespace ts3);
#
# Partition by key, partition function not allowed
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a+2)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
#
# Partition by key, no partition name
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
#
# Partition by key, invalid field in field list
#
--error 1431
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a,d)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
#
# Partition by hash, invalid field in function
#
--error 1054
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a + d)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
#
# Partition by hash, invalid result type
#
--error 1434
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (sin(a))
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
#
# Partition by key specified 3 partitions but only defined 2 => error
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
partitions 3
(partition x1, partition x2);
#
# Partition by key specified 3 partitions but only defined 2 => error
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (rand(a))
partitions 2
(partition x1, partition x2);
#
# Partition by key specified 3 partitions but only defined 2 => error
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by range (rand(a))
partitions 2
(partition x1 values less than (0), partition x2 values less than (2));
#
# Partition by key specified 3 partitions but only defined 2 => error
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (rand(a))
partitions 2
(partition x1 values in (1), partition x2 values in (2));
#
# Partition by hash, values less than error
#
--error 1424
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a)
partitions 2
(partition x1 values less than (4),
partition x2 values less than (5));
#
# Partition by hash, values in error
#
--error 1424
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a)
partitions 2
(partition x1 values in (4),
partition x2 values in (5));
#
# Partition by hash, values in error
#
--error 1424
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a)
partitions 2
(partition x1 values in (4,6),
partition x2 values in (5,7));
#
# Subpartition by key, no partitions defined, single field
#
--error 1444
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by key (b);
#
# Subpartition by key, no partitions defined, list of fields
#
--error 1444
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by key (a, b);
#
# Subpartition by hash, no partitions defined
#
--error 1444
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by hash (a+b);
#
# Subpartition by key, no partitions defined, single field
#
--error 1444
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by key (b);
#
# Subpartition by key, no partitions defined, list of fields
#
--error 1444
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by key (a, b);
#
# Subpartition by hash, no partitions defined
#
--error 1444
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by hash (a+b);
#
# Subpartition by hash, no partitions defined, wrong subpartition function
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by hash (rand(a+b));
#
# Subpartition by hash, wrong subpartition function
#
--error 1444
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by hash (sin(a+b))
(partition x1 (subpartition x11, subpartition x12),
partition x2 (subpartition x21, subpartition x22));
#
# Subpartition by hash, no partitions defined, wrong subpartition function
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by key (a+b)
(partition x1 values less than (1) (subpartition x11, subpartition x12),
partition x2 values less than (2) (subpartition x21, subpartition x22));
#
# Subpartition by hash, no partitions defined, wrong subpartition function
#
--error 1431
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by key (a,d)
(partition x1 values less than (1) (subpartition x11, subpartition x12),
partition x2 values less than (2) (subpartition x21, subpartition x22));
#
# Subpartition by hash, no partitions defined, wrong subpartition function
#
--error 1444
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by hash (3+4);
#
# Subpartition by hash, no partitions defined, wrong subpartition function
#
--error 1054
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by range (a)
subpartition by hash (a+d)
(partition x1 values less than (1) (subpartition x11, subpartition x12),
partition x2 values less than (2) (subpartition x21, subpartition x22));
--- New file ---
+++ mysql-test/t/partition_hash.test 05/07/11 18:19:02
#--disable_abort_on_error
#
# Simple test for the partition storage engine
# Taken fromm the select test
#
#-- source include/have_partition.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# Partition by hash, basic
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a + 2)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
insert into t1 values (1,1,1);
insert into t1 values (2,1,1);
insert into t1 values (3,1,1);
insert into t1 values (4,1,1);
insert into t1 values (5,1,1);
select * from t1;
update t1 set c=3 where b=1;
select * from t1;
select b from t1 where a=3;
select b,c from t1 where a=1 AND b=1;
delete from t1 where a=1;
delete from t1 where c=3;
select * from t1;
ALTER TABLE t1
partition by hash (a + 3)
partitions 3
(partition x1 tablespace ts1,
partition x2 tablespace ts2,
partition x3 tablespace ts3);
select * from t1;
drop table t1;
#
# Partition by hash, only one partition
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by hash (a)
(partition x1);
drop table t1;
#
# Partition by key, only one partition
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by key (a)
(partition x1);
drop table t1;
--- New file ---
+++ mysql-test/t/partition_list.test 05/07/11 18:19:16
#--disable_abort_on_error
#
# Simple test for the partition storage engine
# testing list partitioning
#
#-- source include/have_partition.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# Test ordinary list partitioning that it works ok
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null)
partition by list(a)
partitions 2
(partition x123 values in (1,5,6),
partition x234 values in (4,7,8));
INSERT into t1 VALUES (1,1,1);
--error 1030
INSERT into t1 VALUES (2,1,1);
--error 1030
INSERT into t1 VALUES (3,1,1);
INSERT into t1 VALUES (4,1,1);
INSERT into t1 VALUES (5,1,1);
INSERT into t1 VALUES (6,1,1);
INSERT into t1 VALUES (7,1,1);
INSERT into t1 VALUES (8,1,1);
--error 1030
INSERT into t1 VALUES (9,1,1);
INSERT into t1 VALUES (1,2,1);
INSERT into t1 VALUES (1,3,1);
INSERT into t1 VALUES (1,4,1);
INSERT into t1 VALUES (7,2,1);
INSERT into t1 VALUES (7,3,1);
INSERT into t1 VALUES (7,4,1);
SELECT * from t1;
SELECT * from t1 WHERE a=1;
SELECT * from t1 WHERE a=7;
SELECT * from t1 WHERE b=2;
UPDATE t1 SET a=8 WHERE a=7 AND b=3;
SELECT * from t1;
UPDATE t1 SET a=8 WHERE a=5 AND b=1;
SELECT * from t1;
DELETE from t1 WHERE a=8;
SELECT * from t1;
DELETE from t1 WHERE a=2;
SELECT * from t1;
DELETE from t1 WHERE a=5 OR a=6;
SELECT * from t1;
ALTER TABLE t1
partition by list(a)
partitions 2
(partition x123 values in (1,5,6),
partition x234 values in (4,7,8));
SELECT * from t1;
INSERT into t1 VALUES (6,2,1);
--error 1030
INSERT into t1 VALUES (2,2,1);
drop table t1;
#
# Subpartition by hash, two partitions and two subpartitions
# Defined node group
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by list (a)
subpartition by hash (a+b)
( partition x1 values in (1,2,3)
( subpartition x11 nodegroup 0,
subpartition x12 nodegroup 1),
partition x2 values in (4,5,6)
( subpartition x21 nodegroup 0,
subpartition x22 nodegroup 1)
);
INSERT into t1 VALUES (1,1,1);
INSERT into t1 VALUES (4,1,1);
--error 1030
INSERT into t1 VALUES (7,1,1);
UPDATE t1 SET a=5 WHERE a=1;
SELECT * from t1;
UPDATE t1 SET a=6 WHERE a=4;
SELECT * from t1;
DELETE from t1 WHERE a=6;
SELECT * from t1;
drop table t1;
#
# Subpartition by hash, wrong number of subpartitions
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by list (a)
subpartition by hash (a+b)
subpartitions 3
( partition x1 values in (1,2,4)
( subpartition x11 nodegroup 0,
subpartition x12 nodegroup 1),
partition x2 values in (3,5,6)
( subpartition x21 nodegroup 0,
subpartition x22 nodegroup 1)
);
#
# Subpartition by hash, wrong number of subpartitions
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by list (a)
subpartition by hash (a+b)
( partition x1 values in (1)
( subpartition x11 nodegroup 0,
subpartition xextra,
subpartition x12 nodegroup 1),
partition x2 values in (2)
( subpartition x21 nodegroup 0,
subpartition x22 nodegroup 1)
);
#
# Subpartition by list => error
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by list (a+b)
( partition x1
( subpartition x11 engine myisam,
subpartition x12 engine myisam),
partition x2
( subpartition x21 engine myisam,
subpartition x22 engine myisam)
);
#
# Subpartition by list => error
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key (a,b))
partition by key (a)
subpartition by list (a+b)
( partition x1
( subpartition x11 engine myisam values in (0),
subpartition x12 engine myisam values in (1)),
partition x2
( subpartition x21 engine myisam values in (0),
subpartition x22 engine myisam values in (1))
);
#
# Partition by list, only one partition => ok
#
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
(partition x1 values in (1,2,9,4) tablespace ts1);
drop table t1;
#
# Partition by list, no partition => error
#
--error 1435
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a);
#
# Partition by list, constant partition function not allowed
#
--error 1429
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (3+4)
partitions 2
(partition x1 values in (4) tablespace ts1,
partition x2 values in (8) tablespace ts2);
#
# Partition by list, invalid field in function
#
--error 1054
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a+d)
partitions 2
(partition x1 values in (4) tablespace ts1,
partition x2 values in (8) tablespace ts2);
#
# Partition by list, no values in definition
#
--error 1423
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in (4),
partition x2);
#
# Partition by list, values less than error
#
--error 1424
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in (4),
partition x2 values less than (5));
#
# Partition by list, no values in definition
#
--error 1423
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in (4,6),
partition x2);
#
# Partition by list, duplicate values
#
--error 1438
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in (4, 12+9),
partition x2 values in (3, 21));
#
# Partition by list, wrong constant result type (not INT)
#
--error 1437
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in (4.0, 12+8),
partition x2 values in (3, 21));
#
# Partition by list, missing parenthesis
#
--error 1064
CREATE TABLE t1 (
a int not null,
b int not null,
c int not null,
primary key(a,b))
partition by list (a)
partitions 2
(partition x1 values in 4,
partition x2 values in (5));
--- New file ---
+++ mysql-test/t/partition_order.test 05/07/11 18:19:07
#--disable_abort_on_error
#
# Simple test for the partition storage engine
# Focuses on tests of ordered index read
#
#-- source include/have_partition.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# Ordered index read, int type
#
CREATE TABLE t1 (
a int not null,
b int not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 order by b;
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, unsigned int type
#
CREATE TABLE t1 (
a int not null,
b int unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, tiny int type
#
CREATE TABLE t1 (
a int not null,
b tinyint not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, unsigned tinyint type
#
CREATE TABLE t1 (
a int not null,
b tinyint unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, smallint type
#
CREATE TABLE t1 (
a int not null,
b smallint not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, unsigned smallint type
#
CREATE TABLE t1 (
a int not null,
b smallint unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, mediumint type
#
CREATE TABLE t1 (
a int not null,
b mediumint not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, unsigned int type
#
CREATE TABLE t1 (
a int not null,
b mediumint unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, unsigned bigint type
#
CREATE TABLE t1 (
a int not null,
b bigint unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, bigint type
#
CREATE TABLE t1 (
a int not null,
b bigint not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, bigint type
#
CREATE TABLE t1 (
a int not null,
b bigint not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, float type
#
CREATE TABLE t1 (
a int not null,
b float not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, double type
#
CREATE TABLE t1 (
a int not null,
b double not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, unsigned double type
#
CREATE TABLE t1 (
a int not null,
b double unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, unsigned float type
#
CREATE TABLE t1 (
a int not null,
b float unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, double precision type
#
CREATE TABLE t1 (
a int not null,
b double precision not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, unsigned double precision type
#
CREATE TABLE t1 (
a int not null,
b double precision unsigned not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, decimal type
#
CREATE TABLE t1 (
a int not null,
b decimal not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, 1);
INSERT into t1 values (2, 5);
INSERT into t1 values (30, 4);
INSERT into t1 values (35, 2);
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, char type
#
CREATE TABLE t1 (
a int not null,
b char(10) not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > 0 order by b;
drop table t1;
#
# Ordered index read, varchar type
#
CREATE TABLE t1 (
a int not null,
b varchar(10) not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
drop table t1;
#
# Ordered index read, varchar type limited index size
#
CREATE TABLE t1 (
a int not null,
b varchar(10) not null,
primary key(a),
index (b(5)))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
drop table t1;
#
# Ordered index read, varchar binary type
#
CREATE TABLE t1 (
a int not null,
b varchar(10) binary not null,
primary key(a),
index (b))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
drop table t1;
#
# Ordered index read, tinytext type
#
CREATE TABLE t1 (
a int not null,
b tinytext not null,
primary key(a),
index (b(10)))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
drop table t1;
#
# Ordered index read, text type
#
CREATE TABLE t1 (
a int not null,
b text not null,
primary key(a),
index (b(10)))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
drop table t1;
#
# Ordered index read, mediumtext type
#
CREATE TABLE t1 (
a int not null,
b mediumtext not null,
primary key(a),
index (b(10)))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
drop table t1;
#
# Ordered index read, longtext type
#
CREATE TABLE t1 (
a int not null,
b longtext not null,
primary key(a),
index (b(10)))
partition by range (a)
partitions 2
(partition x1 values less than (25),
partition x2 values less than (100));
# Insert a couple of tuples
INSERT into t1 values (1, '1');
INSERT into t1 values (2, '5');
INSERT into t1 values (30, '4');
INSERT into t1 values (35, '2');
select * from t1 force index (b) where b > '0' order by b;
drop table t1;
#
# Ordered index read, enum type
| Thread |
|---|
| • bk commit into 5.1 tree (mronstrom:1.1846) BUG#8928 | mikael | 15 Jul |