List:Internals« Previous MessageNext Message »
From:sanja Date:March 23 2005 7:36am
Subject:bk commit into 4.1 tree (bell:1.2129) BUG#8824
View as plain text  
Below is the list of changes that have just been committed into a local
4.1 repository of bell. When bell does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2129 05/03/23 08:36:48 bell@stripped +17 -0
  fixed union types merging and table related metadata (BUG#8824)

  sql/sql_union.cc
    1.140 05/03/23 08:36:42 bell@stripped +6 -6
    added table name parameter to prepare() to show right table alias for derived tables

  sql/sql_select.cc
    1.386 05/03/23 08:36:42 bell@stripped +3 -11
    new temporary table field creation by Item_type_holder
    fixed table alias for temporary table

  sql/sql_prepare.cc
    1.145 05/03/23 08:36:42 bell@stripped +2 -2
    added table name parameter to prepare() to show right table alias for derived tables

  sql/sql_parse.cc
    1.429 05/03/23 08:36:42 bell@stripped +2 -4
    made function for enum/set pack length calculation

  sql/sql_lex.h
    1.184 05/03/23 08:36:42 bell@stripped +2 -1
    added table name parameter to prepare() to show right table alias for derived tables

  sql/sql_derived.cc
    1.79 05/03/23 08:36:42 bell@stripped +2 -2
    added table name parameter to prepare() to show right table alias for derived tables

  sql/item_subselect.cc
    1.130 05/03/23 08:36:42 bell@stripped +1 -1
    added table name parameter to prepare() to show right table alias for derived tables

  sql/item_func.h
    1.120 05/03/23 08:36:42 bell@stripped +2 -1
    new item type to make correct field type detection possible

  sql/item.h
    1.174 05/03/23 08:36:42 bell@stripped +16 -16
    replaced mechanism of merging types of UNION

  sql/item.cc
    1.195 05/03/23 08:36:42 bell@stripped +204 -140
    fixed bug in NEW_DATE type field creartion
    replaced mechanism of merging types of UNION

  sql/field.h
    1.125 05/03/23 08:36:42 bell@stripped +13 -35
    removed unned field type reporting

  sql/field.cc
    1.212 05/03/23 08:36:42 bell@stripped +805 -190
    Field type merging rules added
    Fixed table name/alias returting for field made from temporary tables

  mysql-test/t/union.test
    1.81 05/03/23 08:36:42 bell@stripped +25 -0
    test of union of enum

  mysql-test/t/metadata.test
    1.3 05/03/23 08:36:41 bell@stripped +13 -0
    test of metadata of variables, unions and derived tables

  mysql-test/r/union.result
    1.87 05/03/23 08:36:41 bell@stripped +46 -11
    new results
    test of union of enum

  mysql-test/r/metadata.result
    1.7 05/03/23 08:36:41 bell@stripped +26 -1
    new result
    test of metadata of variables, unions and derived tables

  mysql-test/r/func_group.result
    1.38 05/03/23 08:36:41 bell@stripped +1 -1
    new result

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	bell
# Host:	sanja.is.com.ua
# Root:	/home/bell/mysql/bk/work-union_merge-4.1

--- 1.211/sql/field.cc	Tue Feb 22 12:51:53 2005
+++ 1.212/sql/field.cc	Wed Mar 23 08:36:42 2005
@@ -48,6 +48,793 @@
 
 #define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE 320
 
+/*
+  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
 *****************************************************************************/
@@ -164,156 +951,6 @@
 #endif
 
 
-/*
- Tables of filed type compatibility.
-
- There are tables for every type, table consist of list of types in which
- given type can be converted without data lost, list should be ended with
- FIELD_CAST_STOP
-*/
-static Field::field_cast_enum field_cast_decimal[]=
-{Field::FIELD_CAST_DECIMAL,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_tiny[]=
-{Field::FIELD_CAST_TINY,
- Field::FIELD_CAST_SHORT, Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG,
- Field::FIELD_CAST_LONGLONG,
- Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_short[]=
-{Field::FIELD_CAST_SHORT,
- Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG, Field::FIELD_CAST_LONGLONG,
- Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_medium[]=
-{Field::FIELD_CAST_MEDIUM,
- Field::FIELD_CAST_LONG, Field::FIELD_CAST_LONGLONG,
- Field::FIELD_CAST_DOUBLE,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_long[]=
-{Field::FIELD_CAST_LONG,
- Field::FIELD_CAST_LONGLONG,
- Field::FIELD_CAST_DOUBLE,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_longlong[]=
-{Field::FIELD_CAST_LONGLONG,
- Field::FIELD_CAST_DOUBLE,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_float[]=
-{Field::FIELD_CAST_FLOAT,
- Field::FIELD_CAST_DOUBLE,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_double[]=
-{Field::FIELD_CAST_DOUBLE,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_null[]=
-{Field::FIELD_CAST_NULL,
- Field::FIELD_CAST_DECIMAL, Field::FIELD_CAST_TINY, Field::FIELD_CAST_SHORT,
- Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG, Field::FIELD_CAST_LONGLONG,
- Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE,
- Field::FIELD_CAST_TIMESTAMP, Field::FIELD_CAST_YEAR,
- Field::FIELD_CAST_DATE, Field::FIELD_CAST_NEWDATE,
- Field::FIELD_CAST_TIME, Field::FIELD_CAST_DATETIME,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB,
- Field::FIELD_CAST_GEOM, Field::FIELD_CAST_ENUM, Field::FIELD_CAST_SET,
- Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_timestamp[]=
-{Field::FIELD_CAST_TIMESTAMP,
- Field::FIELD_CAST_DATETIME,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_year[]=
-{Field::FIELD_CAST_YEAR,
- Field::FIELD_CAST_SHORT, Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG,
- Field::FIELD_CAST_LONGLONG,
- Field::FIELD_CAST_FLOAT, Field::FIELD_CAST_DOUBLE,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_date[]=
-{Field::FIELD_CAST_DATE,
- Field::FIELD_CAST_DATETIME,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_newdate[]=
-{Field::FIELD_CAST_NEWDATE,
- Field::FIELD_CAST_DATE,
- Field::FIELD_CAST_DATETIME,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_time[]=
-{Field::FIELD_CAST_TIME,
- Field::FIELD_CAST_DATETIME,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_datetime[]=
-{Field::FIELD_CAST_DATETIME,
- Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_string[]=
-{Field::FIELD_CAST_STRING,
- Field::FIELD_CAST_VARSTRING, Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_varstring[]=
-{Field::FIELD_CAST_VARSTRING,
- Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_blob[]=
-{Field::FIELD_CAST_BLOB,
- Field::FIELD_CAST_STOP};
-/*
-  Geometrical, enum and set fields can be casted only to expressions
-*/
-static Field::field_cast_enum field_cast_geom[]=
-{Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_enum[]=
-{Field::FIELD_CAST_STOP};
-static Field::field_cast_enum field_cast_set[]=
-{Field::FIELD_CAST_STOP};
-// Array of pointers on conversion table for all fields types casting
-static Field::field_cast_enum *field_cast_array[]=
-{0, //FIELD_CAST_STOP
- field_cast_decimal, field_cast_tiny, field_cast_short,
- field_cast_medium, field_cast_long, field_cast_longlong,
- field_cast_float, field_cast_double,
- field_cast_null,
- field_cast_timestamp, field_cast_year, field_cast_date, field_cast_newdate,
- field_cast_time, field_cast_datetime,
- field_cast_string, field_cast_varstring, field_cast_blob,
- field_cast_geom, field_cast_enum, field_cast_set
-};
-
-
-/*
-  Check if field of given type can store a value of this field.
-
-  SYNOPSIS
-    type   type for test
-
-  RETURN
-    1 can
-    0 can not
-*/
-
-bool Field::field_cast_compatible(Field::field_cast_enum type)
-{
-  DBUG_ASSERT(type != FIELD_CAST_STOP);
-  Field::field_cast_enum *array= field_cast_array[field_cast_type()];
-  while (*array != FIELD_CAST_STOP)
-  {
-    if (*(array++) == type)
-      return 1;
-  }
-  return 0;
-}
-
-
 /****************************************************************************
 ** Functions for the base classes
 ** This is an unpacked number.
@@ -373,9 +1010,15 @@
 void Field_num::make_field(Send_field *field)
 {
   /* table_cache_key is not set for temp tables */
-  field->db_name= (orig_table->table_cache_key ? orig_table->table_cache_key :
-		   "");
-  field->org_table_name= orig_table->real_name;
+  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;
@@ -389,9 +1032,15 @@
 void Field_str::make_field(Send_field *field)
 {
   /* table_cache_key is not set for temp tables */
-  field->db_name= (orig_table->table_cache_key ? orig_table->table_cache_key :
-		   "");
-  field->org_table_name= orig_table->real_name;
+  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;
@@ -6054,40 +6703,6 @@
     break;
   }
   return 0;
-}
-
-
-/*
-  Check if field_type is appropriate field type
-  to create field for tmp table using
-  item->tmp_table_field() method
-
-  SYNOPSIS
-    field_types_to_be_kept()
-    field_type     - field type
-
-  NOTE
-    it is used in function get_holder_example_field()
-    from item.cc
-
-  RETURN
-    1 - can use item->tmp_table_field() method
-    0 - can not use item->tmp_table_field() method
-
-*/
-
-bool field_types_to_be_kept(enum_field_types field_type)
-{
-  switch (field_type)
-  {
-    case FIELD_TYPE_DATE:
-    case FIELD_TYPE_NEWDATE:
-    case FIELD_TYPE_TIME:
-    case FIELD_TYPE_DATETIME:
-      return 1;
-    default:
-      return 0;
-  }
 }
 
 

--- 1.124/sql/field.h	Mon Feb 28 11:59:41 2005
+++ 1.125/sql/field.h	Wed Mar 23 08:36:42 2005
@@ -31,6 +31,17 @@
 struct st_cache_field;
 void field_conv(Field *to,Field *from);
 
+inline uint get_enum_pack_length(int elements)
+{
+  return elements < 256 ? 1 : 2;
+}
+
+inline uint get_set_pack_length(int elements)
+{
+  uint len= (elements + 7) / 8;
+  return len > 4 ? 8 : len;
+}
+
 class Field
 {
   Field(const Item &);				/* Prevent use of these */
@@ -75,17 +86,6 @@
     GEOM_GEOMETRYCOLLECTION = 7
   };
   enum imagetype { itRAW, itMBR};
-  enum field_cast_enum
-  {
-    FIELD_CAST_STOP, FIELD_CAST_DECIMAL, FIELD_CAST_TINY, FIELD_CAST_SHORT,
-    FIELD_CAST_MEDIUM, FIELD_CAST_LONG, FIELD_CAST_LONGLONG,
-    FIELD_CAST_FLOAT, FIELD_CAST_DOUBLE,
-    FIELD_CAST_NULL,
-    FIELD_CAST_TIMESTAMP, FIELD_CAST_YEAR, FIELD_CAST_DATE, FIELD_CAST_NEWDATE,
-    FIELD_CAST_TIME, FIELD_CAST_DATETIME,
-    FIELD_CAST_STRING, FIELD_CAST_VARSTRING, FIELD_CAST_BLOB,
-    FIELD_CAST_GEOM, FIELD_CAST_ENUM, FIELD_CAST_SET
-  };
 
   utype		unireg_check;
   uint32	field_length;		// Length of field
@@ -119,6 +119,8 @@
   virtual String *val_str(String*,String *)=0;
   virtual Item_result result_type () const=0;
   virtual Item_result cmp_type () const { return result_type(); }
+  static enum_field_types field_type_merge(enum_field_types, enum_field_types);
+  static Item_result result_merge_type(enum_field_types);
   bool eq(Field *field) { return ptr == field->ptr && null_ptr ==
field->null_ptr; }
   virtual bool eq_def(Field *field);
   virtual uint32 pack_length() const { return (uint32) field_length; }
@@ -290,8 +292,6 @@
                             int cuted_increment);
   void set_datetime_warning(const uint level, const uint code, 
                             double nr, timestamp_type ts_type);
-  virtual field_cast_enum field_cast_type()= 0;
-  bool field_cast_compatible(field_cast_enum type);
   /* maximum possible display length */
   virtual uint32 max_length()= 0;
   friend bool reopen_table(THD *,struct st_table *,bool);
@@ -398,7 +398,6 @@
   bool zero_pack() const { return 0; }
   void sql_type(String &str) const;
   uint32 max_length() { return field_length; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_DECIMAL; }
 };
 
 
@@ -430,7 +429,6 @@
   uint32 pack_length() const { return 1; }
   void sql_type(String &str) const;
   uint32 max_length() { return 4; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_TINY; }
 };
 
 
@@ -467,7 +465,6 @@
   uint32 pack_length() const { return 2; }
   void sql_type(String &str) const;
   uint32 max_length() { return 6; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_SHORT; }
 };
 
 
@@ -499,7 +496,6 @@
   uint32 pack_length() const { return 3; }
   void sql_type(String &str) const;
   uint32 max_length() { return 8; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_MEDIUM; }
 };
 
 
@@ -536,7 +532,6 @@
   uint32 pack_length() const { return 4; }
   void sql_type(String &str) const;
   uint32 max_length() { return 11; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_LONG; }
 };
 
 
@@ -576,7 +571,6 @@
   void sql_type(String &str) const;
   bool can_be_compared_as_longlong() const { return TRUE; }
   uint32 max_length() { return 20; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_LONGLONG; }
 };
 #endif
 
@@ -611,7 +605,6 @@
   uint32 pack_length() const { return sizeof(float); }
   void sql_type(String &str) const;
   uint32 max_length() { return 24; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_FLOAT; }
 };
 
 
@@ -646,7 +639,6 @@
   uint32 pack_length() const { return sizeof(double); }
   void sql_type(String &str) const;
   uint32 max_length() { return 53; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_DOUBLE; }
 };
 
 
@@ -677,7 +669,6 @@
   void sql_type(String &str) const;
   uint size_of() const { return sizeof(*this); }
   uint32 max_length() { return 4; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_NULL; }
 };
 
 
@@ -729,7 +720,6 @@
   }
   bool get_date(TIME *ltime,uint fuzzydate);
   bool get_time(TIME *ltime);
-  field_cast_enum field_cast_type() { return FIELD_CAST_TIMESTAMP; }
   timestamp_auto_set_type get_auto_set_type() const;
 };
 
@@ -753,7 +743,6 @@
   bool send_binary(Protocol *protocol);
   void sql_type(String &str) const;
   bool can_be_compared_as_longlong() const { return TRUE; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_YEAR; }
 };
 
 
@@ -786,7 +775,6 @@
   void sql_type(String &str) const;
   bool can_be_compared_as_longlong() const { return TRUE; }
   bool zero_pack() const { return 1; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_DATE; }
 };
 
 class Field_newdate :public Field_str {
@@ -818,7 +806,6 @@
   bool zero_pack() const { return 1; }
   bool get_date(TIME *ltime,uint fuzzydate);
   bool get_time(TIME *ltime);
-  field_cast_enum field_cast_type() { return FIELD_CAST_NEWDATE; }
 };
 
 
@@ -853,7 +840,6 @@
   void sql_type(String &str) const;
   bool can_be_compared_as_longlong() const { return TRUE; }
   bool zero_pack() const { return 1; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_TIME; }
 };
 
 
@@ -891,7 +877,6 @@
   bool zero_pack() const { return 1; }
   bool get_date(TIME *ltime,uint fuzzydate);
   bool get_time(TIME *ltime);
-  field_cast_enum field_cast_type() { return FIELD_CAST_DATETIME; }
 };
 
 
@@ -937,7 +922,6 @@
   enum_field_types real_type() const { return FIELD_TYPE_STRING; }
   bool has_charset(void) const
   { return charset() == &my_charset_bin ? FALSE : TRUE; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_STRING; }
 };
 
 
@@ -986,7 +970,6 @@
   enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; }
   bool has_charset(void) const
   { return charset() == &my_charset_bin ? FALSE : TRUE; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_VARSTRING; }
 };
 
 
@@ -1081,7 +1064,6 @@
   uint size_of() const { return sizeof(*this); }
   bool has_charset(void) const
   { return charset() == &my_charset_bin ? FALSE : TRUE; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_BLOB; }
   uint32 max_length();
 };
 
@@ -1111,7 +1093,6 @@
 
   void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type);
   void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
-  field_cast_enum field_cast_type() { return FIELD_CAST_GEOM; }
 };
 #endif /*HAVE_SPATIAL*/
 
@@ -1155,7 +1136,6 @@
   bool has_charset(void) const { return TRUE; }
   /* enum and set are sorted as integers */
   CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_ENUM; }
 };
 
 
@@ -1181,7 +1161,6 @@
   void sql_type(String &str) const;
   enum_field_types real_type() const { return FIELD_TYPE_SET; }
   bool has_charset(void) const { return TRUE; }
-  field_cast_enum field_cast_type() { return FIELD_CAST_SET; }
 };
 
 
@@ -1268,7 +1247,6 @@
 int set_field_to_null_with_conversions(Field *field, bool no_conversions);
 bool test_if_int(const char *str, int length, const char *int_end,
 		 CHARSET_INFO *cs);
-bool field_types_to_be_kept(enum_field_types field_type);
 
 /*
   The following are for the interface with the .frm file

--- 1.194/sql/item.cc	Tue Mar 15 15:15:43 2005
+++ 1.195/sql/item.cc	Wed Mar 23 08:36:42 2005
@@ -1700,10 +1700,10 @@
   case MYSQL_TYPE_NULL:
     return new Field_null((char*) 0, max_length, Field::NONE,
 			  name, table, &my_charset_bin);
-  case MYSQL_TYPE_NEWDATE:
   case MYSQL_TYPE_INT24:
     return new Field_medium((char*) 0, max_length, null_ptr, 0, Field::NONE,
 			    name, table, 0, unsigned_flag);
+  case MYSQL_TYPE_NEWDATE:
   case MYSQL_TYPE_DATE:
     return new Field_date(maybe_null, name, table, &my_charset_bin);
   case MYSQL_TYPE_TIME:
@@ -2701,203 +2701,267 @@
 }
 
 
-/*
-  Returns field for temporary table dependind on item type
-
-  SYNOPSIS
-    get_holder_example_field()
-    thd            - thread handler
-    item           - pointer to item
-    table          - empty table object
-
-  NOTE
-    It is possible to return field for Item_func 
-    items only if field type of this item is 
-    date or time or datetime type.
-    also see function field_types_to_be_kept() from
-    field.cc
-
-  RETURN
-    # - field
-    0 - no field
-*/
-
-Field *get_holder_example_field(THD *thd, Item *item, TABLE *table)
-{
-  DBUG_ASSERT(table);
-
-  Item_func *tmp_item= 0;
-  if (item->type() == Item::FIELD_ITEM)
-    return (((Item_field*) item)->field);
-  if (item->type() == Item::FUNC_ITEM)
-    tmp_item= (Item_func *) item;
-  else if (item->type() == Item::SUM_FUNC_ITEM)
-  {
-    Item_sum *item_sum= (Item_sum *) item;
-    if (item_sum->keep_field_type())
-    {
-      if (item_sum->args[0]->type() == Item::FIELD_ITEM)
-        return (((Item_field*) item_sum->args[0])->field);
-      if (item_sum->args[0]->type() == Item::FUNC_ITEM)
-        tmp_item= (Item_func *) item_sum->args[0];
-    }
-  }
-  return (tmp_item && field_types_to_be_kept(tmp_item->field_type()) ?
-          tmp_item->tmp_table_field(table) : 0);
-}
-
-
-Item_type_holder::Item_type_holder(THD *thd, Item *item, TABLE *table)
-  :Item(thd, item), item_type(item->result_type()),
-   orig_type(item_type)
+Item_type_holder::Item_type_holder(THD *thd, Item *item)
+  :Item(thd, item), enum_set_typelib(0), fld_type(get_real_type(item))
 {
   DBUG_ASSERT(item->fixed);
 
-  /*
-    It is safe assign pointer on field, because it will be used just after
-    all JOIN::prepare calls and before any SELECT execution
-  */
-  field_example= get_holder_example_field(thd, item, table);
-  max_length= real_length(item);
+  max_length= display_length(item);
   maybe_null= item->maybe_null;
   collation.set(item->collation);
+  get_full_info(item);
 }
 
 
 /*
-  STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT
+  Return expression type of Item_type_holder
+
+  SYNOPSIS
+    Item_type_holder::result_type()
 
-  ROW_RESULT should never appear in Item_type_holder::join_types,
-  but it is included in following table just to make table full
-  (there DBUG_ASSERT in function to catch ROW_RESULT)
+  RETURN
+     Item_result (type of internal MySQL expression result)
 */
-static Item_result type_convertor[4][4]=
-{{STRING_RESULT, STRING_RESULT, STRING_RESULT, ROW_RESULT},
- {STRING_RESULT, REAL_RESULT,   REAL_RESULT,   ROW_RESULT},
- {STRING_RESULT, REAL_RESULT,   INT_RESULT,    ROW_RESULT},
- {ROW_RESULT,    ROW_RESULT,    ROW_RESULT,    ROW_RESULT}};
+
+Item_result Item_type_holder::result_type() const
+{
+  return Field::result_merge_type(fld_type);
+}
 
 
 /*
-  Values of 'from' field can be stored in 'to' field.
+  Find real field type of item
 
   SYNOPSIS
-    is_attr_compatible()
-    from        Item which values should be saved
-    to          Item where values should be saved
+    Item_type_holder::get_real_type()
 
   RETURN
-    1   can be saved
-    0   can not be saved
+    type of field which should be created to store item value
 */
 
-inline bool is_attr_compatible(Item *from, Item *to)
-{
-  return ((to->max_length >= from->max_length) &&
-          (to->maybe_null || !from->maybe_null) &&
-          (to->result_type() != STRING_RESULT ||
-           from->result_type() != STRING_RESULT ||
-          (from->collation.collation == to->collation.collation)));
-}
-
-
-bool Item_type_holder::join_types(THD *thd, Item *item, TABLE *table)
+enum_field_types Item_type_holder::get_real_type(Item *item)
 {
-  uint32 new_length= real_length(item);
-  bool use_new_field= 0, use_expression_type= 0;
-  Item_result new_result_type= type_convertor[item_type][item->result_type()];
-  Field *field= get_holder_example_field(thd, item, table);
-  bool item_is_a_field= (field != NULL);
-  /*
-    Check if both items point to fields: in this case we
-    can adjust column types of result table in the union smartly.
-  */
-  if (field_example && item_is_a_field)
+  switch(item->type())
   {
-    /* Can 'field_example' field store data of the column? */
-    if ((use_new_field=
-         (!field->field_cast_compatible(field_example->field_cast_type()) ||
-          !is_attr_compatible(item, this))))
-    {
-      /*
-        The old field can't store value of the new field.
-        Check if the new field can store value of the old one.
-      */
-      use_expression_type|=
-        (!field_example->field_cast_compatible(field->field_cast_type()) ||
-         !is_attr_compatible(this, item));
-    }
+  case FIELD_ITEM:
+  {
+    /*
+      Item_fields::field_type ask Field_type() but sometimes field return
+      a different type, like for enum/set, so we need to ask real type.
+    */
+    Field *field= ((Item_field *) item)->field;
+    enum_field_types type= field->real_type();
+    /* work around about varchar type field detection */
+    if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING)
+      return MYSQL_TYPE_VAR_STRING;
+    return type;
   }
-  else if (field_example || item_is_a_field)
+  case SUM_FUNC_ITEM:
   {
     /*
-      Expression types can't be mixed with field types, we have to use
-      expression types.
+      Argument of aggregate function sometimes should be asked about field
+      type
     */
-    use_new_field= 1;                           // make next if test easier
-    use_expression_type= 1;
+    Item_sum *item_sum= (Item_sum *) item;
+    if (item_sum->keep_field_type())
+      return get_real_type(item_sum->args[0]);
+    break;
   }
-
-  /* Check whether size/type of the result item should be changed */
-  if (use_new_field ||
-      (new_result_type != item_type) || (new_length > max_length) ||
-      (!maybe_null && item->maybe_null) ||
-      (item_type == STRING_RESULT && 
-       collation.collation != item->collation.collation))
-  {
-    const char *old_cs,*old_derivation;
-    if (use_expression_type || !item_is_a_field)
-      field_example= 0;
-    else
+  case FUNC_ITEM:
+    if (((Item_func *) item)->functype() == Item_func::VAR_VALUE_FUNC)
     {
       /*
-        It is safe to assign a pointer to field here, because it will be used
-        before any table is closed.
+        There are work around of problem with changing variable type on the
+        fly and variable always report "string" as field type to get
+        acceptable information for client in send_field, so we make field
+        type from expression type.
       */
-      field_example= field;
+      switch (item->result_type())
+      {
+      case STRING_RESULT:
+        return MYSQL_TYPE_VAR_STRING;
+      case INT_RESULT:
+        return MYSQL_TYPE_LONGLONG;
+      case REAL_RESULT:
+        return MYSQL_TYPE_DOUBLE;
+      case ROW_RESULT:
+      default:
+        DBUG_ASSERT(0);
+        return MYSQL_TYPE_VAR_STRING;
+      }
     }
+    break;
+  default:
+    break;
+  }
+  return item->field_type();
+}
+
+/*
+  Find field type which can carry current Item_type_holder type and
+  type of given Item.
+
+  SYNOPSIS
+    Item_type_holder::join_types()
+    thd     thread handler
+    item    given item to join its parameters with this item ones
 
+  RETURN
+    TRUE   error - types are incompatible
+    FALSE  OK
+*/
+
+bool Item_type_holder::join_types(THD *thd, Item *item)
+{
+  max_length= max(max_length, display_length(item));
+  fld_type= Field::field_type_merge(fld_type, get_real_type(item));
+  if (Field::result_merge_type(fld_type) == STRING_RESULT)
+  {
+    const char *old_cs, *old_derivation;
     old_cs= collation.collation->name;
     old_derivation= collation.derivation_name();
-    if (item_type == STRING_RESULT && collation.aggregate(item->collation))
+    if (collation.aggregate(item->collation))
     {
       my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
 	       old_cs, old_derivation,
 	       item->collation.collation->name,
 	       item->collation.derivation_name(),
 	       "UNION");
-      return 1;
+      return TRUE;
     }
-
-    max_length= max(max_length, new_length);
-    decimals= max(decimals, item->decimals);
-    maybe_null|= item->maybe_null;
-    item_type= new_result_type;
   }
-  DBUG_ASSERT(item_type != ROW_RESULT);
-  return 0;
+  decimals= max(decimals, item->decimals);
+  maybe_null|= item->maybe_null;
+  get_full_info(item);
+  return FALSE;
 }
 
+/*
+  Calculate lenth for merging result for given Item type
+
+  SYNOPSIS
+    Item_type_holder::real_length()
+    item  Item for lrngth detection
 
-uint32 Item_type_holder::real_length(Item *item)
+  RETURN
+    length
+*/
+
+uint32 Item_type_holder::display_length(Item *item)
 {
   if (item->type() == Item::FIELD_ITEM)
     return ((Item_field *)item)->max_disp_length();
 
-  switch (item->result_type())
+  switch (item->field_type())
   {
-  case STRING_RESULT:
+  case MYSQL_TYPE_DECIMAL:
+  case MYSQL_TYPE_TIMESTAMP:
+  case MYSQL_TYPE_DATE:
+  case MYSQL_TYPE_TIME:
+  case MYSQL_TYPE_DATETIME:
+  case MYSQL_TYPE_YEAR:
+  case MYSQL_TYPE_NEWDATE:
+  case MYSQL_TYPE_ENUM:
+  case MYSQL_TYPE_SET:
+  case MYSQL_TYPE_TINY_BLOB:
+  case MYSQL_TYPE_MEDIUM_BLOB:
+  case MYSQL_TYPE_LONG_BLOB:
+  case MYSQL_TYPE_BLOB:
+  case MYSQL_TYPE_VAR_STRING:
+  case MYSQL_TYPE_STRING:
+  case MYSQL_TYPE_GEOMETRY:
     return item->max_length;
-  case REAL_RESULT:
+  case MYSQL_TYPE_TINY:
+    return 4;
+  case MYSQL_TYPE_SHORT:
+    return 6;
+  case MYSQL_TYPE_LONG:
+    return 11;
+  case MYSQL_TYPE_FLOAT:
+    return 25;
+  case MYSQL_TYPE_DOUBLE:
     return 53;
-  case INT_RESULT:
+  case MYSQL_TYPE_NULL:
+    return 4;
+  case MYSQL_TYPE_LONGLONG:
     return 20;
-  case ROW_RESULT:
+  case MYSQL_TYPE_INT24:
+    return 8;
   default:
     DBUG_ASSERT(0); // we should never go there
     return 0;
   }
 }
+
+
+/*
+  Make temporary table field according collected information about type
+  of UNION result
+
+  SYNOPSIS
+    Item_type_holder::make_field_by_type()
+    table  temporary table for which we create fields
+
+  RETURN
+    created field
+*/
+
+Field *Item_type_holder::make_field_by_type(TABLE *table)
+{
+  if (fld_type == MYSQL_TYPE_ENUM || fld_type == MYSQL_TYPE_SET)
+  {
+    DBUG_ASSERT(enum_set_typelib);
+    /*
+      The field functions defines a field to be not null if null_ptr is not 0
+    */
+    uchar *null_ptr= maybe_null ? (uchar*) "" : 0;
+
+    if (fld_type == MYSQL_TYPE_ENUM)
+      return new Field_enum((char *) 0, max_length, null_ptr, 0,
+		 Field::NONE, name,
+		 table, get_enum_pack_length(enum_set_typelib->count),
+		 enum_set_typelib, collation.collation);
+    else
+      return new Field_set((char *) 0, max_length, null_ptr, 0,
+		 Field::NONE, name,
+		 table, get_set_pack_length(enum_set_typelib->count),
+		 enum_set_typelib, collation.collation);
+  }
+  return tmp_table_field_from_field_type(table);
+}
+
+
+/*
+  Get full information from Item about enum/set fields to be able to create
+  them later
+
+  SYNOPSIS
+    Item_type_holder::get_full_info
+    item    Item for information collection
+*/
+void Item_type_holder::get_full_info(Item *item)
+{
+  if (fld_type == MYSQL_TYPE_ENUM ||
+      fld_type == MYSQL_TYPE_SET)
+  {
+    /*
+      We can have enum/set type after merging only if we have one enum/set
+      field and number of NULL fields
+    */
+    DBUG_ASSERT((enum_set_typelib &&
+                 get_real_type(item) == MYSQL_TYPE_NULL) ||
+                (!enum_set_typelib &&
+                 item->type() == Item::FIELD_ITEM &&
+                 (get_real_type(item) == MYSQL_TYPE_ENUM ||
+                  get_real_type(item) == MYSQL_TYPE_SET) &&
+                 ((Field_enum*)((Item_field *) item)->field)->typelib));
+    if (!enum_set_typelib)
+    {
+      enum_set_typelib= ((Field_enum*)((Item_field *) item)->field)->typelib;
+    }
+  }
+}
+
 
 double Item_type_holder::val()
 {

--- 1.173/sql/item.h	Wed Mar 16 15:44:22 2005
+++ 1.174/sql/item.h	Wed Mar 23 08:36:42 2005
@@ -1321,32 +1321,32 @@
 
 
 /*
-  Used to store type. name, length of Item for UNIONS & derived table
+  Item_type_holder used to store type. name, length of Item for UNIONS &
+  derived tables.
+
+  Item_type_holder do not need cleanup() because its time of live limited by
+  single SP/PS execution.
 */
 class Item_type_holder: public Item
 {
 protected:
-  Item_result item_type;
-  Item_result orig_type;
-  Field *field_example;
+  TYPELIB *enum_set_typelib;
+  enum_field_types fld_type;
+
+  void get_full_info(Item *item);
 public:
-  Item_type_holder(THD*, Item*, TABLE *);
+  Item_type_holder(THD*, Item*);
 
-  Item_result result_type () const { return item_type; }
+  Item_result result_type() const;
+  virtual enum_field_types field_type() const { return fld_type; };
   enum Type type() const { return TYPE_HOLDER; }
   double val();
   longlong val_int();
   String *val_str(String*);
-  bool join_types(THD *thd, Item *, TABLE *);
-  Field *example() { return field_example; }
-  static uint32 real_length(Item *item);
-  void cleanup()
-  {
-    DBUG_ENTER("Item_type_holder::cleanup");
-    Item::cleanup();
-    item_type= orig_type;
-    DBUG_VOID_RETURN;
-  }
+  bool join_types(THD *thd, Item *);
+  Field *make_field_by_type(TABLE *table);
+  static uint32 display_length(Item *item);
+  static enum_field_types get_real_type(Item *);
 };
 
 

--- 1.119/sql/item_func.h	Tue Feb 22 12:51:19 2005
+++ 1.120/sql/item_func.h	Wed Mar 23 08:36:42 2005
@@ -51,7 +51,7 @@
 		  SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC,
 		  SP_STARTPOINT,SP_ENDPOINT,SP_EXTERIORRING,
 		  SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN,
-		  NOT_FUNC, NOT_ALL_FUNC, NOW_FUNC};
+		  NOT_FUNC, NOT_ALL_FUNC, NOW_FUNC, VAR_VALUE_FUNC};
   enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL };
   enum Type type() const { return FUNC_ITEM; }
   virtual enum Functype functype() const   { return UNKNOWN_FUNC; }
@@ -980,6 +980,7 @@
     select @t1:=1,@t1,@t:="hello",@t from foo where (@t1:= t2.b)
   */
   enum_field_types field_type() const  { return MYSQL_TYPE_STRING; }
+  enum Functype functype() const   { return VAR_VALUE_FUNC; }
   const char *func_name() const { return "get_user_var"; }
   bool const_item() const;
   table_map used_tables() const

--- 1.183/sql/sql_lex.h	Mon Feb 28 11:59:41 2005
+++ 1.184/sql/sql_lex.h	Wed Mar 23 08:36:42 2005
@@ -389,7 +389,8 @@
   void exclude_tree();
 
   /* UNION methods */
-  int prepare(THD *thd, select_result *result, ulong additional_options);
+  int prepare(THD *thd, select_result *result, ulong additional_options,
+              const char *tmp_table_alias);
   int exec();
   int cleanup();
   inline void unclean() { cleaned= 0; }

--- 1.428/sql/sql_parse.cc	Mon Mar 14 16:58:22 2005
+++ 1.429/sql/sql_parse.cc	Wed Mar 23 08:36:42 2005
@@ -4539,9 +4539,7 @@
         net_printf(thd,ER_TOO_BIG_SET,field_name); /* purecov: inspected */
         DBUG_RETURN(1);				/* purecov: inspected */
       }
-      new_field->pack_length= (interval_list->elements + 7) / 8;
-      if (new_field->pack_length > 4)
-        new_field->pack_length=8;
+      new_field->pack_length= get_set_pack_length(interval_list->elements);
 
       List_iterator<String> it(*interval_list);
       String *tmp;
@@ -4558,7 +4556,7 @@
   case FIELD_TYPE_ENUM:
     {
       // Should be safe
-      new_field->pack_length= interval_list->elements < 256 ? 1 : 2; 
+      new_field->pack_length= get_enum_pack_length(interval_list->elements);
 
       List_iterator<String> it(*interval_list);
       String *tmp;

--- 1.385/sql/sql_select.cc	Tue Mar  8 20:45:49 2005
+++ 1.386/sql/sql_select.cc	Wed Mar 23 08:36:42 2005
@@ -4836,14 +4836,7 @@
     return create_tmp_field_from_item(thd, item, table, copy_func, modify_item,
                                       convert_blob_length);
   case Item::TYPE_HOLDER:
-  {
-    Field *example= ((Item_type_holder *)item)->example();
-    if (example)
-      return create_tmp_field_from_field(thd, example, item, table, 0,
-                                         convert_blob_length);
-    return create_tmp_field_from_item(thd, item, table, copy_func, 0,
-                                      convert_blob_length);
-  }
+    return ((Item_type_holder *)item)->make_field_by_type(table);
   default:					// Dosen't have to be stored
     return 0;
   }
@@ -5340,8 +5333,6 @@
     if (create_myisam_tmp_table(table,param,select_options))
       goto err;
   }
-  /* Set table_name for easier debugging */
-  table->table_name= base_name(tmpname);
   if (!open_tmp_table(table))
     DBUG_RETURN(table);
 
@@ -9525,7 +9516,8 @@
     unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization
     unit->fake_select_lex->type= "UNION RESULT";
     unit->fake_select_lex->options|= SELECT_DESCRIBE;
-    if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
+    if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE,
+                             "")))
       res= unit->exec();
     res|= unit->cleanup();
   }

--- 1.86/mysql-test/r/union.result	Mon Feb 14 00:35:36 2005
+++ 1.87/mysql-test/r/union.result	Wed Mar 23 08:36:41 2005
@@ -655,7 +655,7 @@
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `f` binary(24) default NULL
+  `f` varbinary(24) default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 drop table t1;
 create table t1 SELECT y from t2 UNION select da from t2;
@@ -666,7 +666,7 @@
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `y` binary(10) default NULL
+  `y` varbinary(10) default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 drop table t1;
 create table t1 SELECT y from t2 UNION select dt from t2;
@@ -677,7 +677,7 @@
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `y` binary(19) default NULL
+  `y` varbinary(19) default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 drop table t1;
 create table t1 SELECT da from t2 UNION select dt from t2;
@@ -699,7 +699,7 @@
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `dt` binary(19) default NULL
+  `dt` varbinary(19) default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 drop table t1;
 create table t1 SELECT dt from t2 UNION select sv from t2;
@@ -710,7 +710,7 @@
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `dt` binary(19) default NULL
+  `dt` varbinary(19) default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 drop table t1;
 create table t1 SELECT sc from t2 UNION select sv from t2;
@@ -732,7 +732,7 @@
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `dt` blob
+  `dt` longblob
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 drop table t1;
 create table t1 SELECT sv from t2 UNION select b from t2;
@@ -755,7 +755,7 @@
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `i` blob
+  `i` longblob
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 drop table t1;
 create table t1 SELECT sv from t2 UNION select tx from t2;
@@ -766,7 +766,7 @@
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `sv` text
+  `sv` longtext
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 drop table t1;
 create table t1 SELECT b from t2 UNION select tx from t2;
@@ -1069,7 +1069,7 @@
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `_latin1'test' collate latin1_bin` char(4) character set latin1 collate latin1_bin NOT
NULL default ''
+  `_latin1'test' collate latin1_bin` varchar(4) character set latin1 collate latin1_bin
NOT NULL default ''
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 select count(*) from t1;
 count(*)
@@ -1082,7 +1082,7 @@
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `test` char(4) character set latin1 collate latin1_bin NOT NULL default ''
+  `test` varchar(4) character set latin1 collate latin1_bin NOT NULL default ''
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 select count(*) from t1;
 count(*)
@@ -1095,7 +1095,7 @@
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `test` char(4) character set latin1 collate latin1_bin NOT NULL default ''
+  `test` varchar(4) character set latin1 collate latin1_bin NOT NULL default ''
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 select count(*) from t1;
 count(*)
@@ -1195,3 +1195,38 @@
 2	b
 3	c
 drop table t1;
+CREATE TABLE t1 (
+a ENUM('ä','ö','ü') character set utf8 not null default 'ü',
+b ENUM("one", "two") character set utf8,
+c ENUM("one", "two")
+);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` enum('ä','ö','ü') character set utf8 NOT NULL default 'ü',
+  `b` enum('one','two') character set utf8 default NULL,
+  `c` enum('one','two') default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('ä', 'one', 'one'), ('ö', 'two', 'one'), ('ü', NULL, NULL);
+create table t2 select NULL union select a from t1;
+show columns from t2;
+Field	Type	Null	Key	Default	Extra
+NULL	enum('ä','ö','ü')	YES		NULL	
+drop table t2;
+create table t2 select a from t1 union select NULL;
+show columns from t2;
+Field	Type	Null	Key	Default	Extra
+a	enum('ä','ö','ü')	YES		NULL	
+drop table t2;
+create table t2 select a from t1 union select a from t1;
+show columns from t2;
+Field	Type	Null	Key	Default	Extra
+a	char(1)				
+drop table t2;
+create table t2 select a from t1 union select c from t1;
+ERROR HY000: Illegal mix of collations (utf8_general_ci,IMPLICIT) and
(latin1_swedish_ci,IMPLICIT) for operation 'UNION'
+create table t2 select a from t1 union select b from t1;
+show columns from t2;
+Field	Type	Null	Key	Default	Extra
+a	varchar(3)	YES		NULL	
+drop table t2, t1;

--- 1.80/mysql-test/t/union.test	Mon Feb 14 00:35:36 2005
+++ 1.81/mysql-test/t/union.test	Wed Mar 23 08:36:42 2005
@@ -711,3 +711,28 @@
 select * from ((((select * from t1))) union (select * from t1) union (select * from t1))
a;
 select * from ((select * from t1) union (((select * from t1))) union (select * from t1))
a;
 drop table t1;
+
+#
+# Enum merging test
+#
+CREATE TABLE t1 (
+  a ENUM('ä','ö','ü') character set utf8 not null default 'ü',
+  b ENUM("one", "two") character set utf8,
+  c ENUM("one", "two")
+);
+show create table t1;
+insert into t1 values ('ä', 'one', 'one'), ('ö', 'two', 'one'), ('ü', NULL, NULL);
+create table t2 select NULL union select a from t1;
+show columns from t2;
+drop table t2;
+create table t2 select a from t1 union select NULL;
+show columns from t2;
+drop table t2;
+create table t2 select a from t1 union select a from t1;
+show columns from t2;
+drop table t2;
+-- error 1267
+create table t2 select a from t1 union select c from t1;
+create table t2 select a from t1 union select b from t1;
+show columns from t2;
+drop table t2, t1;

--- 1.78/sql/sql_derived.cc	Mon Feb 14 02:05:39 2005
+++ 1.79/sql/sql_derived.cc	Wed Mar 23 08:36:42 2005
@@ -123,7 +123,7 @@
     DBUG_RETURN(1); // out of memory
 
   // st_select_lex_unit::prepare correctly work for single select
-  if ((res= unit->prepare(thd, derived_result, 0)))
+  if ((res= unit->prepare(thd, derived_result, 0, org_table_list->alias)))
     goto exit;
 
 	
@@ -161,7 +161,7 @@
     if (is_union)
     {
       // execute union without clean up
-      if (!(res= unit->prepare(thd, derived_result, SELECT_NO_UNLOCK)))
+      if (!(res= unit->prepare(thd, derived_result, SELECT_NO_UNLOCK, "")))
 	res= unit->exec();
     }
     else

--- 1.139/sql/sql_union.cc	Wed Mar  2 18:00:43 2005
+++ 1.140/sql/sql_union.cc	Wed Mar 23 08:36:42 2005
@@ -29,7 +29,7 @@
 {
   DBUG_ENTER("mysql_union");
   int res= 0;
-  if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK)))
+  if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK, "")))
     res= unit->exec();
   res|= unit->cleanup();
   DBUG_RETURN(res);
@@ -142,7 +142,8 @@
 
 
 int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
-				ulong additional_options)
+				ulong additional_options,
+                                const char *tmp_table_alias)
 {
   SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
   SELECT_LEX *sl, *first_select;
@@ -252,7 +253,7 @@
       while ((item_tmp= it++))
       {
 	/* Error's in 'new' will be detected after loop */
-	types.push_back(new Item_type_holder(thd_arg, item_tmp, empty_table));
+	types.push_back(new Item_type_holder(thd_arg, item_tmp));
       }
 
       if (thd_arg->is_fatal_error)
@@ -271,8 +272,7 @@
       Item *type, *item_tmp;
       while ((type= tp++, item_tmp= it++))
       {
-        if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp,
-                                                  empty_table))
+        if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
 	  DBUG_RETURN(-1);
       }
     }
@@ -304,7 +304,7 @@
 				  (first_select_in_union()->options |
 				   thd_arg->options |
 				   TMP_TABLE_ALL_COLUMNS),
-				  HA_POS_ERROR, (char*) "")))
+				  HA_POS_ERROR, (char *) tmp_table_alias)))
       goto err;
     table->file->extra(HA_EXTRA_WRITE_CACHE);
     table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);

--- 1.129/sql/item_subselect.cc	Thu Mar 10 14:00:30 2005
+++ 1.130/sql/item_subselect.cc	Wed Mar 23 08:36:42 2005
@@ -1235,7 +1235,7 @@
 
 int subselect_union_engine::prepare()
 {
-  return unit->prepare(thd, result, SELECT_NO_UNLOCK);
+  return unit->prepare(thd, result, SELECT_NO_UNLOCK, "");
 }
 
 int subselect_uniquesubquery_engine::prepare()

--- 1.37/mysql-test/r/func_group.result	Sat Mar  5 06:18:40 2005
+++ 1.38/mysql-test/r/func_group.result	Wed Mar 23 08:36:41 2005
@@ -747,7 +747,7 @@
 create table t2 select f2 from (select max(now()) f2 from t1) a;
 show columns from t2;
 Field	Type	Null	Key	Default	Extra
-f2	datetime			0000-00-00 00:00:00	
+f2	datetime	YES		NULL	
 drop table t2;
 create table t2 select f2 from (select now() f2 from t1) a;
 show columns from t2;

--- 1.6/mysql-test/r/metadata.result	Tue Jan 18 15:41:02 2005
+++ 1.7/mysql-test/r/metadata.result	Wed Mar 23 08:36:41 2005
@@ -55,8 +55,33 @@
 2	female	no
 select t1.id from t1 union select t2.id from t2;
 Catalog	Database	Table	Table_alias	Column	Column_alias	Name	Type	Length	Max
length	Is_null	Flags	Decimals	Charsetnr
-def	test	t1	t1	id	id	1	3	1	Y	32768	0	63
+def				id	id	1	4	1	Y	32768	0	63
 id
 1
 2
 drop table t1,t2;
+create table t1 ( a int, b varchar(30), primary key(a));
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1 union distinct select 1 FROM t1 where a=1;
+Catalog	Database	Table	Table_alias	Column	Column_alias	Name	Type	Length	Max
length	Is_null	Flags	Decimals	Charsetnr
+def				@arg00	@arg00	8	20	1	Y	32768	0	63
+@arg00
+1
+select * from (select @arg00) aaa;
+Catalog	Database	Table	Table_alias	Column	Column_alias	Name	Type	Length	Max
length	Is_null	Flags	Decimals	Charsetnr
+def			aaa	@arg00	@arg00	8	20	1	Y	32768	0	63
+@arg00
+1
+select 1 union select 1;
+Catalog	Database	Table	Table_alias	Column	Column_alias	Name	Type	Length	Max
length	Is_null	Flags	Decimals	Charsetnr
+def				1	1	8	20	1	N	32769	0	63
+1
+1
+select * from (select 1 union select 1) aaa;
+Catalog	Database	Table	Table_alias	Column	Column_alias	Name	Type	Length	Max
length	Is_null	Flags	Decimals	Charsetnr
+def			aaa	1	1	8	20	1	N	32769	0	63
+1
+1
+drop table t1;

--- 1.2/mysql-test/t/metadata.test	Tue Oct 26 19:29:54 2004
+++ 1.3/mysql-test/t/metadata.test	Wed Mar 23 08:36:41 2005
@@ -34,4 +34,17 @@
 select t1.id from t1 union select t2.id from t2;
 drop table t1,t2;
 
+#
+# variables union and derived tables metadata test
+#
+create table t1 ( a int, b varchar(30), primary key(a));
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1 union distinct select 1 FROM t1 where a=1;
+select * from (select @arg00) aaa;
+select 1 union select 1;
+select * from (select 1 union select 1) aaa;
+drop table t1;
+
 --disable_metadata

--- 1.144/sql/sql_prepare.cc	Fri Jan 14 00:09:12 2005
+++ 1.145/sql/sql_prepare.cc	Wed Mar 23 08:36:42 2005
@@ -1079,7 +1079,7 @@
   thd->used_tables= 0;                        // Updated by setup_fields
 
   // JOIN::prepare calls
-  if (unit->prepare(thd, 0, 0))
+  if (unit->prepare(thd, 0, 0, ""))
   {
     send_error(thd);
     goto err_prep;
@@ -1228,7 +1228,7 @@
   thd->used_tables= 0;                        // Updated by setup_fields
 
   // JOIN::prepare calls
-  if (lex->unit.prepare(thd, 0, 0))
+  if (lex->unit.prepare(thd, 0, 0, ""))
   {
     res= thd->net.report_error ? -1 : 1;
   }
Thread
bk commit into 4.1 tree (bell:1.2129) BUG#8824sanja23 Mar