mariadb/storage/connect/myutil.cpp
Andrew Hutchings 358635bbad MDEV-29782 CONNECT YEAR type conversion fix
When using the MySQL table type the CONNECT engine converted the YEAR
datatype to DATETIME for INSERT queries. This is incorrect, causing an
error on the INSERT. It should be SHORT instead.
2023-02-21 17:55:01 +00:00

318 lines
9.7 KiB
C++

/************** MyUtil C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: MYUTIL */
/* ------------- */
/* Version 1.2 */
/* */
/* Author Olivier BERTRAND 2014 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* It contains utility functions to convert data types. */
/* It can optionally use the embedded MySQL library. */
/* */
/************************************************************************/
#include "my_global.h"
#include <mysql.h>
#if defined(_WIN32)
//#include <windows.h>
#else // !_WIN32
#include "osutil.h"
#endif // !_WIN32
#include "global.h"
#include "plgdbsem.h"
//#include "value.h"
//#include "valblk.h"
#include "myutil.h"
#define DLL_EXPORT // Items are exported from this DLL
//extern "C" int xconv;
TYPCONV GetTypeConv(void);
/************************************************************************/
/* Convert from MySQL type name to PlugDB type number */
/************************************************************************/
int MYSQLtoPLG(char *typname, char *var)
{
int type;
TYPCONV xconv = GetTypeConv();
if (!stricmp(typname, "int") || !stricmp(typname, "mediumint") ||
!stricmp(typname, "integer"))
type = TYPE_INT;
else if (!stricmp(typname, "smallint"))
type = TYPE_SHORT;
else if (!stricmp(typname, "char") || !stricmp(typname, "varchar") ||
!stricmp(typname, "enum") || !stricmp(typname, "set"))
type = TYPE_STRING;
else if (!stricmp(typname, "double") || !stricmp(typname, "float") ||
!stricmp(typname, "real"))
type = TYPE_DOUBLE;
else if (!stricmp(typname, "decimal") || !stricmp(typname, "numeric"))
type = TYPE_DECIM;
else if (!stricmp(typname, "date") || !stricmp(typname, "datetime") ||
!stricmp(typname, "time") || !stricmp(typname, "timestamp") ||
!stricmp(typname, "year"))
type = TYPE_DATE;
else if (!stricmp(typname, "bigint") || !stricmp(typname, "longlong"))
type = TYPE_BIGINT;
else if (!stricmp(typname, "tinyint"))
type = TYPE_TINY;
else if (!stricmp(typname, "text") && var) {
switch (xconv) {
case TPC_YES:
type = TYPE_STRING;
*var = 'X';
break;
case TPC_SKIP:
*var = 'K';
/* falls through */
default: // TPC_NO
type = TYPE_ERROR;
} // endswitch xconv
return type;
} else
type = TYPE_ERROR;
if (var) {
if (type == TYPE_DATE) {
// This is to make the difference between temporal values
if (!stricmp(typname, "date"))
*var = 'D';
else if (!stricmp(typname, "datetime"))
*var = 'A';
else if (!stricmp(typname, "timestamp"))
*var = 'S';
else if (!stricmp(typname, "time"))
*var = 'T';
else if (!stricmp(typname, "year"))
*var = 'Y';
} else if (type == TYPE_STRING) {
if (!stricmp(typname, "varchar"))
// This is to make the difference between CHAR and VARCHAR
*var = 'V';
} else if (type == TYPE_ERROR && xconv == TPC_SKIP)
*var = 'K';
else
*var = 0;
} // endif var
return type;
} // end of MYSQLtoPLG
/************************************************************************/
/* Convert from PlugDB type to MySQL type number */
/************************************************************************/
enum enum_field_types PLGtoMYSQL(int type, bool dbf, char v)
{
enum enum_field_types mytype;
switch (type) {
case TYPE_INT:
mytype = MYSQL_TYPE_LONG;
break;
case TYPE_SHORT:
mytype = MYSQL_TYPE_SHORT;
break;
case TYPE_DOUBLE:
mytype = MYSQL_TYPE_DOUBLE;
break;
case TYPE_DATE:
mytype = (dbf) ? MYSQL_TYPE_DATE :
(v == 'S') ? MYSQL_TYPE_TIMESTAMP :
(v == 'D') ? MYSQL_TYPE_NEWDATE :
(v == 'T') ? MYSQL_TYPE_TIME :
(v == 'Y') ? MYSQL_TYPE_YEAR : MYSQL_TYPE_DATETIME;
break;
case TYPE_STRING:
mytype = (v) ? MYSQL_TYPE_VARCHAR : MYSQL_TYPE_STRING;
break;
case TYPE_BIGINT:
mytype = MYSQL_TYPE_LONGLONG;
break;
case TYPE_TINY:
mytype = MYSQL_TYPE_TINY;
break;
case TYPE_DECIM:
#if !defined(ALPHA)
mytype = MYSQL_TYPE_NEWDECIMAL;
#else // ALPHA
mytype = MYSQL_TYPE_DECIMAL;
#endif // ALPHA
break;
default:
mytype = MYSQL_TYPE_NULL;
} // endswitch mytype
return mytype;
} // end of PLGtoMYSQL
/************************************************************************/
/* Convert from PlugDB type to MySQL type name */
/************************************************************************/
const char *PLGtoMYSQLtype(int type, bool dbf, char v)
{
switch (type) {
case TYPE_INT: return "INT";
case TYPE_SHORT: return "SMALLINT";
case TYPE_DOUBLE: return "DOUBLE";
case TYPE_DATE: return dbf ? "DATE" :
(v == 'S') ? "TIMESTAMP" :
(v == 'D') ? "DATE" :
(v == 'T') ? "TIME" :
(v == 'Y') ? "YEAR" : "DATETIME";
case TYPE_STRING: return v ? "VARCHAR" : "CHAR";
case TYPE_BIGINT: return "BIGINT";
case TYPE_TINY: return "TINYINT";
case TYPE_DECIM: return "DECIMAL";
default: return (v) ? "VARCHAR" : "CHAR";
} // endswitch mytype
} // end of PLGtoMYSQLtype
/************************************************************************/
/* Convert from MySQL type to PlugDB type number */
/************************************************************************/
int MYSQLtoPLG(int mytype, char *var)
{
int type, xconv = GetTypeConv();
switch (mytype) {
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_YEAR:
type = TYPE_SHORT;
break;
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_ENUM: // ???
type = TYPE_INT;
break;
case MYSQL_TYPE_LONGLONG:
type = TYPE_BIGINT;
break;
case MYSQL_TYPE_TINY:
type = TYPE_TINY;
break;
case MYSQL_TYPE_DECIMAL:
#if !defined(ALPHA)
case MYSQL_TYPE_NEWDECIMAL:
#endif // !ALPHA)
type = TYPE_DECIM;
break;
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
type = TYPE_DOUBLE;
break;
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIME:
type = TYPE_DATE;
break;
case MYSQL_TYPE_VAR_STRING:
#if !defined(ALPHA)
case MYSQL_TYPE_VARCHAR:
#endif // !ALPHA)
case MYSQL_TYPE_STRING:
type = (*var == 'B') ? TYPE_BIN : TYPE_STRING;
break;
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
if (var) {
switch (xconv) {
case TPC_YES:
if (*var != 'B') {
// This is a TEXT column
type = TYPE_STRING;
*var = 'X';
} else
type = TYPE_BIN;
break;
case TPC_SKIP:
*var = 'K'; // Skip
/* falls through */
default: // TPC_NO
type = TYPE_ERROR;
} // endswitch xconv
return type;
} // endif var
/* falls through */
default:
type = TYPE_ERROR;
} // endswitch mytype
if (var) switch (mytype) {
// This is to make the difference between CHAR and VARCHAR
#if !defined(ALPHA)
case MYSQL_TYPE_VARCHAR:
#endif // !ALPHA)
case MYSQL_TYPE_VAR_STRING: *var = 'V'; break;
// This is to make the difference between temporal values
case MYSQL_TYPE_TIMESTAMP: *var = 'S'; break;
case MYSQL_TYPE_DATE: *var = 'D'; break;
case MYSQL_TYPE_DATETIME: *var = 'A'; break;
case MYSQL_TYPE_YEAR: *var = 'Y'; break;
case MYSQL_TYPE_TIME: *var = 'T'; break;
default: *var = 0;
} // endswitch mytype
return type;
} // end of MYSQLtoPLG
/************************************************************************/
/* Returns the format corresponding to a MySQL date type number. */
/************************************************************************/
PCSZ MyDateFmt(int mytype)
{
PCSZ fmt;
switch (mytype) {
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATETIME:
fmt = "YYYY-MM-DD hh:mm:ss";
break;
case MYSQL_TYPE_DATE:
fmt = "YYYY-MM-DD";
break;
case MYSQL_TYPE_YEAR:
fmt = "YYYY";
break;
case MYSQL_TYPE_TIME:
fmt = "hh:mm:ss";
break;
default:
fmt = NULL;
} // endswitch mytype
return fmt;
} // end of MyDateFmt
/************************************************************************/
/* Returns the format corresponding to a MySQL date type name. */
/************************************************************************/
PCSZ MyDateFmt(char *typname)
{
PCSZ fmt;
if (!stricmp(typname, "datetime") || !stricmp(typname, "timestamp"))
fmt = "YYYY-MM-DD hh:mm:ss";
else if (!stricmp(typname, "date"))
fmt = "YYYY-MM-DD";
else if (!stricmp(typname, "year"))
fmt = "YYYY";
else if (!stricmp(typname, "time"))
fmt = "hh:mm:ss";
else
fmt = NULL;
return fmt;
} // end of MyDateFmt