/* Copyright (c) 2003, 2011, Oracle and/or its affiliates. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef NDB_SQL_UTIL_HPP #define NDB_SQL_UTIL_HPP #include #include struct charset_info_st; typedef struct charset_info_st CHARSET_INFO; /** * Helper class with comparison functions on NDB (column) data types. * * Notes: this Helper class * - is used by kernel code * - provides non-elementary functions * - is not generic, template-based code * - has link/library dependencies upon MySQL code * (in contrast to other type utility classes, like ./NdbTypesUtil). */ class NdbSqlUtil { public: /** * Compare attribute values. Returns negative, zero, positive for * less, equal, greater. We trust DBTUP to validate all data and * mysql upgrade to not invalidate them. Bad values (such as NaN) * causing undefined results crash here always (require, not assert) * since they are likely to cause a more obscure crash in DBTUX. * wl4163_todo: API probably should not crash. * * Parameters are pointers to values (no alignment requirements) and * their lengths in bytes. First parameter is a pointer to type * specific extra info. Char types receive CHARSET_INFO in it. */ typedef int Cmp(const void* info, const void* p1, uint n1, const void* p2, uint n2); /** * Prototype for "like" comparison. Defined for string types. First * argument can be fixed or var* type, second argument is fixed. * Returns 0 on match, +1 on no match, and -1 on bad data. * * Uses default special chars ( \ % _ ). */ typedef int Like(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2); /** * Prototype for mask comparisons. Defined for bit type. * * If common portion of data AND Mask is equal to mask * return 0, else return 1. * If cmpZero, compare data AND Mask to zero. */ typedef int AndMask(const void* data, unsigned dataLen, const void* mask, unsigned maskLen, bool cmpZero); struct Type { enum Enum { Undefined = NDB_TYPE_UNDEFINED, Tinyint = NDB_TYPE_TINYINT, Tinyunsigned = NDB_TYPE_TINYUNSIGNED, Smallint = NDB_TYPE_SMALLINT, Smallunsigned = NDB_TYPE_SMALLUNSIGNED, Mediumint = NDB_TYPE_MEDIUMINT, Mediumunsigned = NDB_TYPE_MEDIUMUNSIGNED, Int = NDB_TYPE_INT, Unsigned = NDB_TYPE_UNSIGNED, Bigint = NDB_TYPE_BIGINT, Bigunsigned = NDB_TYPE_BIGUNSIGNED, Float = NDB_TYPE_FLOAT, Double = NDB_TYPE_DOUBLE, Olddecimal = NDB_TYPE_OLDDECIMAL, Char = NDB_TYPE_CHAR, Varchar = NDB_TYPE_VARCHAR, Binary = NDB_TYPE_BINARY, Varbinary = NDB_TYPE_VARBINARY, Datetime = NDB_TYPE_DATETIME, Date = NDB_TYPE_DATE, Blob = NDB_TYPE_BLOB, Text = NDB_TYPE_TEXT, Bit = NDB_TYPE_BIT, Longvarchar = NDB_TYPE_LONGVARCHAR, Longvarbinary = NDB_TYPE_LONGVARBINARY, Time = NDB_TYPE_TIME, Year = NDB_TYPE_YEAR, Timestamp = NDB_TYPE_TIMESTAMP, Olddecimalunsigned = NDB_TYPE_OLDDECIMALUNSIGNED, Decimal = NDB_TYPE_DECIMAL, Decimalunsigned = NDB_TYPE_DECIMALUNSIGNED, Time2 = NDB_TYPE_TIME2, Datetime2 = NDB_TYPE_DATETIME2, Timestamp2 = NDB_TYPE_TIMESTAMP2 }; Enum m_typeId; // redundant Cmp* m_cmp; // comparison method Like* m_like; // "like" comparison method AndMask* m_mask; // Mask comparison method }; /** * Get type by id. Can return the Undefined type. */ static const Type& getType(Uint32 typeId); /** * Check character set. */ static uint check_column_for_pk(Uint32 typeId, const void* info); static uint check_column_for_hash_index(Uint32 typeId, const void* info); static uint check_column_for_ordered_index(Uint32 typeId, const void* info); /** * Get number of length bytes and length from variable length string. * Returns false on error (invalid data). For other types returns * zero length bytes and the fixed attribute length. */ static bool get_var_length(Uint32 typeId, const void* p, unsigned attrlen, Uint32& lb, Uint32& len); /** * Temporary workaround for bug#7284. */ static int strnxfrm_bug7284(CHARSET_INFO* cs, unsigned char* dst, unsigned dstLen, const unsigned char*src, unsigned srcLen); /** * Wrapper for 'strnxfrm' who change prototype in 5.6 */ static size_t ndb_strnxfrm(struct charset_info_st * cs, uchar *dst, size_t dstlen, const uchar *src, size_t srclen); /** * Convert attribute data to/from network byte order * This method converts the passed data of the passed type * between host and network byte order. * On little-endian (network order) hosts, it has no effect. */ static void convertByteOrder(Uint32 typeId, Uint32 typeLog2Size, Uint32 arrayType, Uint32 arraySize, uchar* data, Uint32 dataByteSize); /** * Unpack and pack date/time types. There is no check that the data * is valid for MySQL. Random input gives equally random output. * Fractional seconds wl#946 introduce new formats (type names with * suffix 2). The methods for these take an extra precision argument * with range 0-6 which translates to 0-3 bytes. */ struct Year { uint year; }; struct Date { uint year, month, day; }; struct Time { uint sign; // as in Time2 uint hour, minute, second; }; struct Datetime { uint year, month, day; uint hour, minute, second; }; struct Timestamp { uint second; }; struct Time2 { uint sign; uint interval; uint hour, minute, second; uint fraction; }; struct Datetime2 { uint sign; uint year, month, day; uint hour, minute, second; uint fraction; }; struct Timestamp2 { uint second; uint fraction; }; // bytes to struct static void unpack_year(Year&, const uchar*); static void unpack_date(Date&, const uchar*); static void unpack_time(Time&, const uchar*); static void unpack_datetime(Datetime&, const uchar*); static void unpack_timestamp(Timestamp&, const uchar*); static void unpack_time2(Time2&, const uchar*, uint prec); static void unpack_datetime2(Datetime2&, const uchar*, uint prec); static void unpack_timestamp2(Timestamp2&, const uchar*, uint prec); // struct to bytes static void pack_year(const Year&, uchar*); static void pack_date(const Date&, uchar*); static void pack_time(const Time&, uchar*); static void pack_datetime(const Datetime&, uchar*); static void pack_timestamp(const Timestamp&, uchar*); static void pack_time2(const Time2&, uchar*, uint prec); static void pack_datetime2(const Datetime2&, uchar*, uint prec); static void pack_timestamp2(const Timestamp2&, uchar*, uint prec); private: friend class NdbPack; /** * List of all types. Must match Type::Enum. */ static const Type m_typeList[]; /** * Comparison methods. */ static Cmp cmpTinyint; static Cmp cmpTinyunsigned; static Cmp cmpSmallint; static Cmp cmpSmallunsigned; static Cmp cmpMediumint; static Cmp cmpMediumunsigned; static Cmp cmpInt; static Cmp cmpUnsigned; static Cmp cmpBigint; static Cmp cmpBigunsigned; static Cmp cmpFloat; static Cmp cmpDouble; static Cmp cmpOlddecimal; static Cmp cmpChar; static Cmp cmpVarchar; static Cmp cmpBinary; static Cmp cmpVarbinary; static Cmp cmpDatetime; static Cmp cmpDate; static Cmp cmpBlob; static Cmp cmpText; static Cmp cmpBit; static Cmp cmpLongvarchar; static Cmp cmpLongvarbinary; static Cmp cmpTime; static Cmp cmpYear; static Cmp cmpTimestamp; static Cmp cmpOlddecimalunsigned; static Cmp cmpDecimal; static Cmp cmpDecimalunsigned; static Cmp cmpTime2; static Cmp cmpDatetime2; static Cmp cmpTimestamp2; // static Like likeChar; static Like likeBinary; static Like likeVarchar; static Like likeVarbinary; static Like likeLongvarchar; static Like likeLongvarbinary; // static AndMask maskBit; }; #endif