/*
Copyright ( c ) 2026 , MariaDB Foundation .
Copyright ( c ) 2026 , Roman Nozdrin < drrtuy @ gmail . com >
Copyright ( c ) 2026 , Leonid Fedorov .
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; version 2 of the License .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1335 USA
*/
#pragma once
#include <string>
#include <vector>
#include "duckdb_types.h"
#define MYSQL_SERVER 1
#include "my_global.h"
#include "sql_class.h"
#include "field.h"
static inline const Type_collection *duckdb_uuid_type_collection()
{
static const Type_collection *const coll=
[]() -> const Type_collection *
{
static const LEX_CSTRING uuid_name= {STRING_WITH_LEN("uuid" )};
const Type_handler *th=
Type_handler::handler_by_name(current_thd, uuid_name);
return th ? th->type_collection() : nullptr;
}();
return coll;
}
static inline bool is_uuid_field(const Field *field)
{
const Type_collection *uuid_coll= duckdb_uuid_type_collection();
return uuid_coll &&
field->type_handler()->type_collection() == uuid_coll;
}
/**
Name of the DuckDB sequence backing the AUTO_INCREMENT column of a table .
MariaDB allows at most one AUTO_INCREMENT column per table , so the table
name alone identifies the sequence .
*/
std::string autoinc_sequence_name(const std::string &table_name);
/** The AUTO_INCREMENT field of a table, or nullptr if there is none. */
Field *find_autoinc_field(const TABLE *table);
class BaseConvertor
{
public :
/** Check if query can be executed by duckdb */
virtual bool check()= 0 ;
/** Get the query under duckdb syntax. */
virtual std::string translate()= 0 ;
virtual ~BaseConvertor()= default ;
};
enum enum_ddl_convertor_type
{
/* Do nothing */
NONE_OP= 0 ,
/* Drop column */
DROP_COLUMN,
/* Add column */
ADD_COLUMN,
/* Alter column */
ALTER_COLUMN,
/* Add index */
ADD_INDEX,
/* Rename table */
RENAME_TABLE,
/* This should be the last ! */
DDL_CONVERTOR_TYPE_END
};
enum class ddl_error_context
{
ALTER,
CREATE
};
class FieldConvertor : public BaseConvertor
{
public :
FieldConvertor(Field *field, ddl_error_context ctx= ddl_error_context::ALTER)
: m_field(field), m_ctx(ctx)
{
}
bool check() override;
std::string translate() override;
static std::string convert_type(const Field *field);
private :
Field *m_field;
ddl_error_context m_ctx;
};
/** Convertor to translate "ALTER TABLE ..." */
class AlterTableConvertor : public BaseConvertor
{
public :
AlterTableConvertor(const std::string &schema_name,
const std::string &table_name,
const enum_ddl_convertor_type type)
: m_schema_name(schema_name), m_table_name(table_name), m_type(type)
{
}
~AlterTableConvertor() override= default ;
bool check() override { return false ; }
std::string translate() override { return "" ; }
std::string m_schema_name;
std::string m_table_name;
const enum_ddl_convertor_type m_type;
};
/** Convert create table from mysql to duckdb. */
class CreateTableConvertor : public BaseConvertor
{
public :
CreateTableConvertor(THD *thd, const TABLE *table,
const HA_CREATE_INFO *create_info,
const std::string &schema_name,
const std::string &table_name)
: m_schema_name(schema_name), m_table_name(table_name), m_thd(thd),
m_table(table), m_create_info(create_info)
{
}
~CreateTableConvertor() override= default ;
bool check() override;
std::string translate() override;
private :
std::string m_schema_name;
std::string m_table_name;
/** Thread context */
THD *m_thd;
/** Table to create */
const TABLE *m_table;
/** Create info */
const HA_CREATE_INFO *m_create_info;
/** Append column definition to output.
@param[in, out] output output stream */
void append_column_definition(std::ostringstream &output);
};
/** Convertor to translate "RENAME TABLE ... to ..." or
"ALTER TABLE ... RENAME TO ..." */
class RenameTableConvertor : public AlterTableConvertor
{
public :
RenameTableConvertor(const std::string &old_schema_name,
const std::string &old_table_name,
const std::string &new_schema_name,
const std::string &new_table_name)
: AlterTableConvertor(old_schema_name, old_table_name, RENAME_TABLE),
m_new_schema_name(new_schema_name), m_new_table_name(new_table_name)
{
}
~RenameTableConvertor() override= default ;
bool check() override;
/** ALTER TABLE ... RENAME TO ... */
std::string translate() override;
private :
/** New schema name */
std::string m_new_schema_name;
/** New table name */
std::string m_new_table_name;
};
/** Pair of Create_field(new) and Field(new). */
using Column= std::pair<Create_field *, Field *>;
/** Vector of columns to alter. */
using Columns= std::vector<Column>;
/** Convertor to translate "ALTER TABLE ... ADD COLUMN ..." */
class AddColumnConvertor : public AlterTableConvertor
{
public :
AddColumnConvertor(const std::string &schema_name,
const std::string &table_name, const TABLE *altered_table,
Alter_info *alter_info)
: AlterTableConvertor(schema_name, table_name, ADD_COLUMN),
m_new_table(altered_table), m_alter_info(alter_info)
{
prepare_columns();
}
~AddColumnConvertor() override= default ;
bool check() override;
std::string translate() override;
private :
/** new TABLE */
const TABLE *m_new_table;
/** Alter options, fields and keys for the new version of table. */
Alter_info *m_alter_info;
/** Columns to add */
Columns m_columns_to_add;
/** Columns to set not null */
Columns m_columns_to_set_not_null;
/** Columns whose temporary default must be dropped */
Columns m_columns_to_drop_default;
/** Prepare columns to add and set not null. */
void prepare_columns();
};
/** Convertor to translate "ALTER TABLE ... DROP COLUMN ..." */
class DropColumnConvertor : public AlterTableConvertor
{
public :
DropColumnConvertor(const std::string &schema_name,
const std::string &table_name, const TABLE *old_table,
const TABLE *new_table, Alter_info *alter_info)
: AlterTableConvertor(schema_name, table_name, DROP_COLUMN),
m_old_table(old_table), m_new_table(new_table),
m_alter_info(alter_info)
{
prepare_columns();
}
~DropColumnConvertor() override= default ;
bool check() override;
std::string translate() override;
private :
/** old TABLE */
const TABLE *m_old_table;
/** new TABLE (altered) */
const TABLE *m_new_table;
/** Alter options, fields and keys for the new version of table. */
Alter_info *m_alter_info;
/** Columns to drop */
Columns m_columns_to_drop;
/** Prepare columns to drop. */
void prepare_columns();
};
/** Convertor to translate change column default value. */
class ChangeColumnDefaultConvertor : public AlterTableConvertor
{
public :
ChangeColumnDefaultConvertor(const std::string &schema_name,
const std::string &table_name,
const TABLE *old_table, const TABLE *new_table)
: AlterTableConvertor(schema_name, table_name, ALTER_COLUMN),
m_old_table(old_table), m_new_table(new_table)
{
prepare_columns();
}
~ChangeColumnDefaultConvertor() override= default ;
std::string translate() override;
private :
/** old TABLE */
const TABLE *m_old_table;
/** new TABLE (altered) */
const TABLE *m_new_table;
/** Columns to set default */
Columns m_columns_to_set_default;
/** Columns to drop default */
Columns m_columns_to_drop_default;
/** Prepare columns by comparing old and new table defaults. */
void prepare_columns();
};
/** Convertor to translate "ALTER TABLE ... [ CHANGE | MODIFY | RENAME ]
COLUMN ..." */
class ChangeColumnConvertor : public AlterTableConvertor
{
public :
ChangeColumnConvertor(const std::string &schema_name,
const std::string &table_name, const TABLE *new_table,
Alter_info *alter_info)
: AlterTableConvertor(schema_name, table_name, ALTER_COLUMN),
m_new_table(new_table), m_alter_info(alter_info)
{
prepare_columns();
}
~ChangeColumnConvertor() override= default ;
bool check() override;
std::string translate() override;
private :
/** new TABLE */
const TABLE *m_new_table;
/** Alter options, fields and keys for the new version of table. */
Alter_info *m_alter_info;
/** Columns to change */
Columns m_columns;
/** Columns to change type */
Columns m_columns_to_change_type;
/** Columns to set not null */
Columns m_columns_to_set_not_null;
/** Columns to drop not null */
Columns m_columns_to_drop_not_null;
/** Columns to rename */
Columns m_columns_to_rename;
/** Prepare columns to change. */
void prepare_columns();
};
/** Convertor to set primary key column not null. */
class ChangeColumnForPrimaryKeyConvertor : public AlterTableConvertor
{
public :
ChangeColumnForPrimaryKeyConvertor(const std::string &schema_name,
const std::string &table_name,
const TABLE *new_table)
: AlterTableConvertor(schema_name, table_name, ALTER_COLUMN),
m_new_table(new_table)
{
prepare_columns();
}
std::string translate() override;
private :
/** new TABLE */
const TABLE *m_new_table;
/** Columns to set not null */
std::vector<Field *> m_columns_to_set_not_null;
/** Prepare columns to set not null. */
void prepare_columns();
};
/* Convert a binary string to hexadecimal representation '\x01\x0A\xAC'::BLOB
*/
std::string toHex(const char *data, size_t length);
/* Report DuckDB table structure error */
bool report_duckdb_table_struct_error(
const char *err_msg, const char *try_instead, const char *column,
ddl_error_context ctx= ddl_error_context::ALTER);
Messung V0.5 in Prozent C=86 H=100 G=93
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-10-08)
¤
*© Formatika GbR, Deutschland