/*
 *	PROGRAM:	JRD Access Method
 *	MODULE:		dsc.cpp
 *	DESCRIPTION:	Utility routines for working with data descriptors
 *
 *	Note: This module is used by both engine & utility functions.
 *
 * The contents of this file are subject to the Interbase Public
 * License Version 1.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy
 * of the License at http://www.Inprise.com/IPL.html
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code was created by Inprise Corporation
 * and its predecessors. Portions created by Inprise Corporation are
 * Copyright (C) Inprise Corporation.
 *
 * All Rights Reserved.
 * Contributor(s): ______________________________________.
 */

#include "firebird.h"
#include <string.h>
#include <stdlib.h>
#include "../common/dsc.h"
#include "../common/TimeZoneUtil.h"
#include "ibase.h"
#include "../jrd/intl.h"
#include "../yvalve/gds_proto.h"
#include "../common/gdsassert.h"
#include "../common/dsc_proto.h"
#include "../common/StatusArg.h"

using namespace Firebird;


// When converting non-text values to text, how many bytes to allocate
// for holding the text image of the value.

static const USHORT _DSC_convert_to_text_length[DTYPE_TYPE_MAX] =
{
	0,							// dtype_unknown
	0,							// dtype_text
	0,							// dtype_cstring
	0,							// dtype_varying
	0,
	0,
	0,							// dtype_packed
	0,							// dtype_byte
	6,							// dtype_short      -32768
	11,							// dtype_long       -2147483648
	20,							// dtype_quad       -9223372036854775808
	15,							// dtype_real       -1.23456789e+12
	24,							// dtype_double     -1.2345678901234567e+123
	24,							// dtype_d_float (believed to have this range)  -1.2345678901234567e+123
	10,							// dtype_sql_date   YYYY-MM-DD
	13,							// dtype_sql_time   HH:MM:SS.MMMM
	25,							// dtype_timestamp  YYYY-MM-DD HH:MM:SS.MMMM
	//  -- in BLR_version4  DD-Mon-YYYY HH:MM:SS.MMMM
	9,							// dtype_blob       FFFF:FFFF
	9,							// dtype_array      FFFF:FFFF
	20,							// dtype_int64      -9223372036854775808
	8,							// dtype_dbkey
	5,							// dtype_boolean
	23,							// dtype_dec64		1 + 1 + 1 + 1 + 16(34) + 3(4)
	42,							// dtype_dec128		+-  .   e   +-  coeff  + exp
	47,							// dtype_int128
	14 + TimeZoneUtil::MAX_LEN,	// dtype_sql_time_tz      HH:MM:SS.MMMM +NN:NN
	25 + TimeZoneUtil::MAX_LEN,	// dtype_timestamp_tz     YYYY-MM-DD HH:MM:SS.MMMM +NN:NN
	14 + TimeZoneUtil::MAX_LEN,	// dtype_ex_time_tz       HH:MM:SS.MMMM +NN:NN
	25 + TimeZoneUtil::MAX_LEN	// dtype_ex_timestamp_tz  YYYY-MM-DD HH:MM:SS.MMMM +NN:NN
};

// Unimplemented names are in lowercase & <brackets>
// Datatypes that represent a range of SQL datatypes are in lowercase
static const TEXT* const DSC_dtype_names[] =
{
	"<dtype_unknown>",
	"CHAR",
	"CSTRING",
	"VARCHAR",
	"<dtype_4>",
	"<dtype_5>",
	"<packed>",
	"<byte>",
	"SMALLINT",					// Also DECIMAL & NUMERIC
	"INTEGER",					// Also DECIMAL & NUMERIC
	"<quad>",
	"FLOAT",
	"DOUBLE PRECISION",
	"<d_float>",
	"DATE",
	"TIME",
	"TIMESTAMP",
	"BLOB",
	"ARRAY",
	"BIGINT",
	"DB_KEY",
	"BOOLEAN",
	"DECFLOAT(16)",
	"DECFLOAT(34)",
	"INT128",
	"TIME WITH TIME ZONE",
	"TIMESTAMP WITH TIME ZONE"
};


// The result of adding two datatypes in blr_version5 semantics
// Note: DTYPE_CANNOT as the result means that the operation cannot be done.
// dtype_unknown as the result means that we do not yet know the type of one of
// the operands, so we cannot decide the type of the result.

const BYTE DSC_add_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
{

	/*
	dtype_unknown		dtype_text			dtype_cstring		dtype_varying
	4 (unused)			5 (unused)			dtype_packed		dtype_byte
	dtype_short			dtype_long			dtype_quad			dtype_real
	dtype_double		dtype_d_float		dtype_sql_date		dtype_sql_time
	dtype_timestamp		dtype_blob			dtype_array			dtype_int64
	dtype_dbkey			dtype_boolean		dtype_dec64			dtype_dec128
	dtype_int128 		dtype_sql_time_tz	dtype_timestamp_tz	dtype_ex_time_tz
	dtype_ex_timestamp_tz
	*/

	// dtype_unknown
	{dtype_unknown, dtype_unknown, dtype_unknown, dtype_unknown,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_unknown, dtype_unknown, DTYPE_CANNOT, dtype_unknown,
	 dtype_unknown, dtype_unknown, dtype_unknown, dtype_unknown,
	 dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown, dtype_unknown,
	 dtype_unknown, dtype_unknown, dtype_unknown, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_text
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_cstring
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_varying
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// 4 (unused)
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// 5 (unused)
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_packed
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_byte
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_short
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec64, dtype_dec128,
	 dtype_int128, dtype_sql_time_tz, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_long
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec64, dtype_dec128,
	 dtype_int128, dtype_sql_time_tz, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_quad
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_real
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec64, dtype_dec128,
	 dtype_double, dtype_sql_time_tz, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_double
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec64, dtype_dec128,
	 dtype_double, dtype_sql_time_tz, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_d_float -- VMS deprecated
	{dtype_unknown, dtype_d_float, dtype_d_float, dtype_d_float,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_d_float, dtype_d_float, DTYPE_CANNOT, dtype_d_float,
	 dtype_d_float, dtype_d_float, dtype_sql_date, dtype_sql_time,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec64, dtype_dec128,
	 dtype_d_float, dtype_sql_time_tz, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_date
	{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_sql_date, dtype_sql_date, DTYPE_CANNOT, dtype_sql_date,
	 dtype_sql_date, dtype_sql_date, DTYPE_CANNOT, dtype_timestamp,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_date,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_date, dtype_sql_date,
	 dtype_sql_date, dtype_timestamp_tz, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_time
	{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_sql_time, dtype_sql_time, DTYPE_CANNOT, dtype_sql_time,
	 dtype_sql_time, dtype_sql_time, dtype_timestamp, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time, dtype_sql_time,
	 dtype_sql_time, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_timestamp
	{dtype_unknown, dtype_timestamp, dtype_timestamp, dtype_timestamp,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_timestamp, dtype_timestamp, DTYPE_CANNOT, dtype_timestamp,
	 dtype_timestamp, dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp, dtype_timestamp,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_blob
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_array
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_int64
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, dtype_sql_time_tz, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dbkey
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_boolean
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dec64
	{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_dec64, dtype_dec64, DTYPE_CANNOT, dtype_dec64,
	 dtype_dec64, dtype_dec64, dtype_sql_date, dtype_sql_time,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec64, dtype_dec128,
	 dtype_dec128, dtype_sql_time_tz, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dec128
	{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_dec128,
	 dtype_dec128, dtype_dec128, dtype_sql_date, dtype_sql_time,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_dec128, dtype_sql_time_tz, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_int128
	{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int128, dtype_int128, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, dtype_sql_date, dtype_sql_time,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, dtype_sql_time_tz, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_time_tz
	{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_sql_time_tz, dtype_sql_time_tz, DTYPE_CANNOT, dtype_sql_time_tz,
	 dtype_sql_time_tz, dtype_sql_time_tz, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time_tz,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time_tz, dtype_sql_time_tz,
	 dtype_sql_time_tz, DTYPE_CANNOT, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_timestamp_tz
	{dtype_unknown, dtype_timestamp_tz, dtype_timestamp_tz, dtype_timestamp_tz,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_timestamp_tz, dtype_timestamp_tz, DTYPE_CANNOT, dtype_timestamp_tz,
	 dtype_timestamp_tz, dtype_timestamp_tz, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp_tz,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp_tz, dtype_timestamp_tz,
	 dtype_timestamp_tz, dtype_timestamp_tz, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_ex_time_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_ex_timestamp_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT}
};

/* The result of subtracting two datatypes in blr_version5 semantics
   Note: DTYPE_CANNOT as the result means that the operation cannot be done.
   dtype_unknown as the result means that we do not yet know the type of one of
   the operands, so we cannot decide the type of the result. */

const BYTE DSC_sub_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
{

	/*
	dtype_unknown		dtype_text			dtype_cstring		dtype_varying
	4 (unused)			5 (unused)			dtype_packed		dtype_byte
	dtype_short			dtype_long			dtype_quad			dtype_real
	dtype_double		dtype_d_float		dtype_sql_date		dtype_sql_time
	dtype_timestamp		dtype_blob			dtype_array			dtype_int64
	dtype_dbkey			dtype_boolean		dtype_dec64			dtype_dec128
	dtype_int128 		dtype_sql_time_tz	dtype_timestamp_tz	dtype_ex_time_tz
	dtype_ex_timestamp_tz
	*/

	// dtype_unknown
	{dtype_unknown, dtype_unknown, dtype_unknown, dtype_unknown,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_unknown, dtype_unknown, DTYPE_CANNOT, dtype_unknown,
	 dtype_unknown, dtype_unknown, dtype_unknown, dtype_unknown,
	 dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown, dtype_unknown,
	 dtype_unknown, dtype_unknown, dtype_unknown, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_text
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_cstring
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_varying
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, dtype_timestamp_tz, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// 4 (unused)
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// 5 (unused)
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_packed
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_byte
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_short
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_long
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_quad
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_real
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec64, dtype_dec128,
	 dtype_double, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_double
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec64, dtype_dec128,
	 dtype_double, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_d_float -- VMS deprecated
	{dtype_unknown, dtype_d_float, dtype_d_float, dtype_d_float,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_d_float, dtype_d_float, DTYPE_CANNOT, dtype_d_float,
	 dtype_d_float, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec64, dtype_dec128,
	 dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_date
	{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_sql_date, dtype_sql_date, DTYPE_CANNOT, dtype_sql_date,
	 dtype_sql_date, dtype_sql_date, dtype_long, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_date,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_date, dtype_sql_date,
	 dtype_sql_date, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_time
	{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_sql_time, dtype_sql_time, DTYPE_CANNOT, dtype_sql_time,
	 dtype_sql_time, dtype_sql_time, DTYPE_CANNOT, dtype_long,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time, dtype_sql_time,
	 dtype_sql_time, dtype_long, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_timestamp
	{dtype_unknown, dtype_timestamp, dtype_timestamp, dtype_timestamp,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_timestamp, dtype_timestamp, DTYPE_CANNOT, dtype_timestamp,
	 dtype_timestamp, dtype_timestamp, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp, dtype_timestamp,
	 dtype_timestamp, DTYPE_CANNOT, dtype_double, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_blob
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_array
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_int64
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int64,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec64, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dbkey
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_boolean
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dec64
	{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_dec64, dtype_dec64, DTYPE_CANNOT, dtype_dec64,
	 dtype_dec64, dtype_dec64, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec64, dtype_dec128,
	 dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dec128
	{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_dec128,
	 dtype_dec128, dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_int128
	{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int128, dtype_int128, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_time_tz
	{dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_sql_time_tz, dtype_sql_time_tz, DTYPE_CANNOT, dtype_sql_time_tz,
	 dtype_sql_time_tz, dtype_sql_time_tz, DTYPE_CANNOT, dtype_long,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time_tz,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_sql_time_tz, dtype_sql_time_tz,
	 dtype_sql_time_tz, dtype_long, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_timestamp_tz
	{dtype_unknown, dtype_timestamp_tz, dtype_timestamp_tz, dtype_timestamp_tz,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_timestamp_tz, dtype_timestamp_tz, DTYPE_CANNOT, dtype_timestamp_tz,
	 dtype_timestamp_tz, dtype_timestamp_tz, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp_tz,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_timestamp_tz, dtype_timestamp_tz,
	 dtype_timestamp_tz, DTYPE_CANNOT, dtype_double, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_ex_time_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_ex_timestamp_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT}
};


/* The result of multiplying or dividing two datatypes in blr_version5 semantics
   Note: DTYPE_CANNOT as the result means that the operation cannot be done.
   dtype_unknown as the result means that we do not yet know the type of one of
   the operands, so we cannot decide the type of the result. */

const BYTE DSC_multiply_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
{

	/*
	dtype_unknown		dtype_text			dtype_cstring		dtype_varying
	4 (unused)			5 (unused)			dtype_packed		dtype_byte
	dtype_short			dtype_long			dtype_quad			dtype_real
	dtype_double		dtype_d_float		dtype_sql_date		dtype_sql_time
	dtype_timestamp		dtype_blob			dtype_array			dtype_int64
	dtype_dbkey			dtype_boolean		dtype_dec64			dtype_dec128
	dtype_int128 		dtype_sql_time_tz	dtype_timestamp_tz	dtype_ex_time_tz
	dtype_ex_timestamp_tz
	*/

	// dtype_unknown
	{dtype_unknown, dtype_unknown, dtype_unknown, dtype_unknown,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_unknown, dtype_unknown, DTYPE_CANNOT, dtype_unknown,
	 dtype_unknown, dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown, dtype_unknown,
	 dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_text
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_cstring
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_varying
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// 4 (unused)
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// 5 (unused)
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_packed
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_byte
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_short
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_long
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int64, dtype_int64, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_quad
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_real
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_double, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_double
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_double, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_d_float -- VMS deprecated
	{dtype_unknown, dtype_d_float, dtype_d_float, dtype_d_float,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_d_float, dtype_d_float, DTYPE_CANNOT, dtype_d_float,
	 dtype_d_float, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_date
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_time
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_timestamp
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_blob
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_array
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_int64
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int128, dtype_int128, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dbkey
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_boolean
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dec64
	{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_dec128,
	 dtype_dec128, dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dec128
	{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_dec128,
	 dtype_dec128, dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_int128
	{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int128, dtype_int128, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_time_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_timestamp_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_ex_time_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_ex_timestamp_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT}
};

/* The result of multiplying two datatypes in blr_version4 semantics.
   Note: DTYPE_CANNOT as the result means that the operation cannot be done.
   dtype_unknown as the result means that we do not yet know the type of one of
   the operands, so we cannot decide the type of the result. */

const BYTE DSC_multiply_blr4_result[DTYPE_TYPE_MAX][DTYPE_TYPE_MAX] =
{

	/*
	dtype_unknown		dtype_text			dtype_cstring		dtype_varying
	4 (unused)			5 (unused)			dtype_packed		dtype_byte
	dtype_short			dtype_long			dtype_quad			dtype_real
	dtype_double		dtype_d_float		dtype_sql_date		dtype_sql_time
	dtype_timestamp		dtype_blob			dtype_array			dtype_int64
	dtype_dbkey			dtype_boolean		dtype_dec64			dtype_dec128
	dtype_int128 		dtype_sql_time_tz	dtype_timestamp_tz	dtype_ex_time_tz
	dtype_ex_timestamp_tz
	*/

	// dtype_unknown
	{dtype_unknown, dtype_unknown, dtype_unknown, dtype_unknown,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_unknown, dtype_unknown, DTYPE_CANNOT, dtype_unknown,
	 dtype_unknown, dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_unknown, dtype_unknown,
	 dtype_unknown, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_text
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_cstring
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_varying
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// 4 (unused)
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// 5 (unused)
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_packed
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_byte
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_short
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_long, dtype_long, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_long
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_long, dtype_long, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_quad
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_real
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_double, dtype_double,
	 dtype_double, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_double
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_double, dtype_double,
	 dtype_double, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_d_float -- VMS deprecated
	{dtype_unknown, dtype_d_float, dtype_d_float, dtype_d_float,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_d_float, dtype_d_float, DTYPE_CANNOT, dtype_d_float,
	 dtype_d_float, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_d_float, dtype_d_float,
	 dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_date
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_time
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_timestamp
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_blob
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_array
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_int64
	{dtype_unknown, dtype_double, dtype_double, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_double, dtype_double, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_double,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dbkey
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_boolean
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dec64
	{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_dec128
	{dtype_unknown, dtype_dec128, dtype_dec128, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_dec128, dtype_dec128, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_dec128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_int128
	{dtype_unknown, dtype_int128, dtype_int128, dtype_int128,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 dtype_int128, dtype_int128, DTYPE_CANNOT, dtype_double,
	 dtype_double, dtype_d_float, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, dtype_int128,
	 DTYPE_CANNOT, DTYPE_CANNOT, dtype_dec128, dtype_dec128,
	 dtype_int128, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_sql_time_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_timestamp_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_ex_time_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT},

	// dtype_ex_timestamp_tz
	{DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT, DTYPE_CANNOT,
	 DTYPE_CANNOT}
};

#ifdef DEV_BUILD
static bool validate_dsc_tables();
#endif



int dsc::getStringLength() const
{
	return DSC_string_length(this);
}


USHORT DSC_convert_to_text_length(USHORT dsc_type)
{
	if (dsc_type < (sizeof(_DSC_convert_to_text_length) / sizeof(_DSC_convert_to_text_length[0])))
		return _DSC_convert_to_text_length[dsc_type] + (dsc_type == dtype_int64 ? 1 : 0);
	fb_assert(FALSE);
	return 0;
}


bool DSC_make_descriptor(DSC* desc,
						USHORT blr_type,
						SSHORT scale,
						USHORT length,
						SSHORT sub_type,
						SSHORT charset,
						SSHORT collation)
{
/**************************************
 *
 *	D S C _ m a k e _ d e s c r i p t o r
 *
 **************************************
 *
 * Functional description
 *	Make an internal descriptor from external parameters.
 *
 **************************************/

#ifdef DEV_BUILD
	{
		// Execute this validation code once per server startup only
		static bool been_here = false;
		if (!been_here)
		{
			been_here = true;
			fb_assert(validate_dsc_tables());
		}
	}
#endif

	desc->dsc_flags = 0;
	desc->dsc_address = NULL;
	desc->dsc_length = length;
	desc->dsc_scale = (SCHAR) scale;
	desc->dsc_sub_type = sub_type;

	switch (blr_type)
	{
	case blr_text:
		desc->dsc_dtype = dtype_text;
		desc->setTextType(INTL_CS_COLL_TO_TTYPE(charset, collation));
		break;

	case blr_varying:
		desc->dsc_dtype = dtype_varying;
		desc->dsc_length += sizeof(USHORT);
		desc->setTextType(INTL_CS_COLL_TO_TTYPE(charset, collation));
		break;

	case blr_short:
		desc->dsc_length = sizeof(SSHORT);
		desc->dsc_dtype = dtype_short;
		break;

	case blr_long:
		desc->dsc_length = sizeof(SLONG);
		desc->dsc_dtype = dtype_long;
		break;

	case blr_int64:
		desc->dsc_length = sizeof(SINT64);
		desc->dsc_dtype = dtype_int64;
		break;

	case blr_quad:
		desc->dsc_length = 2 * sizeof(SLONG);
		desc->dsc_dtype = dtype_quad;
		break;

	case blr_float:
		desc->dsc_length = sizeof(float);
		desc->dsc_dtype = dtype_real;
		break;

	case blr_double:
	case blr_d_float:
		desc->dsc_length = sizeof(double);
		desc->dsc_dtype = dtype_double;
		break;

	case blr_dec64:
		desc->dsc_length = sizeof(Decimal64);
		desc->dsc_dtype = dtype_dec64;
		break;

	case blr_dec128:
		desc->dsc_length = sizeof(Decimal128);
		desc->dsc_dtype = dtype_dec128;
		break;

	case blr_int128:
		desc->dsc_length = sizeof(Int128);
		desc->dsc_dtype = dtype_int128;
		break;

	case blr_timestamp:
		desc->dsc_length = 2 * sizeof(SLONG);
		desc->dsc_dtype = dtype_timestamp;
		break;

	case blr_sql_date:
		desc->dsc_length = sizeof(SLONG);
		desc->dsc_dtype = dtype_sql_date;
		break;

	case blr_sql_time:
		desc->dsc_length = sizeof(ULONG);
		desc->dsc_dtype = dtype_sql_time;
		break;

	case blr_timestamp_tz:
		desc->dsc_length = sizeof(ISC_TIMESTAMP_TZ);
		desc->dsc_dtype = dtype_timestamp_tz;
		break;

	case blr_sql_time_tz:
		desc->dsc_length = sizeof(ISC_TIME_TZ);
		desc->dsc_dtype = dtype_sql_time_tz;
		break;

	case blr_ex_timestamp_tz:
		desc->dsc_length = sizeof(ISC_TIMESTAMP_TZ_EX);
		desc->dsc_dtype = dtype_ex_timestamp_tz;
		break;

	case blr_ex_time_tz:
		desc->dsc_length = sizeof(ISC_TIME_TZ_EX);
		desc->dsc_dtype = dtype_ex_time_tz;
		break;

	case blr_blob:
		desc->dsc_length = 2 * sizeof(SLONG);
		desc->dsc_dtype = dtype_blob;
		if (sub_type == isc_blob_text)
		{
			fb_assert(charset <= MAX_SCHAR);
			desc->dsc_scale = (SCHAR) charset;
			desc->dsc_flags = collation << 8;	// collation of blob
		}
		break;

	case blr_cstring:
		desc->dsc_dtype = dtype_cstring;
		desc->setTextType(INTL_CS_COLL_TO_TTYPE(charset, collation));
		break;

	case blr_bool:
		desc->dsc_length = sizeof(UCHAR);
		desc->dsc_dtype = dtype_boolean;
		break;

	default:
		fb_assert(FALSE);
		desc->dsc_dtype = dtype_unknown;
		return false;
		break;
	}
	return true;
}


int DSC_string_length(const dsc* desc)
{
/**************************************
 *
 *	D S C _ s t r i n g _ l e n g t h
 *
 **************************************
 *
 * Functional description
 *	Estimate length of string (in bytes) based on descriptor.
 *	Estimated length assumes representing string in
 *	narrow-char ASCII format.
 *
 *	Note that this strips off the short at the
 *	start of dtype_varying, and the NULL for dtype_cstring.
 *
 **************************************/

	switch (desc->dsc_dtype)
	{
	case dtype_text:
		return desc->dsc_length;
	case dtype_cstring:
		return desc->dsc_length - 1;
	case dtype_varying:
		return desc->dsc_length - sizeof(USHORT);
	default:
 		if (!DTYPE_IS_EXACT(desc->dsc_dtype) || desc->dsc_scale == 0)
 			return (int) _DSC_convert_to_text_length[desc->dsc_dtype];
 		if (desc->dsc_scale < 0)
			return (int) _DSC_convert_to_text_length[desc->dsc_dtype] + 1;
		return (int) _DSC_convert_to_text_length[desc->dsc_dtype] + desc->dsc_scale;
	}
}


const TEXT *DSC_dtype_tostring(UCHAR dtype)
{
/**************************************
 *
 *	D S C _ d t y p e _ t o s t r i n g
 *
 **************************************
 *
 * Functional description
 *	Convert a datatype to its textual representation
 *
 **************************************/
	if (dtype < FB_NELEM(DSC_dtype_names))
		return DSC_dtype_names[dtype];

	return "<unknown>";
}


void DSC_get_dtype_name(const dsc* desc, TEXT * buffer, USHORT len)
{
/**************************************
 *
 *	D S C _ g e t _ d t y p e _ n a m e
 *
 **************************************
 *
 * Functional description
 *	Convert a datatype to its textual representation
 *
 **************************************/
	fb_utils::copy_terminate(buffer, DSC_dtype_tostring(desc->dsc_dtype), len);
}


const char* dsc::typeToText() const
{
	switch (dsc_dtype)
	{
	case dtype_unknown:
		return "unknown";
	case dtype_text:
		return "char";
	case dtype_cstring:
		return "cstring";
	case dtype_varying:
		return "varchar";
	case dtype_packed:
		return "packed";
	case dtype_byte:
		return "byte";
	case dtype_short:
		return "smallint";
	case dtype_long:
		return "integer";
	case dtype_quad:
		return "quad";
	case dtype_real:
		return "float";
	case dtype_double:
		return "double precision";
	case dtype_d_float:
		return "d_float";
	case dtype_sql_date:
		return "date";
	case dtype_sql_time:
		return "time";
	case dtype_timestamp:
		return "timestamp";
	case dtype_blob:
		return "blob";
	case dtype_array:
		return "array";
	case dtype_int64:
		return "bigint";
	case dtype_dbkey:
		return "dbkey";
	case dtype_boolean:
		return "boolean";
	case dtype_dec64:
		return "decfloat(16)";
	case dtype_dec128:
		return "decfloat(34)";
	case dtype_int128:
		return "int128";
	case dtype_sql_time_tz:
		return "time with timezone";
	case dtype_timestamp_tz:
		return "timestamp with timezone";
	case dtype_ex_time_tz:
		return "extended time with timezone";
	case dtype_ex_timestamp_tz:
		return "extended timestamp with timezone";
	default:
		return "out of range";
	}
}


void dsc::getSqlInfo(SLONG* sqlLength, SLONG* sqlSubType, SLONG* sqlScale, SLONG* sqlType) const
{
	*sqlLength = dsc_length;
	*sqlSubType = 0;
	*sqlScale = 0;
	*sqlType = 0;

	switch (dsc_dtype)
	{
		case dtype_real:
			*sqlType = SQL_FLOAT;
			break;

		case dtype_array:
			*sqlType = SQL_ARRAY;
			break;

		case dtype_timestamp:
			*sqlType = SQL_TIMESTAMP;
			break;

		case dtype_sql_date:
			*sqlType = SQL_TYPE_DATE;
			break;

		case dtype_sql_time:
			*sqlType = SQL_TYPE_TIME;
			break;

		case dtype_double:
			*sqlType = SQL_DOUBLE;
			*sqlScale = dsc_scale;
			break;

		case dtype_text:
			*sqlType = SQL_TEXT;
			*sqlSubType = dsc_sub_type;
			break;

		case dtype_blob:
			*sqlType = SQL_BLOB;
			*sqlSubType = dsc_sub_type;
			*sqlScale = dsc_scale;
			break;

		case dtype_varying:
			*sqlType = SQL_VARYING;
			*sqlLength -= sizeof(USHORT);
			*sqlSubType = dsc_sub_type;
			break;

		case dtype_short:
		case dtype_long:
		case dtype_int64:
			switch (dsc_dtype)
			{
				case dtype_short:
					*sqlType = SQL_SHORT;
					break;

				case dtype_long:
					*sqlType = SQL_LONG;
					break;

				default:
					*sqlType = SQL_INT64;
			}

			*sqlScale = dsc_scale;
			if (dsc_sub_type)
				*sqlSubType = dsc_sub_type;
			break;

		case dtype_quad:
			*sqlType = SQL_QUAD;
			*sqlScale = dsc_scale;
			break;

		case dtype_boolean:
			*sqlType = SQL_BOOLEAN;
			break;

		case dtype_dec64:
			*sqlType = SQL_DEC16;
			*sqlScale = 0;
			break;

		case dtype_dec128:
			*sqlType = SQL_DEC34;
			*sqlScale = 0;
			break;

		case dtype_int128:
			*sqlType = SQL_INT128;
			*sqlScale = dsc_scale;
			if (dsc_sub_type)
				*sqlSubType = dsc_sub_type;
			break;

		case dtype_timestamp_tz:
			*sqlType = SQL_TIMESTAMP_TZ;
			break;

		case dtype_sql_time_tz:
			*sqlType = SQL_TIME_TZ;
			break;

		case dtype_ex_timestamp_tz:
			*sqlType = SQL_TIMESTAMP_TZ_EX;
			break;

		case dtype_ex_time_tz:
			*sqlType = SQL_TIME_TZ_EX;
			break;

		default:
			status_exception::raise(
				Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
				Arg::Gds(isc_dsql_datatype_err));
	}
}


#ifdef DEV_BUILD
void dsc::address32bit() const
{
/**************************************
 *
 *	a d d r e s s 3 2 b i t
 *
 **************************************
 *
 * Functional description
 *	Validates dsc_address member to fit into 4-byte integer.
 *
 **************************************/
#if SIZEOF_VOID_P > 4
	FB_UINT64 addr = (FB_UINT64)(IPTR) dsc_address;
	fb_assert(addr == (addr & 0xFFFFFFFF));
#endif
}


static bool validate_dsc_tables()
{
/**************************************
 *
 *	v a l i d a t e _ d s c _ t a b l e s
 *
 **************************************
 *
 * Functional description
 *	Validate tables that are used to describe
 *	operations on descriptors.  Note that this function
 *	is called as part of a DEV_BUILD assertion check
 *	only once per server.
 *
 * WARNING: the fprintf's are ifdef'd because trying to print
 *          to stderr when the server is running detached will trash
 *          server memory.  If you uncomment the printf's and build a
 *          kit, make sure that you run that server with the -d flag
 *          so it won't detach from its controlling terminal.
 *
 **************************************/

#define DSC_DIAG(a)

	for (BYTE op1 = dtype_unknown; op1 < DTYPE_TYPE_MAX; op1++)
	{
		for (BYTE op2 = dtype_unknown; op2 < DTYPE_TYPE_MAX; op2++)
		{

			if ((DSC_add_result[op1][op2] >= DTYPE_TYPE_MAX) &&
				(DSC_add_result[op1][op2] != DTYPE_CANNOT))
			{
				DSC_DIAG(fprintf (stderr, "DSC_add_result [%d][%d] is %d, invalid.\n",
					op1, op2, DSC_add_result [op1][op2]));
				return false;
			}

			// Addition operator must be communitive
			if (DSC_add_result[op1][op2] != DSC_add_result[op2][op1])
			{
				DSC_DIAG(fprintf (stderr,
					"Not commutative: DSC_add_result[%d][%d] = %d, ... [%d][%d] = %d\n",
					op1, op2, DSC_add_result [op1][op2],
					op2, op1, DSC_add_result [op2][op1] ));
				return false;
			}

			// Difficult to validate Subtraction
			if ((DSC_sub_result[op1][op2] >= DTYPE_TYPE_MAX) &&
				(DSC_sub_result[op1][op2] != DTYPE_CANNOT))
			{
				DSC_DIAG(fprintf (stderr, "DSC_sub_result [%d][%d] is %d, invalid.\n",
					op1, op2, DSC_sub_result [op1][op2]));
				return false;
			}

			// Multiplication operator must be commutative
			if (DSC_multiply_result[op1][op2] != DSC_multiply_result[op2][op1])
			{
				DSC_DIAG(fprintf (stderr,
					"Not commutative: DSC_multiply_result [%d][%d] = %d,\n\t... [%d][%d] = %d\n",
					op1, op2, DSC_multiply_result [op1][op2],
					op2, op1, DSC_multiply_result [op2][op1]));
				return false;
			}

			// Multiplication operator must be communitive
			if (DSC_multiply_blr4_result[op1][op2] != DSC_multiply_blr4_result[op2][op1])
			{
				DSC_DIAG(fprintf (stderr,
					"Not commutative: DSC_multiply_blr4_result [%d][%d] = %d\n\
					\t... [%d][%d] = %d\n",
					op1, op2, DSC_multiply_blr4_result [op1][op2],
					op2, op1, DSC_multiply_blr4_result [op2][op1] ));
				return false;
			}
		}
	}
	return true;
}

#endif // DEV_BUILD
