mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 13:02:28 +01:00
9e6784924a
Fixed compile-pentium64 scripts Fixed wrong estimate of update_with_key_prefix in sql-bench Merge bk-internal.mysql.com:/home/bk/mysql-5.1 into mysql.com:/home/my/mysql-5.1 Fixed unsafe define of uint4korr() Fixed that --extern works with mysql-test-run.pl Small trivial cleanups This also fixes a bug in counting number of rows that are updated when we have many simultanous queries Move all connection handling and command exectuion main loop from sql_parse.cc to sql_connection.cc Split handle_one_connection() into reusable sub functions. Split create_new_thread() into reusable sub functions. Added thread_scheduler; Preliminary interface code for future thread_handling code. Use 'my_thread_id' for internal thread id's Make thr_alarm_kill() to depend on thread_id instead of thread Make thr_abort_locks_for_thread() depend on thread_id instead of thread In store_globals(), set my_thread_var->id to be thd->thread_id. Use my_thread_var->id as basis for my_thread_name() The above changes makes the connection we have between THD and threads more soft. Added a lot of DBUG_PRINT() and DBUG_ASSERT() functions Fixed compiler warnings Fixed core dumps when running with --debug Removed setting of signal masks (was never used) Made event code call pthread_exit() (portability fix) Fixed that event code doesn't call DBUG_xxx functions before my_thread_init() is called. Made handling of thread_id and thd->variables.pseudo_thread_id uniform. Removed one common 'not freed memory' warning from mysqltest Fixed a couple of usage of not initialized warnings (unlikely cases) Suppress compiler warnings from bdb and (for the moment) warnings from ndb BitKeeper/deleted/.del-SETUP.sh.rej: Rename: BUILD/SETUP.sh.rej -> BitKeeper/deleted/.del-SETUP.sh.rej BitKeeper/deleted/.del-configure.in.rej: Rename: configure.in.rej -> BitKeeper/deleted/.del-configure.in.rej BitKeeper/deleted/.del-my_global.h.rej: Rename: include/my_global.h.rej -> BitKeeper/deleted/.del-my_global.h.rej BitKeeper/deleted/.del-my_pthread.h.rej: Rename: include/my_pthread.h.rej -> BitKeeper/deleted/.del-my_pthread.h.rej BitKeeper/deleted/.del-mysql_client_test.c.rej: Rename: tests/mysql_client_test.c.rej -> BitKeeper/deleted/.del-mysql_client_test.c.rej BitKeeper/deleted/.del-mysqld.cc.rej~35c1c438e11ebd89: Rename: sql/mysqld.cc.rej -> BitKeeper/deleted/.del-mysqld.cc.rej~35c1c438e11ebd89 BitKeeper/deleted/.del-sql_parse.cc.rej: Rename: sql/sql_parse.cc.rej -> BitKeeper/deleted/.del-sql_parse.cc.rej BitKeeper/deleted/.del-table.cc.rej: Rename: sql/table.cc.rej -> BitKeeper/deleted/.del-table.cc.rej BitKeeper/deleted/.del-thr_alarm.c.rej: Rename: mysys/thr_alarm.c.rej -> BitKeeper/deleted/.del-thr_alarm.c.rej BUILD/compile-pentium64: Update this to be in line with compile-pentium BUILD/compile-pentium: Send command line options to SETUP.sh BUILD/compile-solaris-sparc-debug: Update scripts BUILD/compile-solaris-sparc-forte: Update scripts BUILD/compile-solaris-sparc-purify: Update scripts BUILD/compile-solaris-sparc: Update scripts BitKeeper/deleted/.del-DbtupSystemRestart.cpp~15b54d7e4e75d2d: Removed compiler warning BitKeeper/deleted/.del-ha_berkeley.cc: Moved get_auto_primary_key() here as int5store() gives (wrong) compiler warnings in win64 configure.in: Added detection of port_create and port.h (for future)as --- manual merge BitKeeper/deleted/.del-ha_berkeley.h: Moved get_auto_primary_key() to ha_berkeley.cc BitKeeper/deleted/.del-mysqlmanager.c~e97636d71145a0b: Fixed compiler warnings BitKeeper/etc/ignore: added storage/ndb/src/ndbapi/ndberror_check client/mysqlbinlog.cc: Removed not needed 'static' (caused compiler warning) client/mysqldump.c: Fixed compiler warnings from 'max' build client/mysqltest.c: Free warning and query memory no abort. (Removes strange warnings on screen if mysql-test-run fails) Removed compiler warnings Portability fix for windows (windows doesn't have mode_t) client/sql_string.h: Removed compiler warning cmd-line-utils/readline/xmalloc.c: Fixed compiler warnings from 'max' build extra/charset2html.c: Fixed compiler warnings extra/comp_err.c: Fixed compiler warnings from 'max' build extra/yassl/include/lock.hpp: Fix for windows64 extra/yassl/include/openssl/ssl.h: Changed prototype for SSL_set_fd() to fix compiler warnings (and possible errors) on windows 64 bit extra/yassl/include/socket_wrapper.hpp: Moved socket_t to ssl.h, to be able to removed compiler warnings on windows 64 bit extra/yassl/include/yassl.hpp: Fix for windows64 extra/yassl/src/ssl.cpp: Removed compiler warning Detect wrong parameter (Happens when running test suite on solaris) Changed prototype for SSL_set_fd() to fix compiler warnings (and possible errors) on windows 64 bit extra/yassl/taocrypt/src/integer.cpp: Fixed compiler warnings extra/yassl/testsuite/testsuite.cpp: Removed compiler warning include/config-win.h: Added HAVE_WINSOCK2 (for future) include/my_dbug.h: Fixed DBUG_PROCESS() so that we don't get compiler warnings for it include/my_global.h: Fixed unsafe define of uint4korr() manual merge (ignore changes from 5.0) Fixed warnings on win64 when using int5store and int6store include/my_pthread.h: Added my_thread_id typedef Renamed 'my_thread_id() function to my_thead_dbug_id() include/thr_alarm.h: Make thr_alarm_kill() to depend on thread_id instead of thread include/thr_lock.h: Make thr_abort_locks_for_thread() depend on thread_id instead of thread libmysql/libmysql.def: Fixed compiler warnings on win64 libmysqld/CMakeLists.txt: Added missing files libmysqld/Makefile.am: Added new files libmysqld/lib_sql.cc: Remove not needed code (store_globals() now takes care of things) mysql-test/lib/mtr_report.pl: Removed wrong messages when using --extern mysql-test/mysql-test-run.pl: Fixed that --extern works Print help on stdout instead of stderr (make it easier to pipe it to less) Fixed typo that caused mysql-test-run.pl to fail on Solaris mysql-test/r/keywords.result: manual merge mysql-test/r/ndb_lock.result: After merge fixes mysql-test/r/ps.result: Portability fix mysql-test/t/disabled.def: Disabled ndb_alter_table as this very often fails for me (and have done it for a long time) mysql-test/t/keywords.test: manual merge mysql-test/t/ndb_lock.test: Added other possible error code mysql-test/t/ps.test: Portability fix (when compiling without DLOPEN) mysql-test/t/wait_timeout.test: Don't run this if we are not using a thread per connection (as other thread_handling code may not support timeouts) mysys/base64.c: Fixed compiler warnings on win64 mysys/mf_keycache.c: Fixed compiler warnings mysys/my_getopt.c: Fixed compiler warning mysys/my_init.c: Fixed compiler warning Re-indented long comment mysys/my_thr_init.c: Always use mysys_var->id to generate thread name (makes things uniform accross thread implementations and thread usage) Always generate my_thread_name() when using DBUG Ensure mysys_var->pthread_self is set Fixed compiler warnings mysys/ptr_cmp.c: Fixed compiler warnings from 'max' build mysys/thr_alarm.c: Change thr_alarm_kill() to use mysys_var->id instead of thread id Fixed compiler warning on windows mysys/thr_lock.c: Change thr_abort_locks_for_thread() to use mysys_var->id instead of thread id Add purecov statements around not tested code Fixed compiler warnings mysys/thr_mutex.c: my_thread_id() -> my_thread_dbug_id() server-tools/instance-manager/guardian.cc: Fixed compiler warning server-tools/instance-manager/instance.cc: Fixed compiler warning server-tools/instance-manager/mysql_connection.cc: Fixed compiler warnings server-tools/instance-manager/mysqlmanager.cc: Fixed compiler warnings sql/CMakeLists.txt: Added missing files sql/Makefile.am: Added new files sql/event_scheduler.cc: Added pthread_exit() calls Ensure DBUG_xxx calls are not made before my_thread_init() Use common functions to set up thread handling sql/field.h: manual merge sql/ha_ndbcluster.cc: Removed some trivial 'current_thd' calls sql/handler.cc: Avoid warnings on KILL_CONNECTION Don't print out null pointer with printf() (Causes crashes on Solaris) sql/item.cc: Fixed compiler warnings from 'max' build sql/item_cmpfunc.cc: After merge fixes sql/item_func.cc: Merge embedded and normal code usage (GET_LOCK, RELEASE_LOCK now works on my_thread_id instead of pthread_t) Fixed compiler warning sql/item_strfunc.cc: Fixed compiler warning sql/item_timefunc.cc: Fixed compiler warnings sql/lock.cc: Use (new) parameter to thr_abort_locks_for_thread() sql/log.cc: Fixed compiler warning sql/log_event.cc: Fixed compiler warnings about not used variable sql/mysql_priv.h: Remove TEST_NO_THREADS (not needed with new scheduler interface) Added functions from sql_connect.cc and new functions from sql_parse.cc sql/mysqld.cc: Use thread_scheduler structure to dispatch calls (make code more dynamic) Change --one-thread option to use thread_scheduler interface Made ONE_THREAD option independent of DBUG_BUILD --one-thread is now depricated. One should instead use '--thread-handling=no-threads' Remove not used uname() function. Split create_new_thread() into reusable sub functions. Preliminary interface code for future thread_handling code. Fixed compiler warnings sql/parse_file.cc: Don't send zero pointer to fn_format() (Causes crashes when using --debug) sql/repl_failsafe.cc: Setup pseudo_thread_id same way as other code sql/set_var.cc: Added variables 'thread_handling' Prepare for future variable 'thread_pool_size' Fixed compiler warnings sql/set_var.h: Fixed compiler warning sql/slave.cc: Setup pseudo_thread_id same way as other code Removed not used signal mask sql/sql_acl.cc: Fixed compiler warnings from 'max' build sql/sql_base.cc: Fixed long comments Normalized variable setup Don't destroy value of thd->variables.pseduo_thread_id More DBUG_PRINT()'s More DBUG_ASSERT()'s Fixed compiler warnings from 'max' build sql/sql_class.cc: Remove thd->real_id and thd->dbug_thread_id Added DBUG_ASSERT() Use thread_scheduler to signal threads to be killed. In THD::store_globals(), set my_thread_var->id to be thd->thread_id. Fixed compiler warnings sql/sql_class.h: Use 'my_thread_id' for internal thread id's Remove not needed THD elements: block_signals and dbug_thread_id Added 'thread_scheduler' scheduling extension element to THD sql/sql_insert.cc: After merge fixes (This actually fixes a bug in old code when many connections are in use) Setup pseudo_thread_id same way as other code Removed not used signal mask Initialize variable that may be used unitialized on error conditions (not fatal) sql/sql_parse.cc: Move connection related code to sql_connect.cc Remove setting of signal mask (not needed) Ensure TABLE_LIST->alias is set for generated TABLE_LIST elements (fixed core dumps when running with --debug) Added previous 'optional' element to reset_mgh() Removed not needed DBUG_PRINT call sql/sql_partition.cc: Fixed compiler warnings sql/sql_prepare.cc: Removed not needed casts Fixed compiler warnings from 'max' build sql/sql_select.cc: Fixed compiler warnings sql-bench/bench-init.pl.sh: Added --one-missing-tests sql-bench/example: Better example sql-bench/run-all-tests.sh: Added --only-missing-tests sql-bench/test-insert.sh: Fixed wrong estimate of update_with_key_prefix sql/sql_show.cc: Don't send pthread_kill() to threads to detect if they exists. (Not that useful and causes problems with future thread_handling code) Fixed compiler warnings sql/sql_table.cc: Simplify code Fixed compiler warnings sql/sql_test.cc: Remove dbug_thread_id from test output sql/sql_view.cc: Don't send zero pointer to fn_format() sql/tztime.cc: Fixed compiler warning sql/udf_example.def: Fixed compiler warnings on win64 sql/unireg.cc: Initialize variable that may be used unitialized on error conditions storage/archive/archive_test.c: Fixed compiler warnings storage/archive/azio.c: Fixed compiler warnings storage/innobase/dict/dict0crea.c: Fixed compiler warnings detected on windows64 storage/innobase/dict/dict0dict.c: Fixed compiler warnings detected on windows64 storage/innobase/dict/dict0load.c: Fixed compiler warnings detected on windows64 storage/innobase/dict/dict0mem.c: Fixed compiler warnings detected on windows64 storage/innobase/eval/eval0proc.c: Fixed compiler warnings detected on windows64 storage/innobase/handler/ha_innodb.cc: Fixed compiler warnings detected on windows64 storage/innobase/include/ut0byte.ic: Fixed compiler warnings on win64 storage/innobase/include/ut0ut.ic: Fixed compiler warnings on win64 storage/innobase/mtr/mtr0log.c: Fixed compiler warnings detected on windows64 storage/innobase/pars/pars0lex.l: Fixed warnings on win64 storage/innobase/rem/rem0cmp.c: Fixed compiler warnings detected on windows64 storage/innobase/row/row0mysql.c: Fixed compiler warnings detected on windows64 storage/innobase/row/row0sel.c: Fixed compiler warnings detected on windows64 storage/innobase/sync/sync0rw.c: Fixed compiler warnings detected on windows64 storage/innobase/trx/trx0trx.c: Fixed compiler warnings detected on windows64 storage/myisam/mi_log.c: my_thread_id() -> my_thread_debug_id() storage/myisam/mi_packrec.c: Fixed compiler warnings detected on windows64 storage/myisam/myisamchk.c: Fixed compiler warnings from 'max' build storage/ndb/src/common/debugger/EventLogger.cpp: Fixed compiler warnings storage/ndb/src/common/util/ConfigValues.cpp: Removed compiler warnings storage/ndb/src/common/util/NdbSqlUtil.cpp: Removed compiler warnings storage/ndb/src/cw/cpcd/CPCD.hpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/backup/Backup.cpp: Fixed compiler warnings detected on windows64 storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp: Fixed compiler warnings detected on windows64 storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp: Fixed compiler warnings detected on windows64 storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtup/tuppage.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtup/tuppage.hpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/dbtux/DbtuxStat.cpp: Fixed compiler warnings storage/ndb/src/kernel/blocks/diskpage.hpp: Fixed compiler warnings storage/ndb/src/kernel/vm/ndbd_malloc.cpp: Fixed compiler warnings storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp: Fixed compiler warnings storage/ndb/src/mgmclient/main.cpp: Fixed compiler warnings storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp: Fixed compiler warnings storage/ndb/src/ndbapi/NdbOperationExec.cpp: Fixed compiler warnings storage/ndb/src/ndbapi/SignalSender.cpp: Fixed compiler warnings storage/ndb/tools/restore/consumer_restore.cpp: Fixed compiler warnings strings/ctype-ucs2.c: Fixed compiler warnings strings/ctype-utf8.c: Fixed compiler warnings strings/decimal.c: Fixed compiler warnings strings/my_strchr.c: Fixed conflict between function and prototype support-files/compiler_warnings.supp: Ignore warnings from sql_yacc.cc that are hard to remove Ignore some not important warnings from windows 64 bit build Suppress warnings from bdb and (for the moment) warnings from ndb Suppress all warnings for all pushbuild platforms (should make all trees green) vio/viosslfactories.c: Added DBUG_PRINT BUILD/compile-pentium64-max: New BitKeeper file ``BUILD/compile-pentium64-max'' libmysqld/scheduler.cc: New BitKeeper file ``libmysqld/scheduler.cc'' libmysqld/sql_connect.cc: New BitKeeper file ``libmysqld/sql_connect.cc'' mysql-test/include/one_thread_per_connection.inc: New BitKeeper file ``mysql-test/include/one_thread_per_connection.inc'' mysql-test/r/no-threads.result: New BitKeeper file ``mysql-test/r/no-threads.result'' mysql-test/r/one_thread_per_connection.require: New BitKeeper file ``mysql-test/r/one_thread_per_connection.require'' mysql-test/t/no-threads-master.opt: New BitKeeper file ``mysql-test/t/no-threads-master.opt'' mysql-test/t/no-threads.test: New BitKeeper file ``mysql-test/t/no-threads.test'' sql/scheduler.cc: New BitKeeper file ``sql/scheduler.cc'' sql/scheduler.h: New BitKeeper file ``sql/scheduler.h'' sql/sql_connect.cc: New BitKeeper file ``sql/sql_connect.cc''
1064 lines
27 KiB
C
1064 lines
27 KiB
C
/***********************************************************************
|
|
Comparison services for records
|
|
|
|
(c) 1994-1996 Innobase Oy
|
|
|
|
Created 7/1/1994 Heikki Tuuri
|
|
************************************************************************/
|
|
|
|
#include "rem0cmp.h"
|
|
|
|
#ifdef UNIV_NONINL
|
|
#include "rem0cmp.ic"
|
|
#endif
|
|
|
|
#include "srv0srv.h"
|
|
|
|
/* ALPHABETICAL ORDER
|
|
==================
|
|
|
|
The records are put into alphabetical order in the following
|
|
way: let F be the first field where two records disagree.
|
|
If there is a character in some position n where the the
|
|
records disagree, the order is determined by comparison of
|
|
the characters at position n, possibly after
|
|
collating transformation. If there is no such character,
|
|
but the corresponding fields have different lengths, then
|
|
if the data type of the fields is paddable,
|
|
shorter field is padded with a padding character. If the
|
|
data type is not paddable, longer field is considered greater.
|
|
Finally, the SQL null is bigger than any other value.
|
|
|
|
At the present, the comparison functions return 0 in the case,
|
|
where two records disagree only in the way that one
|
|
has more fields than the other. */
|
|
|
|
#ifdef UNIV_DEBUG
|
|
/*****************************************************************
|
|
Used in debug checking of cmp_dtuple_... .
|
|
This function is used to compare a data tuple to a physical record. If
|
|
dtuple has n fields then rec must have either m >= n fields, or it must
|
|
differ from dtuple in some of the m fields rec has. */
|
|
static
|
|
int
|
|
cmp_debug_dtuple_rec_with_match(
|
|
/*============================*/
|
|
/* out: 1, 0, -1, if dtuple is greater, equal,
|
|
less than rec, respectively, when only the
|
|
common first fields are compared */
|
|
dtuple_t* dtuple, /* in: data tuple */
|
|
rec_t* rec, /* in: physical record which differs from
|
|
dtuple in some of the common fields, or which
|
|
has an equal number or more fields than
|
|
dtuple */
|
|
const ulint* offsets,/* in: array returned by rec_get_offsets() */
|
|
ulint* matched_fields);/* in/out: number of already
|
|
completely matched fields; when function
|
|
returns, contains the value for current
|
|
comparison */
|
|
#endif /* UNIV_DEBUG */
|
|
#ifndef UNIV_HOTBACKUP
|
|
/*****************************************************************
|
|
This function is used to compare two data fields for which the data type
|
|
is such that we must use MySQL code to compare them. The prototype here
|
|
must be a copy of the the one in ha_innobase.cc! */
|
|
extern
|
|
int
|
|
innobase_mysql_cmp(
|
|
/*===============*/
|
|
/* out: 1, 0, -1, if a is greater,
|
|
equal, less than b, respectively */
|
|
int mysql_type, /* in: MySQL type */
|
|
uint charset_number, /* in: number of the charset */
|
|
unsigned char* a, /* in: data field */
|
|
unsigned int a_length, /* in: data field length,
|
|
not UNIV_SQL_NULL */
|
|
unsigned char* b, /* in: data field */
|
|
unsigned int b_length); /* in: data field length,
|
|
not UNIV_SQL_NULL */
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
/*************************************************************************
|
|
Transforms the character code so that it is ordered appropriately for the
|
|
language. This is only used for the latin1 char set. MySQL does the
|
|
comparisons for other char sets. */
|
|
UNIV_INLINE
|
|
ulint
|
|
cmp_collate(
|
|
/*========*/
|
|
/* out: collation order position */
|
|
ulint code) /* in: code of a character stored in database record */
|
|
{
|
|
return((ulint) srv_latin1_ordering[code]);
|
|
}
|
|
|
|
/*****************************************************************
|
|
Returns TRUE if two columns are equal for comparison purposes. */
|
|
|
|
ibool
|
|
cmp_cols_are_equal(
|
|
/*===============*/
|
|
/* out: TRUE if the columns are
|
|
considered equal in comparisons */
|
|
const dict_col_t* col1, /* in: column 1 */
|
|
const dict_col_t* col2, /* in: column 2 */
|
|
ibool check_charsets)
|
|
/* in: whether to check charsets */
|
|
{
|
|
if (dtype_is_non_binary_string_type(col1->mtype, col1->prtype)
|
|
&& dtype_is_non_binary_string_type(col2->mtype, col2->prtype)) {
|
|
|
|
/* Both are non-binary string types: they can be compared if
|
|
and only if the charset-collation is the same */
|
|
|
|
if (check_charsets) {
|
|
return(dtype_get_charset_coll(col1->prtype)
|
|
== dtype_get_charset_coll(col2->prtype));
|
|
} else {
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
if (dtype_is_binary_string_type(col1->mtype, col1->prtype)
|
|
&& dtype_is_binary_string_type(col2->mtype, col2->prtype)) {
|
|
|
|
/* Both are binary string types: they can be compared */
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
if (col1->mtype != col2->mtype) {
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
if (col1->mtype == DATA_INT
|
|
&& (col1->prtype & DATA_UNSIGNED)
|
|
!= (col2->prtype & DATA_UNSIGNED)) {
|
|
|
|
/* The storage format of an unsigned integer is different
|
|
from a signed integer: in a signed integer we OR
|
|
0x8000... to the value of positive integers. */
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
return(col1->mtype != DATA_INT || col1->len == col2->len);
|
|
}
|
|
|
|
#ifndef UNIV_HOTBACKUP
|
|
/*****************************************************************
|
|
Innobase uses this function to compare two data fields for which the data type
|
|
is such that we must compare whole fields or call MySQL to do the comparison */
|
|
static
|
|
int
|
|
cmp_whole_field(
|
|
/*============*/
|
|
/* out: 1, 0, -1, if a is greater,
|
|
equal, less than b, respectively */
|
|
ulint mtype, /* in: main type */
|
|
ulint prtype, /* in: precise type */
|
|
unsigned char* a, /* in: data field */
|
|
unsigned int a_length, /* in: data field length,
|
|
not UNIV_SQL_NULL */
|
|
unsigned char* b, /* in: data field */
|
|
unsigned int b_length) /* in: data field length,
|
|
not UNIV_SQL_NULL */
|
|
{
|
|
float f_1;
|
|
float f_2;
|
|
double d_1;
|
|
double d_2;
|
|
int swap_flag = 1;
|
|
|
|
switch (mtype) {
|
|
|
|
case DATA_DECIMAL:
|
|
/* Remove preceding spaces */
|
|
for (; a_length && *a == ' '; a++, a_length--);
|
|
for (; b_length && *b == ' '; b++, b_length--);
|
|
|
|
if (*a == '-') {
|
|
if (*b != '-') {
|
|
return(-1);
|
|
}
|
|
|
|
a++; b++;
|
|
a_length--;
|
|
b_length--;
|
|
|
|
swap_flag = -1;
|
|
|
|
} else if (*b == '-') {
|
|
|
|
return(1);
|
|
}
|
|
|
|
while (a_length > 0 && (*a == '+' || *a == '0')) {
|
|
a++; a_length--;
|
|
}
|
|
|
|
while (b_length > 0 && (*b == '+' || *b == '0')) {
|
|
b++; b_length--;
|
|
}
|
|
|
|
if (a_length != b_length) {
|
|
if (a_length < b_length) {
|
|
return(-swap_flag);
|
|
}
|
|
|
|
return(swap_flag);
|
|
}
|
|
|
|
while (a_length > 0 && *a == *b) {
|
|
|
|
a++; b++; a_length--;
|
|
}
|
|
|
|
if (a_length == 0) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
if (*a > *b) {
|
|
return(swap_flag);
|
|
}
|
|
|
|
return(-swap_flag);
|
|
case DATA_DOUBLE:
|
|
d_1 = mach_double_read(a);
|
|
d_2 = mach_double_read(b);
|
|
|
|
if (d_1 > d_2) {
|
|
return(1);
|
|
} else if (d_2 > d_1) {
|
|
return(-1);
|
|
}
|
|
|
|
return(0);
|
|
|
|
case DATA_FLOAT:
|
|
f_1 = mach_float_read(a);
|
|
f_2 = mach_float_read(b);
|
|
|
|
if (f_1 > f_2) {
|
|
return(1);
|
|
} else if (f_2 > f_1) {
|
|
return(-1);
|
|
}
|
|
|
|
return(0);
|
|
case DATA_BLOB:
|
|
if (prtype & DATA_BINARY_TYPE) {
|
|
|
|
ut_print_timestamp(stderr);
|
|
fprintf(stderr,
|
|
" InnoDB: Error: comparing a binary BLOB"
|
|
" with a character set sensitive\n"
|
|
"InnoDB: comparison!\n");
|
|
}
|
|
/* fall through */
|
|
case DATA_VARMYSQL:
|
|
case DATA_MYSQL:
|
|
return(innobase_mysql_cmp(
|
|
(int)(prtype & DATA_MYSQL_TYPE_MASK),
|
|
(uint)dtype_get_charset_coll(prtype),
|
|
a, a_length, b, b_length));
|
|
default:
|
|
fprintf(stderr,
|
|
"InnoDB: unknown type number %lu\n",
|
|
(ulong) mtype);
|
|
ut_error;
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
|
|
/*****************************************************************
|
|
This function is used to compare two data fields for which we know the
|
|
data type. */
|
|
|
|
int
|
|
cmp_data_data_slow(
|
|
/*===============*/
|
|
/* out: 1, 0, -1, if data1 is greater, equal,
|
|
less than data2, respectively */
|
|
ulint mtype, /* in: main type */
|
|
ulint prtype, /* in: precise type */
|
|
byte* data1, /* in: data field (== a pointer to a memory
|
|
buffer) */
|
|
ulint len1, /* in: data field length or UNIV_SQL_NULL */
|
|
byte* data2, /* in: data field (== a pointer to a memory
|
|
buffer) */
|
|
ulint len2) /* in: data field length or UNIV_SQL_NULL */
|
|
{
|
|
#ifndef UNIV_HOTBACKUP
|
|
ulint data1_byte;
|
|
ulint data2_byte;
|
|
ulint cur_bytes;
|
|
|
|
if (len1 == UNIV_SQL_NULL || len2 == UNIV_SQL_NULL) {
|
|
|
|
if (len1 == len2) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
if (len1 == UNIV_SQL_NULL) {
|
|
/* We define the SQL null to be the smallest possible
|
|
value of a field in the alphabetical order */
|
|
|
|
return(-1);
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
|
|
if (mtype >= DATA_FLOAT
|
|
|| (mtype == DATA_BLOB
|
|
&& 0 == (prtype & DATA_BINARY_TYPE)
|
|
&& dtype_get_charset_coll(prtype)
|
|
!= DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
|
|
|
|
return(cmp_whole_field(mtype, prtype,
|
|
data1, (unsigned) len1,
|
|
data2, (unsigned) len2));
|
|
}
|
|
|
|
/* Compare then the fields */
|
|
|
|
cur_bytes = 0;
|
|
|
|
for (;;) {
|
|
if (len1 <= cur_bytes) {
|
|
if (len2 <= cur_bytes) {
|
|
|
|
return(0);
|
|
}
|
|
|
|
data1_byte = dtype_get_pad_char(mtype, prtype);
|
|
|
|
if (data1_byte == ULINT_UNDEFINED) {
|
|
|
|
return(-1);
|
|
}
|
|
} else {
|
|
data1_byte = *data1;
|
|
}
|
|
|
|
if (len2 <= cur_bytes) {
|
|
data2_byte = dtype_get_pad_char(mtype, prtype);
|
|
|
|
if (data2_byte == ULINT_UNDEFINED) {
|
|
|
|
return(1);
|
|
}
|
|
} else {
|
|
data2_byte = *data2;
|
|
}
|
|
|
|
if (data1_byte == data2_byte) {
|
|
/* If the bytes are equal, they will remain such even
|
|
after the collation transformation below */
|
|
|
|
goto next_byte;
|
|
}
|
|
|
|
if (mtype <= DATA_CHAR
|
|
|| (mtype == DATA_BLOB
|
|
&& 0 == (prtype & DATA_BINARY_TYPE))) {
|
|
|
|
data1_byte = cmp_collate(data1_byte);
|
|
data2_byte = cmp_collate(data2_byte);
|
|
}
|
|
|
|
if (data1_byte > data2_byte) {
|
|
|
|
return(1);
|
|
} else if (data1_byte < data2_byte) {
|
|
|
|
return(-1);
|
|
}
|
|
next_byte:
|
|
/* Next byte */
|
|
cur_bytes++;
|
|
data1++;
|
|
data2++;
|
|
}
|
|
#else /* !UNIV_HOTBACKUP */
|
|
/* This function depends on MySQL code that is not included in
|
|
InnoDB Hot Backup builds. Besides, this function should never
|
|
be called in InnoDB Hot Backup. */
|
|
ut_error;
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
|
|
return(0); /* Not reached */
|
|
}
|
|
|
|
/*****************************************************************
|
|
This function is used to compare a data tuple to a physical record.
|
|
Only dtuple->n_fields_cmp first fields are taken into account for
|
|
the the data tuple! If we denote by n = n_fields_cmp, then rec must
|
|
have either m >= n fields, or it must differ from dtuple in some of
|
|
the m fields rec has. If rec has an externally stored field we do not
|
|
compare it but return with value 0 if such a comparison should be
|
|
made. */
|
|
|
|
int
|
|
cmp_dtuple_rec_with_match(
|
|
/*======================*/
|
|
/* out: 1, 0, -1, if dtuple is greater, equal,
|
|
less than rec, respectively, when only the
|
|
common first fields are compared, or
|
|
until the first externally stored field in
|
|
rec */
|
|
dtuple_t* dtuple, /* in: data tuple */
|
|
rec_t* rec, /* in: physical record which differs from
|
|
dtuple in some of the common fields, or which
|
|
has an equal number or more fields than
|
|
dtuple */
|
|
const ulint* offsets,/* in: array returned by rec_get_offsets() */
|
|
ulint* matched_fields, /* in/out: number of already completely
|
|
matched fields; when function returns,
|
|
contains the value for current comparison */
|
|
ulint* matched_bytes) /* in/out: number of already matched
|
|
bytes within the first field not completely
|
|
matched; when function returns, contains the
|
|
value for current comparison */
|
|
{
|
|
#ifndef UNIV_HOTBACKUP
|
|
dfield_t* dtuple_field; /* current field in logical record */
|
|
ulint dtuple_f_len; /* the length of the current field
|
|
in the logical record */
|
|
byte* dtuple_b_ptr; /* pointer to the current byte in
|
|
logical field data */
|
|
ulint dtuple_byte; /* value of current byte to be compared
|
|
in dtuple*/
|
|
ulint rec_f_len; /* length of current field in rec */
|
|
byte* rec_b_ptr; /* pointer to the current byte in
|
|
rec field */
|
|
ulint rec_byte; /* value of current byte to be
|
|
compared in rec */
|
|
ulint cur_field; /* current field number */
|
|
ulint cur_bytes; /* number of already matched bytes
|
|
in current field */
|
|
int ret = 3333; /* return value */
|
|
|
|
ut_ad(dtuple && rec && matched_fields && matched_bytes);
|
|
ut_ad(dtuple_check_typed(dtuple));
|
|
ut_ad(rec_offs_validate(rec, NULL, offsets));
|
|
|
|
cur_field = *matched_fields;
|
|
cur_bytes = *matched_bytes;
|
|
|
|
ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
|
|
ut_ad(cur_field <= rec_offs_n_fields(offsets));
|
|
|
|
if (cur_bytes == 0 && cur_field == 0) {
|
|
ulint rec_info = rec_get_info_bits(rec,
|
|
rec_offs_comp(offsets));
|
|
ulint tup_info = dtuple_get_info_bits(dtuple);
|
|
|
|
if (rec_info & REC_INFO_MIN_REC_FLAG) {
|
|
ret = !(tup_info & REC_INFO_MIN_REC_FLAG);
|
|
goto order_resolved;
|
|
} else if (tup_info & REC_INFO_MIN_REC_FLAG) {
|
|
ret = -1;
|
|
goto order_resolved;
|
|
}
|
|
}
|
|
|
|
/* Match fields in a loop; stop if we run out of fields in dtuple
|
|
or find an externally stored field */
|
|
|
|
while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
|
|
|
|
ulint mtype;
|
|
ulint prtype;
|
|
|
|
dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
|
|
{
|
|
const dtype_t* type
|
|
= dfield_get_type(dtuple_field);
|
|
|
|
mtype = type->mtype;
|
|
prtype = type->prtype;
|
|
}
|
|
|
|
dtuple_f_len = dfield_get_len(dtuple_field);
|
|
|
|
rec_b_ptr = rec_get_nth_field(rec, offsets,
|
|
cur_field, &rec_f_len);
|
|
|
|
/* If we have matched yet 0 bytes, it may be that one or
|
|
both the fields are SQL null, or the record or dtuple may be
|
|
the predefined minimum record, or the field is externally
|
|
stored */
|
|
|
|
if (UNIV_LIKELY(cur_bytes == 0)) {
|
|
if (rec_offs_nth_extern(offsets, cur_field)) {
|
|
/* We do not compare to an externally
|
|
stored field */
|
|
|
|
ret = 0;
|
|
|
|
goto order_resolved;
|
|
}
|
|
|
|
if (dtuple_f_len == UNIV_SQL_NULL) {
|
|
if (rec_f_len == UNIV_SQL_NULL) {
|
|
|
|
goto next_field;
|
|
}
|
|
|
|
ret = -1;
|
|
goto order_resolved;
|
|
} else if (rec_f_len == UNIV_SQL_NULL) {
|
|
/* We define the SQL null to be the
|
|
smallest possible value of a field
|
|
in the alphabetical order */
|
|
|
|
ret = 1;
|
|
goto order_resolved;
|
|
}
|
|
}
|
|
|
|
if (mtype >= DATA_FLOAT
|
|
|| (mtype == DATA_BLOB
|
|
&& 0 == (prtype & DATA_BINARY_TYPE)
|
|
&& dtype_get_charset_coll(prtype)
|
|
!= DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
|
|
|
|
ret = cmp_whole_field(mtype, prtype,
|
|
dfield_get_data(dtuple_field),
|
|
(unsigned) dtuple_f_len,
|
|
rec_b_ptr, (unsigned) rec_f_len);
|
|
|
|
if (ret != 0) {
|
|
cur_bytes = 0;
|
|
|
|
goto order_resolved;
|
|
} else {
|
|
goto next_field;
|
|
}
|
|
}
|
|
|
|
/* Set the pointers at the current byte */
|
|
|
|
rec_b_ptr = rec_b_ptr + cur_bytes;
|
|
dtuple_b_ptr = (byte*)dfield_get_data(dtuple_field)
|
|
+ cur_bytes;
|
|
/* Compare then the fields */
|
|
|
|
for (;;) {
|
|
if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) {
|
|
if (dtuple_f_len <= cur_bytes) {
|
|
|
|
goto next_field;
|
|
}
|
|
|
|
rec_byte = dtype_get_pad_char(mtype, prtype);
|
|
|
|
if (rec_byte == ULINT_UNDEFINED) {
|
|
ret = 1;
|
|
|
|
goto order_resolved;
|
|
}
|
|
} else {
|
|
rec_byte = *rec_b_ptr;
|
|
}
|
|
|
|
if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) {
|
|
dtuple_byte = dtype_get_pad_char(mtype,
|
|
prtype);
|
|
|
|
if (dtuple_byte == ULINT_UNDEFINED) {
|
|
ret = -1;
|
|
|
|
goto order_resolved;
|
|
}
|
|
} else {
|
|
dtuple_byte = *dtuple_b_ptr;
|
|
}
|
|
|
|
if (dtuple_byte == rec_byte) {
|
|
/* If the bytes are equal, they will
|
|
remain such even after the collation
|
|
transformation below */
|
|
|
|
goto next_byte;
|
|
}
|
|
|
|
if (mtype <= DATA_CHAR
|
|
|| (mtype == DATA_BLOB
|
|
&& !(prtype & DATA_BINARY_TYPE))) {
|
|
|
|
rec_byte = cmp_collate(rec_byte);
|
|
dtuple_byte = cmp_collate(dtuple_byte);
|
|
}
|
|
|
|
ret = (int) (dtuple_byte - rec_byte);
|
|
if (UNIV_UNLIKELY(ret)) {
|
|
if (ret < 0) {
|
|
ret = -1;
|
|
goto order_resolved;
|
|
} else {
|
|
ret = 1;
|
|
goto order_resolved;
|
|
}
|
|
}
|
|
next_byte:
|
|
/* Next byte */
|
|
cur_bytes++;
|
|
rec_b_ptr++;
|
|
dtuple_b_ptr++;
|
|
}
|
|
|
|
next_field:
|
|
cur_field++;
|
|
cur_bytes = 0;
|
|
}
|
|
|
|
ut_ad(cur_bytes == 0);
|
|
|
|
ret = 0; /* If we ran out of fields, dtuple was equal to rec
|
|
up to the common fields */
|
|
order_resolved:
|
|
ut_ad((ret >= - 1) && (ret <= 1));
|
|
ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets,
|
|
matched_fields));
|
|
ut_ad(*matched_fields == cur_field); /* In the debug version, the
|
|
above cmp_debug_... sets
|
|
*matched_fields to a value */
|
|
*matched_fields = cur_field;
|
|
*matched_bytes = cur_bytes;
|
|
|
|
return(ret);
|
|
#else /* !UNIV_HOTBACKUP */
|
|
/* This function depends on MySQL code that is not included in
|
|
InnoDB Hot Backup builds. Besides, this function should never
|
|
be called in InnoDB Hot Backup. */
|
|
ut_error;
|
|
return(0);
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
}
|
|
|
|
/******************************************************************
|
|
Compares a data tuple to a physical record. */
|
|
|
|
int
|
|
cmp_dtuple_rec(
|
|
/*===========*/
|
|
/* out: 1, 0, -1, if dtuple is greater, equal,
|
|
less than rec, respectively; see the comments
|
|
for cmp_dtuple_rec_with_match */
|
|
dtuple_t* dtuple, /* in: data tuple */
|
|
rec_t* rec, /* in: physical record */
|
|
const ulint* offsets)/* in: array returned by rec_get_offsets() */
|
|
{
|
|
ulint matched_fields = 0;
|
|
ulint matched_bytes = 0;
|
|
|
|
ut_ad(rec_offs_validate(rec, NULL, offsets));
|
|
return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
|
|
&matched_fields, &matched_bytes));
|
|
}
|
|
|
|
/******************************************************************
|
|
Checks if a dtuple is a prefix of a record. The last field in dtuple
|
|
is allowed to be a prefix of the corresponding field in the record. */
|
|
|
|
ibool
|
|
cmp_dtuple_is_prefix_of_rec(
|
|
/*========================*/
|
|
/* out: TRUE if prefix */
|
|
dtuple_t* dtuple, /* in: data tuple */
|
|
rec_t* rec, /* in: physical record */
|
|
const ulint* offsets)/* in: array returned by rec_get_offsets() */
|
|
{
|
|
ulint n_fields;
|
|
ulint matched_fields = 0;
|
|
ulint matched_bytes = 0;
|
|
|
|
ut_ad(rec_offs_validate(rec, NULL, offsets));
|
|
n_fields = dtuple_get_n_fields(dtuple);
|
|
|
|
if (n_fields > rec_offs_n_fields(offsets)) {
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
cmp_dtuple_rec_with_match(dtuple, rec, offsets,
|
|
&matched_fields, &matched_bytes);
|
|
if (matched_fields == n_fields) {
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
if (matched_fields == n_fields - 1
|
|
&& matched_bytes == dfield_get_len(
|
|
dtuple_get_nth_field(dtuple, n_fields - 1))) {
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
/*****************************************************************
|
|
This function is used to compare two physical records. Only the common
|
|
first fields are compared, and if an externally stored field is
|
|
encountered, then 0 is returned. */
|
|
|
|
int
|
|
cmp_rec_rec_with_match(
|
|
/*===================*/
|
|
/* out: 1, 0 , -1 if rec1 is greater, equal,
|
|
less, respectively, than rec2; only the common
|
|
first fields are compared */
|
|
rec_t* rec1, /* in: physical record */
|
|
rec_t* rec2, /* in: physical record */
|
|
const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
|
|
const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
|
|
dict_index_t* index, /* in: data dictionary index */
|
|
ulint* matched_fields, /* in/out: number of already completely
|
|
matched fields; when the function returns,
|
|
contains the value the for current
|
|
comparison */
|
|
ulint* matched_bytes) /* in/out: number of already matched
|
|
bytes within the first field not completely
|
|
matched; when the function returns, contains
|
|
the value for the current comparison */
|
|
{
|
|
#ifndef UNIV_HOTBACKUP
|
|
ulint rec1_n_fields; /* the number of fields in rec */
|
|
ulint rec1_f_len; /* length of current field in rec */
|
|
byte* rec1_b_ptr; /* pointer to the current byte in rec field */
|
|
ulint rec1_byte; /* value of current byte to be compared in
|
|
rec */
|
|
ulint rec2_n_fields; /* the number of fields in rec */
|
|
ulint rec2_f_len; /* length of current field in rec */
|
|
byte* rec2_b_ptr; /* pointer to the current byte in rec field */
|
|
ulint rec2_byte; /* value of current byte to be compared in
|
|
rec */
|
|
ulint cur_field; /* current field number */
|
|
ulint cur_bytes; /* number of already matched bytes in current
|
|
field */
|
|
int ret = 3333; /* return value */
|
|
ulint comp;
|
|
|
|
ut_ad(rec1 && rec2 && index);
|
|
ut_ad(rec_offs_validate(rec1, index, offsets1));
|
|
ut_ad(rec_offs_validate(rec2, index, offsets2));
|
|
ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
|
|
|
|
comp = rec_offs_comp(offsets1);
|
|
rec1_n_fields = rec_offs_n_fields(offsets1);
|
|
rec2_n_fields = rec_offs_n_fields(offsets2);
|
|
|
|
cur_field = *matched_fields;
|
|
cur_bytes = *matched_bytes;
|
|
|
|
/* Match fields in a loop */
|
|
|
|
while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) {
|
|
|
|
ulint mtype;
|
|
ulint prtype;
|
|
|
|
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
|
|
/* This is for the insert buffer B-tree. */
|
|
mtype = DATA_BINARY;
|
|
prtype = 0;
|
|
} else {
|
|
const dict_col_t* col
|
|
= dict_index_get_nth_col(index, cur_field);
|
|
|
|
mtype = col->mtype;
|
|
prtype = col->prtype;
|
|
}
|
|
|
|
rec1_b_ptr = rec_get_nth_field(rec1, offsets1,
|
|
cur_field, &rec1_f_len);
|
|
rec2_b_ptr = rec_get_nth_field(rec2, offsets2,
|
|
cur_field, &rec2_f_len);
|
|
|
|
if (cur_bytes == 0) {
|
|
if (cur_field == 0) {
|
|
/* Test if rec is the predefined minimum
|
|
record */
|
|
if (rec_get_info_bits(rec1, comp)
|
|
& REC_INFO_MIN_REC_FLAG) {
|
|
|
|
if (rec_get_info_bits(rec2, comp)
|
|
& REC_INFO_MIN_REC_FLAG) {
|
|
ret = 0;
|
|
} else {
|
|
ret = -1;
|
|
}
|
|
|
|
goto order_resolved;
|
|
|
|
} else if (rec_get_info_bits(rec2, comp)
|
|
& REC_INFO_MIN_REC_FLAG) {
|
|
|
|
ret = 1;
|
|
|
|
goto order_resolved;
|
|
}
|
|
}
|
|
|
|
if (rec_offs_nth_extern(offsets1, cur_field)
|
|
|| rec_offs_nth_extern(offsets2, cur_field)) {
|
|
/* We do not compare to an externally
|
|
stored field */
|
|
|
|
ret = 0;
|
|
|
|
goto order_resolved;
|
|
}
|
|
|
|
if (rec1_f_len == UNIV_SQL_NULL
|
|
|| rec2_f_len == UNIV_SQL_NULL) {
|
|
|
|
if (rec1_f_len == rec2_f_len) {
|
|
|
|
goto next_field;
|
|
|
|
} else if (rec2_f_len == UNIV_SQL_NULL) {
|
|
|
|
/* We define the SQL null to be the
|
|
smallest possible value of a field
|
|
in the alphabetical order */
|
|
|
|
ret = 1;
|
|
} else {
|
|
ret = -1;
|
|
}
|
|
|
|
goto order_resolved;
|
|
}
|
|
}
|
|
|
|
if (mtype >= DATA_FLOAT
|
|
|| (mtype == DATA_BLOB
|
|
&& 0 == (prtype & DATA_BINARY_TYPE)
|
|
&& dtype_get_charset_coll(prtype)
|
|
!= DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
|
|
|
|
ret = cmp_whole_field(mtype, prtype,
|
|
rec1_b_ptr,
|
|
(unsigned) rec1_f_len,
|
|
rec2_b_ptr,
|
|
(unsigned) rec2_f_len);
|
|
if (ret != 0) {
|
|
cur_bytes = 0;
|
|
|
|
goto order_resolved;
|
|
} else {
|
|
goto next_field;
|
|
}
|
|
}
|
|
|
|
/* Set the pointers at the current byte */
|
|
rec1_b_ptr = rec1_b_ptr + cur_bytes;
|
|
rec2_b_ptr = rec2_b_ptr + cur_bytes;
|
|
|
|
/* Compare then the fields */
|
|
for (;;) {
|
|
if (rec2_f_len <= cur_bytes) {
|
|
|
|
if (rec1_f_len <= cur_bytes) {
|
|
|
|
goto next_field;
|
|
}
|
|
|
|
rec2_byte = dtype_get_pad_char(mtype, prtype);
|
|
|
|
if (rec2_byte == ULINT_UNDEFINED) {
|
|
ret = 1;
|
|
|
|
goto order_resolved;
|
|
}
|
|
} else {
|
|
rec2_byte = *rec2_b_ptr;
|
|
}
|
|
|
|
if (rec1_f_len <= cur_bytes) {
|
|
rec1_byte = dtype_get_pad_char(mtype, prtype);
|
|
|
|
if (rec1_byte == ULINT_UNDEFINED) {
|
|
ret = -1;
|
|
|
|
goto order_resolved;
|
|
}
|
|
} else {
|
|
rec1_byte = *rec1_b_ptr;
|
|
}
|
|
|
|
if (rec1_byte == rec2_byte) {
|
|
/* If the bytes are equal, they will remain
|
|
such even after the collation transformation
|
|
below */
|
|
|
|
goto next_byte;
|
|
}
|
|
|
|
if (mtype <= DATA_CHAR
|
|
|| (mtype == DATA_BLOB
|
|
&& !(prtype & DATA_BINARY_TYPE))) {
|
|
|
|
rec1_byte = cmp_collate(rec1_byte);
|
|
rec2_byte = cmp_collate(rec2_byte);
|
|
}
|
|
|
|
if (rec1_byte < rec2_byte) {
|
|
ret = -1;
|
|
goto order_resolved;
|
|
} else if (rec1_byte > rec2_byte) {
|
|
ret = 1;
|
|
goto order_resolved;
|
|
}
|
|
next_byte:
|
|
/* Next byte */
|
|
|
|
cur_bytes++;
|
|
rec1_b_ptr++;
|
|
rec2_b_ptr++;
|
|
}
|
|
|
|
next_field:
|
|
cur_field++;
|
|
cur_bytes = 0;
|
|
}
|
|
|
|
ut_ad(cur_bytes == 0);
|
|
|
|
ret = 0; /* If we ran out of fields, rec1 was equal to rec2 up
|
|
to the common fields */
|
|
order_resolved:
|
|
|
|
ut_ad((ret >= - 1) && (ret <= 1));
|
|
|
|
*matched_fields = cur_field;
|
|
*matched_bytes = cur_bytes;
|
|
|
|
return(ret);
|
|
#else /* !UNIV_HOTBACKUP */
|
|
/* This function depends on MySQL code that is not included in
|
|
InnoDB Hot Backup builds. Besides, this function should never
|
|
be called in InnoDB Hot Backup. */
|
|
ut_error;
|
|
return(0);
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
}
|
|
|
|
#ifdef UNIV_DEBUG
|
|
/*****************************************************************
|
|
Used in debug checking of cmp_dtuple_... .
|
|
This function is used to compare a data tuple to a physical record. If
|
|
dtuple has n fields then rec must have either m >= n fields, or it must
|
|
differ from dtuple in some of the m fields rec has. If encounters an
|
|
externally stored field, returns 0. */
|
|
static
|
|
int
|
|
cmp_debug_dtuple_rec_with_match(
|
|
/*============================*/
|
|
/* out: 1, 0, -1, if dtuple is greater, equal,
|
|
less than rec, respectively, when only the
|
|
common first fields are compared */
|
|
dtuple_t* dtuple, /* in: data tuple */
|
|
rec_t* rec, /* in: physical record which differs from
|
|
dtuple in some of the common fields, or which
|
|
has an equal number or more fields than
|
|
dtuple */
|
|
const ulint* offsets,/* in: array returned by rec_get_offsets() */
|
|
ulint* matched_fields) /* in/out: number of already
|
|
completely matched fields; when function
|
|
returns, contains the value for current
|
|
comparison */
|
|
{
|
|
dfield_t* dtuple_field; /* current field in logical record */
|
|
ulint dtuple_f_len; /* the length of the current field
|
|
in the logical record */
|
|
byte* dtuple_f_data; /* pointer to the current logical
|
|
field data */
|
|
ulint rec_f_len; /* length of current field in rec */
|
|
byte* rec_f_data; /* pointer to the current rec field */
|
|
int ret = 3333; /* return value */
|
|
ulint cur_field; /* current field number */
|
|
|
|
ut_ad(dtuple && rec && matched_fields);
|
|
ut_ad(dtuple_check_typed(dtuple));
|
|
ut_ad(rec_offs_validate(rec, NULL, offsets));
|
|
|
|
ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
|
|
ut_ad(*matched_fields <= rec_offs_n_fields(offsets));
|
|
|
|
cur_field = *matched_fields;
|
|
|
|
if (cur_field == 0) {
|
|
if (rec_get_info_bits(rec, rec_offs_comp(offsets))
|
|
& REC_INFO_MIN_REC_FLAG) {
|
|
|
|
ret = !(dtuple_get_info_bits(dtuple)
|
|
& REC_INFO_MIN_REC_FLAG);
|
|
|
|
goto order_resolved;
|
|
}
|
|
|
|
if (dtuple_get_info_bits(dtuple) & REC_INFO_MIN_REC_FLAG) {
|
|
ret = -1;
|
|
|
|
goto order_resolved;
|
|
}
|
|
}
|
|
|
|
/* Match fields in a loop; stop if we run out of fields in dtuple */
|
|
|
|
while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
|
|
|
|
ulint mtype;
|
|
ulint prtype;
|
|
|
|
dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
|
|
{
|
|
const dtype_t* type
|
|
= dfield_get_type(dtuple_field);
|
|
|
|
mtype = type->mtype;
|
|
prtype = type->prtype;
|
|
}
|
|
|
|
dtuple_f_data = dfield_get_data(dtuple_field);
|
|
dtuple_f_len = dfield_get_len(dtuple_field);
|
|
|
|
rec_f_data = rec_get_nth_field(rec, offsets,
|
|
cur_field, &rec_f_len);
|
|
|
|
if (rec_offs_nth_extern(offsets, cur_field)) {
|
|
/* We do not compare to an externally stored field */
|
|
|
|
ret = 0;
|
|
|
|
goto order_resolved;
|
|
}
|
|
|
|
ret = cmp_data_data(mtype, prtype, dtuple_f_data, dtuple_f_len,
|
|
rec_f_data, rec_f_len);
|
|
if (ret != 0) {
|
|
goto order_resolved;
|
|
}
|
|
|
|
cur_field++;
|
|
}
|
|
|
|
ret = 0; /* If we ran out of fields, dtuple was equal to rec
|
|
up to the common fields */
|
|
order_resolved:
|
|
ut_ad((ret >= - 1) && (ret <= 1));
|
|
|
|
*matched_fields = cur_field;
|
|
|
|
return(ret);
|
|
}
|
|
#endif /* UNIV_DEBUG */
|