mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 21:12:26 +01:00
8079d0d635
------------------------------------------------------------ revno: 3459 revision-id: marko.makela@oracle.com-20100511105308-grp2t3prh3tqivw0 parent: marko.makela@oracle.com-20100511105012-b2t7wvz6mu6bll74 parent: marko.makela@oracle.com-20100505123901-xjxu93h1xnbkfkq0 committer: Marko Mäkelä <marko.makela@oracle.com> branch nick: mysql-5.1-innodb timestamp: Tue 2010-05-11 13:53:08 +0300 message: Merge a patch from Facebook to fix Bug #53290 commit e759bc64eb5c5eed4f75677ad67246797d486460 Author: Ryan Mack Date: 3 days ago Bugfix for 53290, fast unique index creation fails on duplicate null values Summary: Bug in the fast index creation code incorrectly considers null values to be duplicates during block merging. Innodb policy is that multiple null values are allowed in a unique index. Null duplicates were correctly ignored while sorting individual blocks and with slow index creation. Test Plan: mtr, including new test, load dbs using deferred index creation License: Copyright (C) 2009-2010 Facebook, Inc. All Rights Reserved. Dual licensed under BSD license and GPLv2. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY FACEBOOK, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FACEBOOK, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------ revno: 3453.2.1 revision-id: marko.makela@oracle.com-20100505123901-xjxu93h1xnbkfkq0 parent: marko.makela@oracle.com-20100505120555-ukoq1gklpheslrxs committer: Marko Mäkelä <marko.makela@oracle.com> branch nick: 5.1-innodb timestamp: Wed 2010-05-05 15:39:01 +0300 message: Merge a contribution from Ryan Mack at Facebook: Bugfix for 53290, fast unique index creation fails on duplicate null values Summary: Bug in the fast index creation code incorrectly considers null values to be duplicates during block merging. Innodb policy is that multiple null values are allowed in a unique index. Null duplicates were correctly ignored while sorting individual blocks and with slow index creation. Test Plan: mtr, including new test, load dbs using deferred index creation DiffCamp Revision: 110840 Reviewed By: mcallaghan CC: mcallaghan, mysql-devel@lists Revert Plan: OK
196 lines
7.8 KiB
C
196 lines
7.8 KiB
C
/*****************************************************************************
|
|
|
|
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free Software
|
|
Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/*******************************************************************//**
|
|
@file include/rem0cmp.h
|
|
Comparison services for records
|
|
|
|
Created 7/1/1994 Heikki Tuuri
|
|
************************************************************************/
|
|
|
|
#ifndef rem0cmp_h
|
|
#define rem0cmp_h
|
|
|
|
#include "univ.i"
|
|
#include "data0data.h"
|
|
#include "data0type.h"
|
|
#include "dict0dict.h"
|
|
#include "rem0rec.h"
|
|
|
|
/*************************************************************//**
|
|
Returns TRUE if two columns are equal for comparison purposes.
|
|
@return TRUE if the columns are considered equal in comparisons */
|
|
UNIV_INTERN
|
|
ibool
|
|
cmp_cols_are_equal(
|
|
/*===============*/
|
|
const dict_col_t* col1, /*!< in: column 1 */
|
|
const dict_col_t* col2, /*!< in: column 2 */
|
|
ibool check_charsets);
|
|
/*!< in: whether to check charsets */
|
|
/*************************************************************//**
|
|
This function is used to compare two data fields for which we know the
|
|
data type.
|
|
@return 1, 0, -1, if data1 is greater, equal, less than data2, respectively */
|
|
UNIV_INLINE
|
|
int
|
|
cmp_data_data(
|
|
/*==========*/
|
|
ulint mtype, /*!< in: main type */
|
|
ulint prtype, /*!< in: precise type */
|
|
const byte* data1, /*!< in: data field (== a pointer to a memory
|
|
buffer) */
|
|
ulint len1, /*!< in: data field length or UNIV_SQL_NULL */
|
|
const byte* data2, /*!< in: data field (== a pointer to a memory
|
|
buffer) */
|
|
ulint len2); /*!< in: data field length or UNIV_SQL_NULL */
|
|
/*************************************************************//**
|
|
This function is used to compare two data fields for which we know the
|
|
data type.
|
|
@return 1, 0, -1, if data1 is greater, equal, less than data2, respectively */
|
|
UNIV_INTERN
|
|
int
|
|
cmp_data_data_slow(
|
|
/*===============*/
|
|
ulint mtype, /*!< in: main type */
|
|
ulint prtype, /*!< in: precise type */
|
|
const byte* data1, /*!< in: data field (== a pointer to a memory
|
|
buffer) */
|
|
ulint len1, /*!< in: data field length or UNIV_SQL_NULL */
|
|
const byte* data2, /*!< in: data field (== a pointer to a memory
|
|
buffer) */
|
|
ulint len2); /*!< in: data field length or UNIV_SQL_NULL */
|
|
/*************************************************************//**
|
|
This function is used to compare two dfields where at least the first
|
|
has its data type field set.
|
|
@return 1, 0, -1, if dfield1 is greater, equal, less than dfield2,
|
|
respectively */
|
|
UNIV_INLINE
|
|
int
|
|
cmp_dfield_dfield(
|
|
/*==============*/
|
|
const dfield_t* dfield1,/*!< in: data field; must have type field set */
|
|
const dfield_t* dfield2);/*!< in: data field */
|
|
/*************************************************************//**
|
|
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 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.
|
|
@return 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 */
|
|
UNIV_INTERN
|
|
int
|
|
cmp_dtuple_rec_with_match(
|
|
/*======================*/
|
|
const dtuple_t* dtuple, /*!< in: data tuple */
|
|
const 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 */
|
|
/**************************************************************//**
|
|
Compares a data tuple to a physical record.
|
|
@see cmp_dtuple_rec_with_match
|
|
@return 1, 0, -1, if dtuple is greater, equal, less than rec, respectively */
|
|
UNIV_INTERN
|
|
int
|
|
cmp_dtuple_rec(
|
|
/*===========*/
|
|
const dtuple_t* dtuple, /*!< in: data tuple */
|
|
const rec_t* rec, /*!< in: physical record */
|
|
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
|
|
/**************************************************************//**
|
|
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.
|
|
@return TRUE if prefix */
|
|
UNIV_INTERN
|
|
ibool
|
|
cmp_dtuple_is_prefix_of_rec(
|
|
/*========================*/
|
|
const dtuple_t* dtuple, /*!< in: data tuple */
|
|
const rec_t* rec, /*!< in: physical record */
|
|
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
|
|
/*************************************************************//**
|
|
Compare two physical records that contain the same number of columns,
|
|
none of which are stored externally.
|
|
@return 1, 0, -1 if rec1 is greater, equal, less, respectively, than rec2 */
|
|
UNIV_INTERN
|
|
int
|
|
cmp_rec_rec_simple(
|
|
/*===============*/
|
|
const rec_t* rec1, /*!< in: physical record */
|
|
const rec_t* rec2, /*!< in: physical record */
|
|
const ulint* offsets1,/*!< in: rec_get_offsets(rec1, ...) */
|
|
const ulint* offsets2,/*!< in: rec_get_offsets(rec2, ...) */
|
|
const dict_index_t* index, /*!< in: data dictionary index */
|
|
ibool* null_eq);/*!< out: set to TRUE if
|
|
found matching null values */
|
|
/*************************************************************//**
|
|
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.
|
|
@return 1, 0, -1 if rec1 is greater, equal, less, respectively */
|
|
UNIV_INTERN
|
|
int
|
|
cmp_rec_rec_with_match(
|
|
/*===================*/
|
|
const rec_t* rec1, /*!< in: physical record */
|
|
const 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 */
|
|
/*************************************************************//**
|
|
This function is used to compare two physical records. Only the common
|
|
first fields are compared.
|
|
@return 1, 0 , -1 if rec1 is greater, equal, less, respectively, than
|
|
rec2; only the common first fields are compared */
|
|
UNIV_INLINE
|
|
int
|
|
cmp_rec_rec(
|
|
/*========*/
|
|
const rec_t* rec1, /*!< in: physical record */
|
|
const 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 */
|
|
|
|
|
|
#ifndef UNIV_NONINL
|
|
#include "rem0cmp.ic"
|
|
#endif
|
|
|
|
#endif
|