field.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:179k
- /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
- /*****************************************************************************
- ** This file implements classes defined in field.h
- *****************************************************************************/
- #ifdef USE_PRAGMA_IMPLEMENTATION
- #pragma implementation // gcc: Class implementation
- #endif
- #include "mysql_priv.h"
- #include "sql_select.h"
- #include <m_ctype.h>
- #include <errno.h>
- #ifdef HAVE_FCONVERT
- #include <floatingpoint.h>
- #endif
- // Maximum allowed exponent value for converting string to decimal
- #define MAX_EXPONENT 1024
- /*****************************************************************************
- Instansiate templates and static variables
- *****************************************************************************/
- #ifdef __GNUC__
- template class List<create_field>;
- template class List_iterator<create_field>;
- #endif
- uchar Field_null::null[1]={1};
- const char field_separator=',';
- #define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE 320
- #define BLOB_PACK_LENGTH_TO_MAX_LENGH(arg)
- ((ulong) ((LL(1) << min(arg, 4) * 8) - LL(1)))
- /*
- Rules for merging different types of fields in UNION
- NOTE: to avoid 256*256 table, gap in table types numeration is skiped
- following #defines describe that gap and how to canculate number of fields
- and index of field in thia array.
- */
- #define FIELDTYPE_TEAR_FROM (MYSQL_TYPE_NEWDATE+1)
- #define FIELDTYPE_TEAR_TO (MYSQL_TYPE_ENUM-1)
- #define FIELDTYPE_NUM (FIELDTYPE_TEAR_FROM + (255-FIELDTYPE_TEAR_TO))
- inline int field_type2index (enum_field_types field_type)
- {
- return (field_type < FIELDTYPE_TEAR_FROM ?
- field_type :
- ((int)FIELDTYPE_TEAR_FROM) + (field_type - FIELDTYPE_TEAR_TO) - 1);
- }
- static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
- {
- /* MYSQL_TYPE_DECIMAL -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_TINY -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_TINY, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_SHORT -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_SHORT,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_SHORT, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_SHORT,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_LONG -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_LONG,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_LONG, MYSQL_TYPE_LONG,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_LONG, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_LONGLONG, MYSQL_TYPE_LONG,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_LONG,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_FLOAT -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_FLOAT,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_FLOAT, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_FLOAT,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_FLOAT,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_DOUBLE -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_NULL -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_NEWDATE, MYSQL_TYPE_TIME,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_NEWDATE,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_ENUM,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_SET, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY
- },
- /* MYSQL_TYPE_TIMESTAMP -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_TIMESTAMP,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_DATETIME,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_DATETIME,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_LONGLONG -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_LONGLONG,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_LONGLONG, MYSQL_TYPE_LONGLONG,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_LONGLONG, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_LONGLONG, MYSQL_TYPE_LONG,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_LONGLONG,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_INT24 -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_INT24,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_INT24, MYSQL_TYPE_LONG,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_INT24, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_INT24,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_DATE -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_NEWDATE,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_TIME -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_TIME,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_DATETIME,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_DATETIME -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_DATETIME,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_DATETIME,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_DATETIME,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_YEAR -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_YEAR, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INT24,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_YEAR,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_NEWDATE -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_NEWDATE, MYSQL_TYPE_DATETIME,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_DATETIME, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_NEWDATE,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_ENUM -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_ENUM, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_SET -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_SET, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_TINY_BLOB -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_TINY_BLOB,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB
- },
- /* MYSQL_TYPE_MEDIUM_BLOB -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_MEDIUM_BLOB,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB
- },
- /* MYSQL_TYPE_LONG_BLOB -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_LONG_BLOB,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB
- },
- /* MYSQL_TYPE_BLOB -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_BLOB,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB
- },
- /* MYSQL_TYPE_VAR_STRING -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING
- },
- /* MYSQL_TYPE_STRING -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_STRING
- },
- /* MYSQL_TYPE_GEOMETRY -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_GEOMETRY, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_NEWDATE <14>
- MYSQL_TYPE_VAR_STRING,
- //<246> MYSQL_TYPE_ENUM
- MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VAR_STRING,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY
- }
- };
- /*
- Return type of which can carry value of both given types in UNION result
- SYNOPSIS
- Field::field_type_merge()
- a, b types for merging
- RETURN
- type of field
- */
- enum_field_types Field::field_type_merge(enum_field_types a,
- enum_field_types b)
- {
- DBUG_ASSERT(a < FIELDTYPE_TEAR_FROM || a > FIELDTYPE_TEAR_TO);
- DBUG_ASSERT(b < FIELDTYPE_TEAR_FROM || b > FIELDTYPE_TEAR_TO);
- return field_types_merge_rules[field_type2index(a)]
- [field_type2index(b)];
- }
- static Item_result field_types_result_type [FIELDTYPE_NUM]=
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- REAL_RESULT, INT_RESULT,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- INT_RESULT, INT_RESULT,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- REAL_RESULT, REAL_RESULT,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- STRING_RESULT, STRING_RESULT,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- INT_RESULT, INT_RESULT,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- STRING_RESULT, STRING_RESULT,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- STRING_RESULT, INT_RESULT,
- //MYSQL_TYPE_NEWDATE <14>
- STRING_RESULT,
- //<246> MYSQL_TYPE_ENUM
- STRING_RESULT,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- STRING_RESULT, STRING_RESULT,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- STRING_RESULT, STRING_RESULT,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- STRING_RESULT, STRING_RESULT,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- STRING_RESULT, STRING_RESULT
- };
- /*
- Detect Item_result by given field type of UNION merge result
- SYNOPSIS
- Field::result_merge_type()
- field_type given field type
- RETURN
- Item_result (type of internal MySQL expression result)
- */
- Item_result Field::result_merge_type(enum_field_types field_type)
- {
- DBUG_ASSERT(field_type < FIELDTYPE_TEAR_FROM || field_type
- > FIELDTYPE_TEAR_TO);
- return field_types_result_type[field_type2index(field_type)];
- }
- /*****************************************************************************
- Static help functions
- *****************************************************************************/
- void Field_num::prepend_zeros(String *value)
- {
- int diff;
- if ((diff= (int) (field_length - value->length())) > 0)
- {
- bmove_upp((char*) value->ptr()+field_length,value->ptr()+value->length(),
- value->length());
- bfill((char*) value->ptr(),diff,'0');
- value->length(field_length);
- (void) value->c_ptr_quick(); // Avoid warnings in purify
- }
- }
- /*
- Test if given number is a int (or a fixed format float with .000)
- SYNOPSIS
- test_if_int()
- str String to test
- end Pointer to char after last used digit
- cs Character set
- NOTES
- This is called after one has called my_strntol() or similar function.
- This is only used to give warnings in ALTER TABLE or LOAD DATA...
- TODO
- Make this multi-byte-character safe
- RETURN
- 0 ok
- 1 error
- */
- bool test_if_int(const char *str, int length, const char *int_end,
- CHARSET_INFO *cs)
- {
- if (str == int_end)
- return 0; // Empty string
- const char *end=str+length;
- if ((str= int_end) == end)
- return 1; // All digits was used
- /* Allow end .0000 */
- if (*str == '.')
- {
- for (str++ ; str != end && *str == '0'; str++) ;
- }
- /* Allow end space */
- for (str++ ; str != end ; str++)
- {
- if (!my_isspace(cs,*str))
- return 0;
- }
- return 1;
- }
- #ifdef NOT_USED
- static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
- {
- cs= system_charset_info; // QQ move test_if_real into CHARSET_INFO struct
- while (length && my_isspace(cs,*str))
- { // Allow start space
- length--; str++;
- }
- if (!length)
- return 0;
- if (*str == '+' || *str == '-')
- {
- length--; str++;
- if (!length || !(my_isdigit(cs,*str) || *str == '.'))
- return 0;
- }
- while (length && my_isdigit(cs,*str))
- {
- length--; str++;
- }
- if (!length)
- return 1;
- if (*str == '.')
- {
- length--; str++;
- while (length && my_isdigit(cs,*str))
- {
- length--; str++;
- }
- }
- if (!length)
- return 1;
- if (*str == 'E' || *str == 'e')
- {
- if (length < 3 || (str[1] != '+' && str[1] != '-') ||
- !my_isdigit(cs,str[2]))
- return 0;
- length-=3;
- str+=3;
- while (length && my_isdigit(cs,*str))
- {
- length--; str++;
- }
- }
- for (; length ; length--, str++)
- { // Allow end space
- if (!my_isspace(cs,*str))
- return 0;
- }
- return 1;
- }
- #endif
- /****************************************************************************
- ** Functions for the base classes
- ** This is an unpacked number.
- ****************************************************************************/
- Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
- uchar null_bit_arg,
- utype unireg_check_arg, const char *field_name_arg,
- struct st_table *table_arg)
- :ptr(ptr_arg),null_ptr(null_ptr_arg),
- table(table_arg),orig_table(table_arg),
- table_name(table_arg ? table_arg->table_name : 0),
- field_name(field_name_arg),
- query_id(0), key_start(0), part_of_key(0), part_of_sortkey(0),
- unireg_check(unireg_check_arg),
- field_length(length_arg),null_bit(null_bit_arg)
- {
- flags=null_ptr ? 0: NOT_NULL_FLAG;
- comment.str= (char*) "";
- comment.length=0;
- }
- uint Field::offset()
- {
- return (uint) (ptr - (char*) table->record[0]);
- }
- void Field::copy_from_tmp(int row_offset)
- {
- memcpy(ptr,ptr+row_offset,pack_length());
- if (null_ptr)
- {
- *null_ptr= (uchar) ((null_ptr[0] & (uchar) ~(uint) null_bit) |
- null_ptr[row_offset] & (uchar) null_bit);
- }
- }
- bool Field::send_binary(Protocol *protocol)
- {
- char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff),charset());
- val_str(&tmp);
- return protocol->store(tmp.ptr(), tmp.length(), tmp.charset());
- }
- void Field_num::add_zerofill_and_unsigned(String &res) const
- {
- if (unsigned_flag)
- res.append(" unsigned");
- if (zerofill)
- res.append(" zerofill");
- }
- void Field_num::make_field(Send_field *field)
- {
- /* table_cache_key is not set for temp tables */
- if (orig_table->table_cache_key)
- {
- field->db_name= orig_table->table_cache_key;
- field->org_table_name= orig_table->real_name;
- }
- else
- {
- field->db_name= field->org_table_name= "";
- }
- field->table_name= orig_table->table_name;
- field->col_name=field->org_col_name=field_name;
- field->charsetnr= charset()->number;
- field->length=field_length;
- field->type=type();
- field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
- field->decimals=dec;
- }
- void Field_str::make_field(Send_field *field)
- {
- /* table_cache_key is not set for temp tables */
- if (orig_table->table_cache_key)
- {
- field->db_name= orig_table->table_cache_key;
- field->org_table_name= orig_table->real_name;
- }
- else
- {
- field->db_name= field->org_table_name= "";
- }
- field->table_name= orig_table->table_name;
- field->col_name=field->org_col_name=field_name;
- field->charsetnr= charset()->number;
- field->length=field_length;
- field->type=type();
- field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
- field->decimals=0;
- }
- uint Field::fill_cache_field(CACHE_FIELD *copy)
- {
- uint store_length;
- copy->str=ptr;
- copy->length=pack_length();
- copy->blob_field=0;
- if (flags & BLOB_FLAG)
- {
- copy->blob_field=(Field_blob*) this;
- copy->strip=0;
- copy->length-=table->blob_ptr_size;
- return copy->length;
- }
- else if (!zero_pack() && (type() == FIELD_TYPE_STRING && copy->length > 4 ||
- type() == FIELD_TYPE_VAR_STRING))
- {
- copy->strip=1; /* Remove end space */
- store_length= 2;
- }
- else
- {
- copy->strip=0;
- store_length= 0;
- }
- return copy->length+ store_length;
- }
- bool Field::get_date(TIME *ltime,uint fuzzydate)
- {
- char buff[40];
- String tmp(buff,sizeof(buff),&my_charset_bin),*res;
- if (!(res=val_str(&tmp)) ||
- str_to_datetime_with_warn(res->ptr(), res->length(),
- ltime, fuzzydate) <= MYSQL_TIMESTAMP_ERROR)
- return 1;
- return 0;
- }
- bool Field::get_time(TIME *ltime)
- {
- char buff[40];
- String tmp(buff,sizeof(buff),&my_charset_bin),*res;
- if (!(res=val_str(&tmp)) ||
- str_to_time_with_warn(res->ptr(), res->length(), ltime))
- return 1;
- return 0;
- }
- /*
- This is called when storing a date in a string
- NOTES
- Needs to be changed if/when we want to support different time formats
- */
- void Field::store_time(TIME *ltime,timestamp_type type)
- {
- char buff[MAX_DATE_STRING_REP_LENGTH];
- uint length= (uint) my_TIME_to_str(ltime, buff);
- store(buff, length, &my_charset_bin);
- }
- bool Field::optimize_range(uint idx, uint part)
- {
- return test(table->file->index_flags(idx, part, 1) & HA_READ_RANGE);
- }
- /****************************************************************************
- Field_null, a field that always return NULL
- ****************************************************************************/
- void Field_null::sql_type(String &res) const
- {
- res.set_ascii("null", 4);
- }
- /****************************************************************************
- Functions for the Field_decimal class
- This is an number stored as a pre-space (or pre-zero) string
- ****************************************************************************/
- void
- Field_decimal::reset(void)
- {
- Field_decimal::store("0",1,&my_charset_bin);
- }
- void Field_decimal::overflow(bool negative)
- {
- uint len=field_length;
- char *to=ptr, filler= '9';
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- if (negative)
- {
- if (!unsigned_flag)
- {
- /* Put - sign as a first digit so we'll have -999..999 or 999..999 */
- *to++ = '-';
- len--;
- }
- else
- {
- filler= '0'; // Fill up with 0
- if (!zerofill)
- {
- /*
- Handle unsigned integer without zerofill, in which case
- the number should be of format ' 0' or ' 0.000'
- */
- uint whole_part=field_length- (dec ? dec+2 : 1);
- // Fill with spaces up to the first digit
- bfill(to, whole_part, ' ');
- to+= whole_part;
- len-= whole_part;
- // The main code will also handle the 0 before the decimal point
- }
- }
- }
- bfill(to, len, filler);
- if (dec)
- ptr[field_length-dec-1]='.';
- return;
- }
- int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
- {
- char buff[80];
- String tmp(buff,sizeof(buff), &my_charset_bin);
- /* Convert character set if the old one is multi byte */
- if (cs->mbmaxlen > 1)
- {
- uint dummy_errors;
- tmp.copy(from, len, cs, &my_charset_bin, &dummy_errors);
- from= tmp.ptr();
- len= tmp.length();
- }
- const char *end= from+len;
- /* The pointer where the field value starts (i.e., "where to write") */
- char *to=ptr;
- uint tmp_dec, tmp_uint;
- /*
- The sign of the number : will be 0 (means positive but sign not
- specified), '+' or '-'
- */
- char sign_char=0;
- /* The pointers where prezeros start and stop */
- const char *pre_zeros_from, *pre_zeros_end;
- /* The pointers where digits at the left of '.' start and stop */
- const char *int_digits_from, *int_digits_end;
- /* The pointers where digits at the right of '.' start and stop */
- const char *frac_digits_from, *frac_digits_end;
- /* The sign of the exponent : will be 0 (means no exponent), '+' or '-' */
- char expo_sign_char=0;
- uint exponent=0; // value of the exponent
- /*
- Pointers used when digits move from the left of the '.' to the
- right of the '.' (explained below)
- */
- const char *int_digits_tail_from;
- /* Number of 0 that need to be added at the left of the '.' (1E3: 3 zeros) */
- uint int_digits_added_zeros;
- /*
- Pointer used when digits move from the right of the '.' to the left
- of the '.'
- */
- const char *frac_digits_head_end;
- /* Number of 0 that need to be added at the right of the '.' (for 1E-3) */
- uint frac_digits_added_zeros;
- char *pos,*tmp_left_pos,*tmp_right_pos;
- /* Pointers that are used as limits (begin and end of the field buffer) */
- char *left_wall,*right_wall;
- char tmp_char;
- /*
- To remember if table->in_use->cuted_fields has already been incremented,
- to do that only once
- */
- bool is_cuted_fields_incr=0;
- LINT_INIT(int_digits_tail_from);
- LINT_INIT(int_digits_added_zeros);
- LINT_INIT(frac_digits_head_end);
- LINT_INIT(frac_digits_added_zeros);
- /*
- There are three steps in this function :
- - parse the input string
- - modify the position of digits around the decimal dot '.'
- according to the exponent value (if specified)
- - write the formatted number
- */
- if ((tmp_dec=dec))
- tmp_dec++;
- /* skip pre-space */
- while (from != end && my_isspace(&my_charset_bin,*from))
- from++;
- if (from == end)
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- is_cuted_fields_incr=1;
- }
- else if (*from == '+' || *from == '-') // Found some sign ?
- {
- sign_char= *from++;
- /*
- We allow "+" for unsigned decimal unless defined different
- Both options allowed as one may wish not to have "+" for unsigned numbers
- because of data processing issues
- */
- if (unsigned_flag)
- {
- if (sign_char=='-')
- {
- Field_decimal::overflow(1);
- return 1;
- }
- /*
- Defining this will not store "+" for unsigned decimal type even if
- it is passed in numeric string. This will make some tests to fail
- */
- #ifdef DONT_ALLOW_UNSIGNED_PLUS
- else
- sign_char=0;
- #endif
- }
- }
- pre_zeros_from= from;
- for (; from!=end && *from == '0'; from++) ; // Read prezeros
- pre_zeros_end=int_digits_from=from;
- /* Read non zero digits at the left of '.'*/
- for (; from != end && my_isdigit(&my_charset_bin, *from) ; from++) ;
- int_digits_end=from;
- if (from!=end && *from == '.') // Some '.' ?
- from++;
- frac_digits_from= from;
- /* Read digits at the right of '.' */
- for (;from!=end && my_isdigit(&my_charset_bin, *from); from++) ;
- frac_digits_end=from;
- // Some exponentiation symbol ?
- if (from != end && (*from == 'e' || *from == 'E'))
- {
- from++;
- if (from != end && (*from == '+' || *from == '-')) // Some exponent sign ?
- expo_sign_char= *from++;
- else
- expo_sign_char= '+';
- /*
- Read digits of the exponent and compute its value. We must care about
- 'exponent' overflow, because as unsigned arithmetic is "modulo", big
- exponents will become small (e.g. 1e4294967296 will become 1e0, and the
- field will finally contain 1 instead of its max possible value).
- */
- for (;from!=end && my_isdigit(&my_charset_bin, *from); from++)
- {
- exponent=10*exponent+(*from-'0');
- if (exponent>MAX_EXPONENT)
- break;
- }
- }
-
- /*
- We only have to generate warnings if count_cuted_fields is set.
- This is to avoid extra checks of the number when they are not needed.
- Even if this flag is not set, it's ok to increment warnings, if
- it makes the code easer to read.
- */
- if (table->in_use->count_cuted_fields)
- {
- // Skip end spaces
- for (;from != end && my_isspace(&my_charset_bin, *from); from++) ;
- if (from != end) // If still something left, warn
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- is_cuted_fields_incr=1;
- }
- }
-
- /*
- Now "move" digits around the decimal dot according to the exponent value,
- and add necessary zeros.
- Examples :
- - 1E+3 : needs 3 more zeros at the left of '.' (int_digits_added_zeros=3)
- - 1E-3 : '1' moves at the right of '.', and 2 more zeros are needed
- between '.' and '1'
- - 1234.5E-3 : '234' moves at the right of '.'
- These moves are implemented with pointers which point at the begin
- and end of each moved segment. Examples :
- - 1234.5E-3 : before the code below is executed, the int_digits part is
- from '1' to '4' and the frac_digits part from '5' to '5'. After the code
- below, the int_digits part is from '1' to '1', the frac_digits_head
- part is from '2' to '4', and the frac_digits part from '5' to '5'.
- - 1234.5E3 : before the code below is executed, the int_digits part is
- from '1' to '4' and the frac_digits part from '5' to '5'. After the code
- below, the int_digits part is from '1' to '4', the int_digits_tail
- part is from '5' to '5', the frac_digits part is empty, and
- int_digits_added_zeros=2 (to make 1234500).
- */
-
- /*
- Below tmp_uint cannot overflow with small enough MAX_EXPONENT setting,
- as int_digits_added_zeros<=exponent<4G and
- (int_digits_end-int_digits_from)<=max_allowed_packet<=2G and
- (frac_digits_from-int_digits_tail_from)<=max_allowed_packet<=2G
- */
- if (!expo_sign_char)
- tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
- else if (expo_sign_char == '-')
- {
- tmp_uint=min(exponent,(uint)(int_digits_end-int_digits_from));
- frac_digits_added_zeros=exponent-tmp_uint;
- int_digits_end -= tmp_uint;
- frac_digits_head_end=int_digits_end+tmp_uint;
- tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
- }
- else // (expo_sign_char=='+')
- {
- tmp_uint=min(exponent,(uint)(frac_digits_end-frac_digits_from));
- int_digits_added_zeros=exponent-tmp_uint;
- int_digits_tail_from=frac_digits_from;
- frac_digits_from=frac_digits_from+tmp_uint;
- /*
- We "eat" the heading zeros of the
- int_digits.int_digits_tail.int_digits_added_zeros concatenation
- (for example 0.003e3 must become 3 and not 0003)
- */
- if (int_digits_from == int_digits_end)
- {
- /*
- There was nothing in the int_digits part, so continue
- eating int_digits_tail zeros
- */
- for (; int_digits_tail_from != frac_digits_from &&
- *int_digits_tail_from == '0'; int_digits_tail_from++) ;
- if (int_digits_tail_from == frac_digits_from)
- {
- // there were only zeros in int_digits_tail too
- int_digits_added_zeros=0;
- }
- }
- tmp_uint= (tmp_dec+(int_digits_end-int_digits_from)+
- (uint)(frac_digits_from-int_digits_tail_from)+
- int_digits_added_zeros);
- }
-
- /*
- Now write the formated number
-
- First the digits of the int_% parts.
- Do we have enough room to write these digits ?
- If the sign is defined and '-', we need one position for it
- */
- if (field_length < tmp_uint + (int) (sign_char == '-'))
- {
- // too big number, change to max or min number
- Field_decimal::overflow(sign_char == '-');
- return 1;
- }
-
- /*
- Tmp_left_pos is the position where the leftmost digit of
- the int_% parts will be written
- */
- tmp_left_pos=pos=to+(uint)(field_length-tmp_uint);
-
- // Write all digits of the int_% parts
- while (int_digits_from != int_digits_end)
- *pos++ = *int_digits_from++ ;
- if (expo_sign_char == '+')
- {
- while (int_digits_tail_from != frac_digits_from)
- *pos++= *int_digits_tail_from++;
- while (int_digits_added_zeros-- >0)
- *pos++= '0';
- }
- /*
- Note the position where the rightmost digit of the int_% parts has been
- written (this is to later check if the int_% parts contained nothing,
- meaning an extra 0 is needed).
- */
- tmp_right_pos=pos;
- /*
- Step back to the position of the leftmost digit of the int_% parts,
- to write sign and fill with zeros or blanks or prezeros.
- */
- pos=tmp_left_pos-1;
- if (zerofill)
- {
- left_wall=to-1;
- while (pos > left_wall) // Fill with zeros
- *pos--='0';
- }
- else
- {
- left_wall=to+(sign_char != 0)-1;
- if (!expo_sign_char) // If exponent was specified, ignore prezeros
- {
- for (;pos > left_wall && pre_zeros_from !=pre_zeros_end;
- pre_zeros_from++)
- *pos--= '0';
- }
- if (pos == tmp_right_pos-1)
- *pos--= '0'; // no 0 has ever been written, so write one
- left_wall= to-1;
- if (sign_char && pos != left_wall)
- {
- /* Write sign if possible (it is if sign is '-') */
- *pos--= sign_char;
- }
- while (pos != left_wall)
- *pos--=' '; //fill with blanks
- }
-
- /*
- Write digits of the frac_% parts ;
- Depending on table->in_use->count_cutted_fields, we may also want
- to know if some non-zero tail of these parts will
- be truncated (for example, 0.002->0.00 will generate a warning,
- while 0.000->0.00 will not)
- (and 0E1000000000 will not, while 1E-1000000000 will)
- */
-
- pos=to+(uint)(field_length-tmp_dec); // Calculate post to '.'
- right_wall=to+field_length;
- if (pos != right_wall)
- *pos++='.';
- if (expo_sign_char == '-')
- {
- while (frac_digits_added_zeros-- > 0)
- {
- if (pos == right_wall)
- {
- if (table->in_use->count_cuted_fields && !is_cuted_fields_incr)
- break; // Go on below to see if we lose non zero digits
- return 0;
- }
- *pos++='0';
- }
- while (int_digits_end != frac_digits_head_end)
- {
- tmp_char= *int_digits_end++;
- if (pos == right_wall)
- {
- if (tmp_char != '0') // Losing a non zero digit ?
- {
- if (!is_cuted_fields_incr)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED, 1);
- return 0;
- }
- continue;
- }
- *pos++= tmp_char;
- }
- }
- for (;frac_digits_from!=frac_digits_end;)
- {
- tmp_char= *frac_digits_from++;
- if (pos == right_wall)
- {
- if (tmp_char != '0') // Losing a non zero digit ?
- {
- if (!is_cuted_fields_incr)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- return 0;
- }
- continue;
- }
- *pos++= tmp_char;
- }
-
- while (pos != right_wall)
- *pos++='0'; // Fill with zeros at right of '.'
- return 0;
- }
- int Field_decimal::store(double nr)
- {
- if (unsigned_flag && nr < 0)
- {
- overflow(1);
- return 1;
- }
-
- #ifdef HAVE_FINITE
- if (!finite(nr)) // Handle infinity as special case
- {
- overflow(nr < 0.0);
- return 1;
- }
- #endif
- reg4 uint i,length;
- char fyllchar,*to;
- char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
- fyllchar = zerofill ? (char) '0' : (char) ' ';
- #ifdef HAVE_SNPRINTF
- buff[sizeof(buff)-1]=0; // Safety
- snprintf(buff,sizeof(buff)-1, "%.*f",(int) dec,nr);
- length=(uint) strlen(buff);
- #else
- length=(uint) my_sprintf(buff,(buff,"%.*f",dec,nr));
- #endif
- if (length > field_length)
- {
- overflow(nr < 0.0);
- return 1;
- }
- else
- {
- to=ptr;
- for (i=field_length-length ; i-- > 0 ;)
- *to++ = fyllchar;
- memcpy(to,buff,length);
- return 0;
- }
- }
- int Field_decimal::store(longlong nr)
- {
- if (unsigned_flag && nr < 0)
- {
- overflow(1);
- return 1;
- }
- char buff[22];
- uint length=(uint) (longlong10_to_str(nr,buff,-10)-buff);
- uint int_part=field_length- (dec ? dec+1 : 0);
- if (length > int_part)
- {
- overflow(test(nr < 0L)); /* purecov: inspected */
- return 1;
- }
- else
- {
- char fyllchar = zerofill ? (char) '0' : (char) ' ';
- char *to=ptr;
- for (uint i=int_part-length ; i-- > 0 ;)
- *to++ = fyllchar;
- memcpy(to,buff,length);
- if (dec)
- {
- to[length]='.';
- bfill(to+length+1,dec,'0');
- }
- return 0;
- }
- }
- double Field_decimal::val_real(void)
- {
- int not_used;
- char *end_not_used;
- return my_strntod(&my_charset_bin, ptr, field_length, &end_not_used,
- ¬_used);
- }
- longlong Field_decimal::val_int(void)
- {
- int not_used;
- if (unsigned_flag)
- return my_strntoull(&my_charset_bin, ptr, field_length, 10, NULL,
- ¬_used);
- else
- return my_strntoll(&my_charset_bin, ptr, field_length, 10, NULL,
- ¬_used);
- }
- String *Field_decimal::val_str(String *val_buffer __attribute__((unused)),
- String *val_ptr)
- {
- char *str;
- for (str=ptr ; *str == ' ' ; str++) ;
- uint tmp_length=(uint) (str-ptr);
- val_ptr->set_charset(&my_charset_bin);
- if (field_length < tmp_length) // Error in data
- val_ptr->length(0);
- else
- val_ptr->set_ascii((const char*) str, field_length-tmp_length);
- return val_ptr;
- }
- /*
- ** Should be able to handle at least the following fixed decimal formats:
- ** 5.00 , -1.0, 05, -05, +5 with optional pre/end space
- */
- int Field_decimal::cmp(const char *a_ptr,const char *b_ptr)
- {
- const char *end;
- int swap=0;
- /* First remove prefixes '0', ' ', and '-' */
- for (end=a_ptr+field_length;
- a_ptr != end &&
- (*a_ptr == *b_ptr ||
- ((my_isspace(&my_charset_bin,*a_ptr) || *a_ptr == '+' ||
- *a_ptr == '0') &&
- (my_isspace(&my_charset_bin,*b_ptr) || *b_ptr == '+' ||
- *b_ptr == '0')));
- a_ptr++,b_ptr++)
- {
- if (*a_ptr == '-') // If both numbers are negative
- swap= -1 ^ 1; // Swap result
- }
- if (a_ptr == end)
- return 0;
- if (*a_ptr == '-')
- return -1;
- if (*b_ptr == '-')
- return 1;
- while (a_ptr != end)
- {
- if (*a_ptr++ != *b_ptr++)
- return swap ^ (a_ptr[-1] < b_ptr[-1] ? -1 : 1); // compare digits
- }
- return 0;
- }
- void Field_decimal::sort_string(char *to,uint length)
- {
- char *str,*end;
- for (str=ptr,end=ptr+length;
- str != end &&
- ((my_isspace(&my_charset_bin,*str) || *str == '+' ||
- *str == '0')) ;
- str++)
- *to++=' ';
- if (str == end)
- return; /* purecov: inspected */
- if (*str == '-')
- {
- *to++=1; // Smaller than any number
- str++;
- while (str != end)
- if (my_isdigit(&my_charset_bin,*str))
- *to++= (char) ('9' - *str++);
- else
- *to++= *str++;
- }
- else memcpy(to,str,(uint) (end-str));
- }
- void Field_decimal::sql_type(String &res) const
- {
- CHARSET_INFO *cs=res.charset();
- uint tmp=field_length;
- if (!unsigned_flag)
- tmp--;
- if (dec)
- tmp--;
- res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
- "decimal(%d,%d)",tmp,dec));
- add_zerofill_and_unsigned(res);
- }
- /****************************************************************************
- ** tiny int
- ****************************************************************************/
- int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
- {
- int not_used; // We can ignore result from str2int
- char *end;
- long tmp= my_strntol(cs, from, len, 10, &end, ¬_used);
- int error= 0;
- if (unsigned_flag)
- {
- if (tmp < 0)
- {
- tmp=0; /* purecov: inspected */
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (tmp > 255)
- {
- tmp= 255;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- error= 1;
- }
- }
- else
- {
- if (tmp < -128)
- {
- tmp= -128;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (tmp >= 128)
- {
- tmp= 127;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- error= 1;
- }
- }
- ptr[0]= (char) tmp;
- return error;
- }
- int Field_tiny::store(double nr)
- {
- int error= 0;
- nr=rint(nr);
- if (unsigned_flag)
- {
- if (nr < 0.0)
- {
- *ptr=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > 255.0)
- {
- *ptr=(char) 255;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- *ptr=(char) nr;
- }
- else
- {
- if (nr < -128.0)
- {
- *ptr= (char) -128;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > 127.0)
- {
- *ptr=127;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- *ptr=(char) nr;
- }
- return error;
- }
- int Field_tiny::store(longlong nr)
- {
- int error= 0;
- if (unsigned_flag)
- {
- if (nr < 0L)
- {
- *ptr=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > 255L)
- {
- *ptr= (char) 255;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- *ptr=(char) nr;
- }
- else
- {
- if (nr < -128L)
- {
- *ptr= (char) -128;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > 127L)
- {
- *ptr=127;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- *ptr=(char) nr;
- }
- return error;
- }
- double Field_tiny::val_real(void)
- {
- int tmp= unsigned_flag ? (int) ((uchar*) ptr)[0] :
- (int) ((signed char*) ptr)[0];
- return (double) tmp;
- }
- longlong Field_tiny::val_int(void)
- {
- int tmp= unsigned_flag ? (int) ((uchar*) ptr)[0] :
- (int) ((signed char*) ptr)[0];
- return (longlong) tmp;
- }
- String *Field_tiny::val_str(String *val_buffer,
- String *val_ptr __attribute__((unused)))
- {
- CHARSET_INFO *cs= &my_charset_bin;
- uint length;
- uint mlength=max(field_length+1,5*cs->mbmaxlen);
- val_buffer->alloc(mlength);
- char *to=(char*) val_buffer->ptr();
- if (unsigned_flag)
- length= (uint) cs->cset->long10_to_str(cs,to,mlength, 10,
- (long) *((uchar*) ptr));
- else
- length= (uint) cs->cset->long10_to_str(cs,to,mlength,-10,
- (long) *((signed char*) ptr));
-
- val_buffer->length(length);
- if (zerofill)
- prepend_zeros(val_buffer);
- return val_buffer;
- }
- bool Field_tiny::send_binary(Protocol *protocol)
- {
- return protocol->store_tiny((longlong) (int8) ptr[0]);
- }
- int Field_tiny::cmp(const char *a_ptr, const char *b_ptr)
- {
- signed char a,b;
- a=(signed char) a_ptr[0]; b= (signed char) b_ptr[0];
- if (unsigned_flag)
- return ((uchar) a < (uchar) b) ? -1 : ((uchar) a > (uchar) b) ? 1 : 0;
- return (a < b) ? -1 : (a > b) ? 1 : 0;
- }
- void Field_tiny::sort_string(char *to,uint length __attribute__((unused)))
- {
- if (unsigned_flag)
- *to= *ptr;
- else
- to[0] = (char) ((uchar) ptr[0] ^ (uchar) 128); /* Revers signbit */
- }
- void Field_tiny::sql_type(String &res) const
- {
- CHARSET_INFO *cs=res.charset();
- res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
- "tinyint(%d)",(int) field_length));
- add_zerofill_and_unsigned(res);
- }
- /****************************************************************************
- Field type short int (2 byte)
- ****************************************************************************/
- int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
- {
- int not_used; // We can ignore result from str2int
- char *end;
- long tmp= my_strntol(cs, from, len, 10, &end, ¬_used);
- int error= 0;
- if (unsigned_flag)
- {
- if (tmp < 0)
- {
- tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (tmp > (uint16) ~0)
- {
- tmp=(uint16) ~0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- error= 1;
- }
- }
- else
- {
- if (tmp < INT_MIN16)
- {
- tmp= INT_MIN16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (tmp > INT_MAX16)
- {
- tmp=INT_MAX16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- error= 1;
- }
- }
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int2store(ptr,tmp);
- }
- else
- #endif
- shortstore(ptr,(short) tmp);
- return error;
- }
- int Field_short::store(double nr)
- {
- int error= 0;
- int16 res;
- nr=rint(nr);
- if (unsigned_flag)
- {
- if (nr < 0)
- {
- res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > (double) (uint16) ~0)
- {
- res=(int16) (uint16) ~0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- res=(int16) (uint16) nr;
- }
- else
- {
- if (nr < (double) INT_MIN16)
- {
- res=INT_MIN16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > (double) INT_MAX16)
- {
- res=INT_MAX16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- res=(int16) nr;
- }
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int2store(ptr,res);
- }
- else
- #endif
- shortstore(ptr,res);
- return error;
- }
- int Field_short::store(longlong nr)
- {
- int error= 0;
- int16 res;
- if (unsigned_flag)
- {
- if (nr < 0L)
- {
- res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > (longlong) (uint16) ~0)
- {
- res=(int16) (uint16) ~0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- res=(int16) (uint16) nr;
- }
- else
- {
- if (nr < INT_MIN16)
- {
- res=INT_MIN16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > INT_MAX16)
- {
- res=INT_MAX16;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- res=(int16) nr;
- }
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int2store(ptr,res);
- }
- else
- #endif
- shortstore(ptr,res);
- return error;
- }
- double Field_short::val_real(void)
- {
- short j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- j=sint2korr(ptr);
- else
- #endif
- shortget(j,ptr);
- return unsigned_flag ? (double) (unsigned short) j : (double) j;
- }
- longlong Field_short::val_int(void)
- {
- short j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- j=sint2korr(ptr);
- else
- #endif
- shortget(j,ptr);
- return unsigned_flag ? (longlong) (unsigned short) j : (longlong) j;
- }
- String *Field_short::val_str(String *val_buffer,
- String *val_ptr __attribute__((unused)))
- {
- CHARSET_INFO *cs= &my_charset_bin;
- uint length;
- uint mlength=max(field_length+1,7*cs->mbmaxlen);
- val_buffer->alloc(mlength);
- char *to=(char*) val_buffer->ptr();
- short j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- j=sint2korr(ptr);
- else
- #endif
- shortget(j,ptr);
- if (unsigned_flag)
- length=(uint) cs->cset->long10_to_str(cs, to, mlength, 10,
- (long) (uint16) j);
- else
- length=(uint) cs->cset->long10_to_str(cs, to, mlength,-10, (long) j);
- val_buffer->length(length);
- if (zerofill)
- prepend_zeros(val_buffer);
- return val_buffer;
- }
- bool Field_short::send_binary(Protocol *protocol)
- {
- return protocol->store_short(Field_short::val_int());
- }
- int Field_short::cmp(const char *a_ptr, const char *b_ptr)
- {
- short a,b;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- a=sint2korr(a_ptr);
- b=sint2korr(b_ptr);
- }
- else
- #endif
- {
- shortget(a,a_ptr);
- shortget(b,b_ptr);
- }
- if (unsigned_flag)
- return ((unsigned short) a < (unsigned short) b) ? -1 :
- ((unsigned short) a > (unsigned short) b) ? 1 : 0;
- return (a < b) ? -1 : (a > b) ? 1 : 0;
- }
- void Field_short::sort_string(char *to,uint length __attribute__((unused)))
- {
- #ifdef WORDS_BIGENDIAN
- if (!table->db_low_byte_first)
- {
- if (unsigned_flag)
- to[0] = ptr[0];
- else
- to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
- to[1] = ptr[1];
- }
- else
- #endif
- {
- if (unsigned_flag)
- to[0] = ptr[1];
- else
- to[0] = (char) (ptr[1] ^ 128); /* Revers signbit */
- to[1] = ptr[0];
- }
- }
- void Field_short::sql_type(String &res) const
- {
- CHARSET_INFO *cs=res.charset();
- res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
- "smallint(%d)",(int) field_length));
- add_zerofill_and_unsigned(res);
- }
- /****************************************************************************
- Field type medium int (3 byte)
- ****************************************************************************/
- int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
- {
- int not_used; // We can ignore result from str2int
- char *end;
- long tmp= my_strntol(cs, from, len, 10, &end, ¬_used);
- int error= 0;
- if (unsigned_flag)
- {
- if (tmp < 0)
- {
- tmp=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (tmp >= (long) (1L << 24))
- {
- tmp=(long) (1L << 24)-1L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- error= 1;
- }
- }
- else
- {
- if (tmp < INT_MIN24)
- {
- tmp= INT_MIN24;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (tmp > INT_MAX24)
- {
- tmp=INT_MAX24;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- error= 1;
- }
- }
- int3store(ptr,tmp);
- return error;
- }
- int Field_medium::store(double nr)
- {
- int error= 0;
- nr=rint(nr);
- if (unsigned_flag)
- {
- if (nr < 0)
- {
- int3store(ptr,0);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr >= (double) (long) (1L << 24))
- {
- uint32 tmp=(uint32) (1L << 24)-1L;
- int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- int3store(ptr,(uint32) nr);
- }
- else
- {
- if (nr < (double) INT_MIN24)
- {
- long tmp=(long) INT_MIN24;
- int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > (double) INT_MAX24)
- {
- long tmp=(long) INT_MAX24;
- int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- int3store(ptr,(long) nr);
- }
- return error;
- }
- int Field_medium::store(longlong nr)
- {
- int error= 0;
- if (unsigned_flag)
- {
- if (nr < 0L)
- {
- int3store(ptr,0);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr >= (longlong) (long) (1L << 24))
- {
- long tmp=(long) (1L << 24)-1L;;
- int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- int3store(ptr,(uint32) nr);
- }
- else
- {
- if (nr < (longlong) INT_MIN24)
- {
- long tmp=(long) INT_MIN24;
- int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > (longlong) INT_MAX24)
- {
- long tmp=(long) INT_MAX24;
- int3store(ptr,tmp);
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- int3store(ptr,(long) nr);
- }
- return error;
- }
- double Field_medium::val_real(void)
- {
- long j= unsigned_flag ? (long) uint3korr(ptr) : sint3korr(ptr);
- return (double) j;
- }
- longlong Field_medium::val_int(void)
- {
- long j= unsigned_flag ? (long) uint3korr(ptr) : sint3korr(ptr);
- return (longlong) j;
- }
- String *Field_medium::val_str(String *val_buffer,
- String *val_ptr __attribute__((unused)))
- {
- CHARSET_INFO *cs= &my_charset_bin;
- uint length;
- uint mlength=max(field_length+1,10*cs->mbmaxlen);
- val_buffer->alloc(mlength);
- char *to=(char*) val_buffer->ptr();
- long j= unsigned_flag ? (long) uint3korr(ptr) : sint3korr(ptr);
- length=(uint) cs->cset->long10_to_str(cs,to,mlength,-10,j);
- val_buffer->length(length);
- if (zerofill)
- prepend_zeros(val_buffer); /* purecov: inspected */
- return val_buffer;
- }
- bool Field_medium::send_binary(Protocol *protocol)
- {
- return protocol->store_long(Field_medium::val_int());
- }
- int Field_medium::cmp(const char *a_ptr, const char *b_ptr)
- {
- long a,b;
- if (unsigned_flag)
- {
- a=uint3korr(a_ptr);
- b=uint3korr(b_ptr);
- }
- else
- {
- a=sint3korr(a_ptr);
- b=sint3korr(b_ptr);
- }
- return (a < b) ? -1 : (a > b) ? 1 : 0;
- }
- void Field_medium::sort_string(char *to,uint length __attribute__((unused)))
- {
- if (unsigned_flag)
- to[0] = ptr[2];
- else
- to[0] = (uchar) (ptr[2] ^ 128); /* Revers signbit */
- to[1] = ptr[1];
- to[2] = ptr[0];
- }
- void Field_medium::sql_type(String &res) const
- {
- CHARSET_INFO *cs=res.charset();
- res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
- "mediumint(%d)",(int) field_length));
- add_zerofill_and_unsigned(res);
- }
- /****************************************************************************
- ** long int
- ****************************************************************************/
- /*
- A helper function to check whether the next character
- in the string "s" is MINUS SIGN.
- */
- #ifdef HAVE_CHARSET_ucs2
- static bool test_if_minus(CHARSET_INFO *cs,
- const char *s, const char *e)
- {
- my_wc_t wc;
- return cs->cset->mb_wc(cs, &wc, (uchar*) s, (uchar*) e) > 0 && wc == '-';
- }
- #else
- /*
- If not UCS2 support is compiled then it is easier
- */
- #define test_if_minus(cs, s, e) (*s == '-')
- #endif
- int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
- {
- long tmp;
- int error= 0;
- char *end;
-
- tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES);
- len-= tmp;
- from+= tmp;
- my_errno=0;
- if (unsigned_flag)
- {
- if (!len || test_if_minus(cs, from, from + len))
- {
- tmp=0; // Set negative to 0
- my_errno=ERANGE;
- error= 1;
- }
- else
- tmp=(long) my_strntoul(cs,from,len,10,&end,&error);
- }
- else
- tmp=my_strntol(cs,from,len,10,&end,&error);
- if (error ||
- (from+len != end && table->in_use->count_cuted_fields &&
- !test_if_int(from,len,end,cs)))
- {
- if (error != 1)
- error= 2;
- }
- #if SIZEOF_LONG > 4
- if (unsigned_flag)
- {
- if ((ulong) tmp > UINT_MAX32)
- {
- tmp= UINT_MAX32;
- error= 1;
- my_errno=ERANGE;
- }
- }
- else
- {
- if (tmp > INT_MAX32)
- {
- tmp= INT_MAX32;
- error= 1;
- my_errno=ERANGE;
- }
- else if (tmp < INT_MIN32)
- {
- tmp= INT_MIN32;
- error= 1;
- my_errno=ERANGE;
- }
- }
- #endif
- if (error)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int4store(ptr,tmp);
- }
- else
- #endif
- longstore(ptr,tmp);
- return error;
- }
- int Field_long::store(double nr)
- {
- int error= 0;
- int32 res;
- nr=rint(nr);
- if (unsigned_flag)
- {
- if (nr < 0)
- {
- res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > (double) UINT_MAX32)
- {
- res= UINT_MAX32;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- res=(int32) (ulong) nr;
- }
- else
- {
- if (nr < (double) INT_MIN32)
- {
- res=(int32) INT_MIN32;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > (double) INT_MAX32)
- {
- res=(int32) INT_MAX32;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- res=(int32) nr;
- }
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int4store(ptr,res);
- }
- else
- #endif
- longstore(ptr,res);
- return error;
- }
- int Field_long::store(longlong nr)
- {
- int error= 0;
- int32 res;
- /*
- This assert has nothing to do with this method per se, it was put here
- only because it is one of the best places for catching places there its
- condition is broken.
- */
- DBUG_ASSERT(table->in_use == current_thd);
-
- if (unsigned_flag)
- {
- if (nr < 0)
- {
- res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr >= (LL(1) << 32))
- {
- res=(int32) (uint32) ~0L;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- res=(int32) (uint32) nr;
- }
- else
- {
- if (nr < (longlong) INT_MIN32)
- {
- res=(int32) INT_MIN32;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > (longlong) INT_MAX32)
- {
- res=(int32) INT_MAX32;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- res=(int32) nr;
- }
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int4store(ptr,res);
- }
- else
- #endif
- longstore(ptr,res);
- return error;
- }
- double Field_long::val_real(void)
- {
- int32 j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- j=sint4korr(ptr);
- else
- #endif
- longget(j,ptr);
- return unsigned_flag ? (double) (uint32) j : (double) j;
- }
- longlong Field_long::val_int(void)
- {
- int32 j;
- /* See the comment in Field_long::store(long long) */
- DBUG_ASSERT(table->in_use == current_thd);
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- j=sint4korr(ptr);
- else
- #endif
- longget(j,ptr);
- return unsigned_flag ? (longlong) (uint32) j : (longlong) j;
- }
- String *Field_long::val_str(String *val_buffer,
- String *val_ptr __attribute__((unused)))
- {
- CHARSET_INFO *cs= &my_charset_bin;
- uint length;
- uint mlength=max(field_length+1,12*cs->mbmaxlen);
- val_buffer->alloc(mlength);
- char *to=(char*) val_buffer->ptr();
- int32 j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- j=sint4korr(ptr);
- else
- #endif
- longget(j,ptr);
- if (unsigned_flag)
- length=cs->cset->long10_to_str(cs,to,mlength, 10,(long) (uint32)j);
- else
- length=cs->cset->long10_to_str(cs,to,mlength,-10,(long) j);
- val_buffer->length(length);
- if (zerofill)
- prepend_zeros(val_buffer);
- return val_buffer;
- }
- bool Field_long::send_binary(Protocol *protocol)
- {
- return protocol->store_long(Field_long::val_int());
- }
- int Field_long::cmp(const char *a_ptr, const char *b_ptr)
- {
- int32 a,b;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- a=sint4korr(a_ptr);
- b=sint4korr(b_ptr);
- }
- else
- #endif
- {
- longget(a,a_ptr);
- longget(b,b_ptr);
- }
- if (unsigned_flag)
- return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 : 0;
- return (a < b) ? -1 : (a > b) ? 1 : 0;
- }
- void Field_long::sort_string(char *to,uint length __attribute__((unused)))
- {
- #ifdef WORDS_BIGENDIAN
- if (!table->db_low_byte_first)
- {
- if (unsigned_flag)
- to[0] = ptr[0];
- else
- to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
- to[1] = ptr[1];
- to[2] = ptr[2];
- to[3] = ptr[3];
- }
- else
- #endif
- {
- if (unsigned_flag)
- to[0] = ptr[3];
- else
- to[0] = (char) (ptr[3] ^ 128); /* Revers signbit */
- to[1] = ptr[2];
- to[2] = ptr[1];
- to[3] = ptr[0];
- }
- }
- void Field_long::sql_type(String &res) const
- {
- CHARSET_INFO *cs=res.charset();
- res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
- "int(%d)",(int) field_length));
- add_zerofill_and_unsigned(res);
- }
- /****************************************************************************
- Field type longlong int (8 bytes)
- ****************************************************************************/
- int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
- {
- longlong tmp;
- int error= 0;
- char *end;
-
- tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES);
- len-= (uint)tmp;
- from+= tmp;
- my_errno=0;
- if (unsigned_flag)
- {
- if (!len || test_if_minus(cs, from, from + len))
- {
- tmp=0; // Set negative to 0
- my_errno= ERANGE;
- error= 1;
- }
- else
- tmp=(longlong) my_strntoull(cs,from,len,10,&end,&error);
- }
- else
- tmp=my_strntoll(cs,from,len,10,&end,&error);
- if (error ||
- (from+len != end && table->in_use->count_cuted_fields &&
- !test_if_int(from,len,end,cs)))
- {
- if (error != 1)
- {
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- error= 2;
- }
- }
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int8store(ptr,tmp);
- }
- else
- #endif
- longlongstore(ptr,tmp);
- return error;
- }
- int Field_longlong::store(double nr)
- {
- int error= 0;
- longlong res;
- nr=rint(nr);
- if (unsigned_flag)
- {
- if (nr < 0)
- {
- res=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr >= (double) ~ (ulonglong) 0)
- {
- res= ~(longlong) 0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- res=(longlong) (ulonglong) nr;
- }
- else
- {
- if (nr <= (double) LONGLONG_MIN)
- {
- res=(longlong) LONGLONG_MIN;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr >= (double) (ulonglong) LONGLONG_MAX)
- {
- res=(longlong) LONGLONG_MAX;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- res=(longlong) nr;
- }
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int8store(ptr,res);
- }
- else
- #endif
- longlongstore(ptr,res);
- return error;
- }
- int Field_longlong::store(longlong nr)
- {
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- int8store(ptr,nr);
- }
- else
- #endif
- longlongstore(ptr,nr);
- return 0;
- }
- double Field_longlong::val_real(void)
- {
- longlong j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- j=sint8korr(ptr);
- }
- else
- #endif
- longlongget(j,ptr);
- /* The following is open coded to avoid a bug in gcc 3.3 */
- if (unsigned_flag)
- {
- ulonglong tmp= (ulonglong) j;
- return ulonglong2double(tmp);
- }
- return (double) j;
- }
- longlong Field_longlong::val_int(void)
- {
- longlong j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- j=sint8korr(ptr);
- else
- #endif
- longlongget(j,ptr);
- return j;
- }
- String *Field_longlong::val_str(String *val_buffer,
- String *val_ptr __attribute__((unused)))
- {
- CHARSET_INFO *cs= &my_charset_bin;
- uint length;
- uint mlength=max(field_length+1,22*cs->mbmaxlen);
- val_buffer->alloc(mlength);
- char *to=(char*) val_buffer->ptr();
- longlong j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- j=sint8korr(ptr);
- else
- #endif
- longlongget(j,ptr);
- length=(uint) (cs->cset->longlong10_to_str)(cs,to,mlength,
- unsigned_flag ? 10 : -10, j);
- val_buffer->length(length);
- if (zerofill)
- prepend_zeros(val_buffer);
- return val_buffer;
- }
- bool Field_longlong::send_binary(Protocol *protocol)
- {
- return protocol->store_longlong(Field_longlong::val_int(), unsigned_flag);
- }
- int Field_longlong::cmp(const char *a_ptr, const char *b_ptr)
- {
- longlong a,b;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- a=sint8korr(a_ptr);
- b=sint8korr(b_ptr);
- }
- else
- #endif
- {
- longlongget(a,a_ptr);
- longlongget(b,b_ptr);
- }
- if (unsigned_flag)
- return ((ulonglong) a < (ulonglong) b) ? -1 :
- ((ulonglong) a > (ulonglong) b) ? 1 : 0;
- return (a < b) ? -1 : (a > b) ? 1 : 0;
- }
- void Field_longlong::sort_string(char *to,uint length __attribute__((unused)))
- {
- #ifdef WORDS_BIGENDIAN
- if (!table->db_low_byte_first)
- {
- if (unsigned_flag)
- to[0] = ptr[0];
- else
- to[0] = (char) (ptr[0] ^ 128); /* Revers signbit */
- to[1] = ptr[1];
- to[2] = ptr[2];
- to[3] = ptr[3];
- to[4] = ptr[4];
- to[5] = ptr[5];
- to[6] = ptr[6];
- to[7] = ptr[7];
- }
- else
- #endif
- {
- if (unsigned_flag)
- to[0] = ptr[7];
- else
- to[0] = (char) (ptr[7] ^ 128); /* Revers signbit */
- to[1] = ptr[6];
- to[2] = ptr[5];
- to[3] = ptr[4];
- to[4] = ptr[3];
- to[5] = ptr[2];
- to[6] = ptr[1];
- to[7] = ptr[0];
- }
- }
- void Field_longlong::sql_type(String &res) const
- {
- CHARSET_INFO *cs=res.charset();
- res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
- "bigint(%d)",(int) field_length));
- add_zerofill_and_unsigned(res);
- }
- /****************************************************************************
- single precision float
- ****************************************************************************/
- int Field_float::store(const char *from,uint len,CHARSET_INFO *cs)
- {
- int error;
- char *end;
- double nr= my_strntod(cs,(char*) from,len,&end,&error);
- if (error || ((uint) (end-from) != len && table->in_use->count_cuted_fields))
- {
- error= 2;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- }
- Field_float::store(nr);
- return error;
- }
- int Field_float::store(double nr)
- {
- float j;
- int error= 0;
- if (isnan(nr))
- {
- j= 0;
- set_null();
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (unsigned_flag && nr < 0)
- {
- j= 0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- {
- double max_value;
- if (dec >= NOT_FIXED_DEC)
- {
- max_value= FLT_MAX;
- }
- else
- {
- uint tmp=min(field_length,array_elements(log_10)-1);
- max_value= (log_10[tmp]-1)/log_10[dec];
- /*
- The following comparison is needed to not get an overflow if nr
- is close to FLT_MAX
- */
- if (fabs(nr) < FLT_MAX/10.0e+32)
- nr= floor(nr*log_10[dec]+0.5)/log_10[dec];
- }
- if (nr < -max_value)
- {
- j= (float)-max_value;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > max_value)
- {
- j= (float)max_value;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- j= (float) nr;
- }
-
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- float4store(ptr,j);
- }
- else
- #endif
- memcpy_fixed(ptr,(byte*) &j,sizeof(j));
- return error;
- }
- int Field_float::store(longlong nr)
- {
- return store((double)nr);
- }
- double Field_float::val_real(void)
- {
- float j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- float4get(j,ptr);
- }
- else
- #endif
- memcpy_fixed((byte*) &j,ptr,sizeof(j));
- return ((double) j);
- }
- longlong Field_float::val_int(void)
- {
- float j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- float4get(j,ptr);
- }
- else
- #endif
- memcpy_fixed((byte*) &j,ptr,sizeof(j));
- return ((longlong) j);
- }
- String *Field_float::val_str(String *val_buffer,
- String *val_ptr __attribute__((unused)))
- {
- float nr;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- float4get(nr,ptr);
- }
- else
- #endif
- memcpy_fixed((byte*) &nr,ptr,sizeof(nr));
- uint to_length=max(field_length,70);
- val_buffer->alloc(to_length);
- char *to=(char*) val_buffer->ptr();
- if (dec >= NOT_FIXED_DEC)
- {
- sprintf(to,"%-*.*g",(int) field_length,FLT_DIG,nr);
- to=strcend(to,' ');
- *to=0;
- }
- else
- {
- #ifdef HAVE_FCONVERT
- char buff[70],*pos=buff;
- int decpt,sign,tmp_dec=dec;
- VOID(sfconvert(&nr,tmp_dec,&decpt,&sign,buff));
- if (sign)
- {
- *to++='-';
- }
- if (decpt < 0)
- { /* val_buffer is < 0 */
- *to++='0';
- if (!tmp_dec)
- goto end;
- *to++='.';
- if (-decpt > tmp_dec)
- decpt= - (int) tmp_dec;
- tmp_dec=(uint) ((int) tmp_dec+decpt);
- while (decpt++ < 0)
- *to++='0';
- }
- else if (decpt == 0)
- {
- *to++= '0';
- if (!tmp_dec)
- goto end;
- *to++='.';
- }
- else
- {
- while (decpt-- > 0)
- *to++= *pos++;
- if (!tmp_dec)
- goto end;
- *to++='.';
- }
- while (tmp_dec--)
- *to++= *pos++;
- #else
- #ifdef HAVE_SNPRINTF
- to[to_length-1]=0; // Safety
- snprintf(to,to_length-1,"%.*f",dec,nr);
- to=strend(to);
- #else
- to+= my_sprintf(to,(to,"%.*f",dec,nr));
- #endif
- #endif
- }
- #ifdef HAVE_FCONVERT
- end:
- #endif
- val_buffer->length((uint) (to-val_buffer->ptr()));
- if (zerofill)
- prepend_zeros(val_buffer);
- return val_buffer;
- }
- int Field_float::cmp(const char *a_ptr, const char *b_ptr)
- {
- float a,b;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- float4get(a,a_ptr);
- float4get(b,b_ptr);
- }
- else
- #endif
- {
- memcpy_fixed(&a,a_ptr,sizeof(float));
- memcpy_fixed(&b,b_ptr,sizeof(float));
- }
- return (a < b) ? -1 : (a > b) ? 1 : 0;
- }
- #define FLT_EXP_DIG (sizeof(float)*8-FLT_MANT_DIG)
- void Field_float::sort_string(char *to,uint length __attribute__((unused)))
- {
- float nr;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- float4get(nr,ptr);
- }
- else
- #endif
- memcpy_fixed(&nr,ptr,sizeof(float));
- uchar *tmp= (uchar*) to;
- if (nr == (float) 0.0)
- { /* Change to zero string */
- tmp[0]=(uchar) 128;
- bzero((char*) tmp+1,sizeof(nr)-1);
- }
- else
- {
- #ifdef WORDS_BIGENDIAN
- memcpy_fixed(tmp,&nr,sizeof(nr));
- #else
- tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
- #endif
- if (tmp[0] & 128) /* Negative */
- { /* make complement */
- uint i;
- for (i=0 ; i < sizeof(nr); i++)
- tmp[i]= (uchar) (tmp[i] ^ (uchar) 255);
- }
- else
- {
- ushort exp_part=(((ushort) tmp[0] << 8) | (ushort) tmp[1] |
- (ushort) 32768);
- exp_part+= (ushort) 1 << (16-1-FLT_EXP_DIG);
- tmp[0]= (uchar) (exp_part >> 8);
- tmp[1]= (uchar) exp_part;
- }
- }
- }
- bool Field_float::send_binary(Protocol *protocol)
- {
- return protocol->store((float) Field_float::val_real(), dec, (String*) 0);
- }
- void Field_float::sql_type(String &res) const
- {
- if (dec == NOT_FIXED_DEC)
- {
- res.set_ascii("float", 5);
- }
- else
- {
- CHARSET_INFO *cs= res.charset();
- res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
- "float(%d,%d)",(int) field_length,dec));
- }
- add_zerofill_and_unsigned(res);
- }
- /****************************************************************************
- double precision floating point numbers
- ****************************************************************************/
- int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
- {
- int error;
- char *end;
- double nr= my_strntod(cs,(char*) from, len, &end, &error);
- if (error || ((uint) (end-from) != len && table->in_use->count_cuted_fields))
- {
- error= 2;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- }
- Field_double::store(nr);
- return error;
- }
- int Field_double::store(double nr)
- {
- int error= 0;
- if (isnan(nr))
- {
- nr= 0;
- set_null();
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (unsigned_flag && nr < 0)
- {
- nr= 0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else
- {
- double max_value;
- if (dec >= NOT_FIXED_DEC)
- {
- max_value= DBL_MAX;
- }
- else
- {
- uint tmp=min(field_length,array_elements(log_10)-1);
- max_value= (log_10[tmp]-1)/log_10[dec];
- if (fabs(nr) < DBL_MAX/10.0e+32)
- nr= floor(nr*log_10[dec]+0.5)/log_10[dec];
- }
- if (nr < -max_value)
- {
- nr= -max_value;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- else if (nr > max_value)
- {
- nr= max_value;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- error= 1;
- }
- }
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- float8store(ptr,nr);
- }
- else
- #endif
- doublestore(ptr,nr);
- return error;
- }
- int Field_double::store(longlong nr)
- {
- return store((double)nr);
- }
- double Field_double::val_real(void)
- {
- double j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- float8get(j,ptr);
- }
- else
- #endif
- doubleget(j,ptr);
- return j;
- }
- longlong Field_double::val_int(void)
- {
- double j;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- float8get(j,ptr);
- }
- else
- #endif
- doubleget(j,ptr);
- return ((longlong) j);
- }
- String *Field_double::val_str(String *val_buffer,
- String *val_ptr __attribute__((unused)))
- {
- double nr;
- #ifdef WORDS_BIGENDIAN
- if (table->db_low_byte_first)
- {
- float8get(nr,ptr);
- }
- else
- #endif
- doubleget(nr,ptr);
- uint to_length=max(field_length, DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE);
- val_buffer->alloc(to_length);
- char *to=(char*) val_buffer->ptr();
- if (dec >= NOT_FIXED_DEC)
- {
- sprintf(to,"%-*.*g",(int) field_length,DBL_DIG,nr);
- to=strcend(to,' ');
- }
- else
- {
- #ifdef HAVE_FCONVERT
- char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
- char *pos= buff;
- int decpt,sign,tmp_dec=dec;
- VOID(fconvert(nr,tmp_dec,&decpt,&sign,buff));
- if (sign)
- {
- *to++='-';
- }
- if (decpt < 0)
- { /* val_buffer is < 0 */
- *to++='0';
- if (!tmp_dec)
- goto end;
- *to++='.';
- if (-decpt > tmp_dec)
- decpt= - (int) tmp_dec;
- tmp_dec=(uint) ((int) tmp_dec+decpt);
- while (decpt++ < 0)
- *to++='0';
- }
- else if (decpt == 0)
- {
- *to++= '0';
- if (!tmp_dec)
- goto end;
- *to++='.';
- }
- else
- {
- while (decpt-- > 0)
- *to++= *pos++;
- if (!tmp_dec)
- goto end;
- *to++='.';
- }
- while (tmp_dec--)
- *to++= *pos++;
- #else
- #ifdef HAVE_SNPRINTF
- to[to_length-1]=0; // Safety
- snprintf(to,to_length-1,"%.*f",dec,nr);
- to=strend(to);
- #else
- to+= my_sprintf(to,(to,"%.*f",dec,nr));
- #endif
- #endif
- }
- #ifdef HAVE_FCONVERT
- end:
- #endif
- val_buffer->length((uint) (to-val_buffer->ptr()));
- if (zerofill)
- prepend_zeros(val_buffer);
- return val_buffer;
- }
- bool Field_double::send_binary(Protocol *protocol)
- {
- return protocol->store((double) Field_double::val_real(), dec, (String*) 0);
- }
- int Field_double::cmp(const char *a_ptr, const char *b_ptr)
- {