From a179de04025443032745ee811a97d8da7afe8996 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sat, 6 Jul 2019 11:09:06 +0400 Subject: [PATCH] MDEV-19991 Turn I_S tables GEOMETRY_COLUMNS and SPATIAL_REF_SYS into a plugin --- plugin/type_geom/CMakeLists.txt | 3 + plugin/type_geom/plugin.cc | 280 ++++++++++++++++++++++++++++++++ sql/field.h | 2 +- sql/handler.h | 6 +- sql/sql_error.cc | 10 ++ sql/sql_error.h | 1 + sql/sql_show.cc | 166 +------------------ sql/sql_show.h | 4 + 8 files changed, 302 insertions(+), 170 deletions(-) create mode 100644 plugin/type_geom/CMakeLists.txt create mode 100644 plugin/type_geom/plugin.cc diff --git a/plugin/type_geom/CMakeLists.txt b/plugin/type_geom/CMakeLists.txt new file mode 100644 index 00000000000..2b0c84f6fa0 --- /dev/null +++ b/plugin/type_geom/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql) + +MYSQL_ADD_PLUGIN(TYPE_GEOM plugin.cc MANDATORY RECOMPILE_FOR_EMBEDDED) diff --git a/plugin/type_geom/plugin.cc b/plugin/type_geom/plugin.cc new file mode 100644 index 00000000000..bcca9011bec --- /dev/null +++ b/plugin/type_geom/plugin.cc @@ -0,0 +1,280 @@ +/* + Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2009, 2019, MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include +#include // THD +#include // ST_SCHEMA_TABLE +#include +#include "sql_show.h" // get_all_tables() +#include "sql_error.h" // convert_error_to_warning() + + +/*********** INFORMATION_SCHEMA.SPATIEL_REF_SYS *******************/ + +namespace Show { + +static ST_FIELD_INFO spatial_ref_sys_fields_info[]= +{ + Column("SRID", SShort(5), NOT_NULL), + Column("AUTH_NAME", Varchar(FN_REFLEN), NOT_NULL), + Column("AUTH_SRID", SLong(5), NOT_NULL), + Column("SRTEXT", Varchar(2048), NOT_NULL), + CEnd() +}; + + +static int spatial_ref_sys_fill(THD *thd, TABLE_LIST *tables, COND *cond) +{ + DBUG_ENTER("fill_spatial_ref_sys"); + TABLE *table= tables->table; + CHARSET_INFO *cs= system_charset_info; + int result= 1; + + restore_record(table, s->default_values); + + table->field[0]->store(-1, FALSE); /*SRID*/ + table->field[1]->store(STRING_WITH_LEN("Not defined"), cs); /*AUTH_NAME*/ + table->field[2]->store(-1, FALSE); /*AUTH_SRID*/ + table->field[3]->store(STRING_WITH_LEN( + "LOCAL_CS[\"Spatial reference wasn't specified\"," + "LOCAL_DATUM[\"Unknown\",0]," "UNIT[\"m\",1.0]," "AXIS[\"x\",EAST]," + "AXIS[\"y\",NORTH]]"), cs);/*SRTEXT*/ + if (schema_table_store_record(thd, table)) + goto exit; + + table->field[0]->store(0, TRUE); /*SRID*/ + table->field[1]->store(STRING_WITH_LEN("EPSG"), cs); /*AUTH_NAME*/ + table->field[2]->store(404000, TRUE); /*AUTH_SRID*/ + table->field[3]->store(STRING_WITH_LEN( + "LOCAL_CS[\"Wildcard 2D cartesian plane in metric unit\"," + "LOCAL_DATUM[\"Unknown\",0]," "UNIT[\"m\",1.0]," + "AXIS[\"x\",EAST]," "AXIS[\"y\",NORTH]," + "AUTHORITY[\"EPSG\",\"404000\"]]"), cs);/*SRTEXT*/ + if (schema_table_store_record(thd, table)) + goto exit; + + result= 0; + +exit: + DBUG_RETURN(result); +} + + +static int fill_table_spatial_ref_sys(THD *thd, TABLE_LIST* tables, COND* cond) +{ + spatial_ref_sys_fill(thd, tables, cond); + return 0; +} + + +static int plugin_init_spatial_ref_sys(void *p) +{ + ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p; + schema->fields_info= spatial_ref_sys_fields_info; + schema->fill_table= fill_table_spatial_ref_sys; + return 0; +} + + +static struct st_mysql_information_schema spatial_ref_sys_plugin= +{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; + + +} // namespace Show + +/*********** INFORMATION_SCHEMA.GEOMETRY_COLUMNS *******************/ + + +namespace Show { + +static ST_FIELD_INFO geometry_columns_fields_info[]= +{ + Column("F_TABLE_CATALOG", Catalog(), NOT_NULL, OPEN_FRM_ONLY), + Column("F_TABLE_SCHEMA", Name(), NOT_NULL, OPEN_FRM_ONLY), + Column("F_TABLE_NAME", Name(), NOT_NULL, OPEN_FRM_ONLY), + Column("F_GEOMETRY_COLUMN", Name(), NOT_NULL, OPEN_FRM_ONLY), + Column("G_TABLE_CATALOG", Catalog(), NOT_NULL, OPEN_FRM_ONLY), + Column("G_TABLE_SCHEMA", Name(), NOT_NULL, OPEN_FRM_ONLY), + Column("G_TABLE_NAME", Name(), NOT_NULL, OPEN_FRM_ONLY), + Column("G_GEOMETRY_COLUMN", Name(), NOT_NULL, OPEN_FRM_ONLY), + Column("STORAGE_TYPE", STiny(2), NOT_NULL, OPEN_FRM_ONLY), + Column("GEOMETRY_TYPE", SLong(7), NOT_NULL, OPEN_FRM_ONLY), + Column("COORD_DIMENSION", STiny(2), NOT_NULL, OPEN_FRM_ONLY), + Column("MAX_PPR", STiny(2), NOT_NULL, OPEN_FRM_ONLY), + Column("SRID", SShort(5), NOT_NULL, OPEN_FRM_ONLY), + CEnd() +}; + + +static void geometry_columns_fill_record(TABLE *table, + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name, + const Field_geom *field) +{ + static const LEX_CSTRING catalog= {STRING_WITH_LEN("def")}; + const CHARSET_INFO *cs= system_charset_info; + const Type_handler_geometry *gth= field->type_handler_geom(); + /*F_TABLE_CATALOG*/ + table->field[0]->store(catalog, cs); + /*F_TABLE_SCHEMA*/ + table->field[1]->store(db_name, cs); + /*F_TABLE_NAME*/ + table->field[2]->store(table_name, cs); + /*G_TABLE_CATALOG*/ + table->field[4]->store(catalog, cs); + /*G_TABLE_SCHEMA*/ + table->field[5]->store(db_name, cs); + /*G_TABLE_NAME*/ + table->field[6]->store(table_name, cs); + /*G_GEOMETRY_COLUMN*/ + table->field[7]->store(field->field_name, cs); + /*STORAGE_TYPE*/ + table->field[8]->store(1LL, true); /*Always 1 (binary implementation)*/ + /*GEOMETRY_TYPE*/ + table->field[9]->store((longlong) (gth->geometry_type()), true); + /*COORD_DIMENSION*/ + table->field[10]->store(2LL, true); + /*MAX_PPR*/ + table->field[11]->set_null(); + /*SRID*/ + table->field[12]->store((longlong) (field->get_srid()), true); +} + + +static int get_geometry_column_record(THD *thd, TABLE_LIST *tables, + TABLE *table, bool res, + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) +{ + TABLE *show_table; + Field **ptr, *field; + DBUG_ENTER("get_geometry_column_record"); + + if (res) + { + /* + open_table() failed with an error. + Convert the error to a warning and let the caller + continue with the next table. + */ + convert_error_to_warning(thd); + DBUG_RETURN(0); + } + + // Skip INFORMATION_SCHEMA tables. They don't have geometry columns. + if (tables->schema_table) + DBUG_RETURN(0); + + show_table= tables->table; + ptr= show_table->field; + show_table->use_all_columns(); // Required for default + restore_record(show_table, s->default_values); + + for (; (field= *ptr) ; ptr++) + { + const Field_geom *fg; + if (field->type() == MYSQL_TYPE_GEOMETRY && + (fg= dynamic_cast(field))) + { + DEBUG_SYNC(thd, "get_schema_column"); + /* Get default row, with all NULL fields set to NULL */ + restore_record(table, s->default_values); + geometry_columns_fill_record(table, db_name, table_name, fg); + if (schema_table_store_record(thd, table)) + DBUG_RETURN(1); + } + } + + DBUG_RETURN(0); +} + + +static ST_SCHEMA_TABLE geometry_columns= +{ + "GEOMETRY_COLUMNS", // table_name + geometry_columns_fields_info, // fields_info + 0, // reset_table + NULL, // fill_table + NULL, // old_format + get_geometry_column_record, // process_table + 1, // idx_field1 + 2, // idx_field2 + 0, // hidden + OPTIMIZE_I_S_TABLE|OPEN_VIEW_FULL // i_s_requested_object +}; + + +static int fill_table_geometry_columns(THD *thd, TABLE_LIST* tables, COND* cond) +{ + tables->schema_table= &geometry_columns; + optimize_for_get_all_tables(thd, tables, cond); + get_all_tables(thd, tables, cond); + return 0; +} + + +static int plugin_init_geometry_columns(void *p) +{ + ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p; + schema->fields_info= geometry_columns_fields_info; + schema->fill_table= fill_table_geometry_columns; + return 0; +} + + +static struct st_mysql_information_schema geometry_columns_plugin= +{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; + + +} // namespace Show + + +/********************* Plugin library descriptors ************************/ + + +maria_declare_plugin(type_geom) +{ + MYSQL_INFORMATION_SCHEMA_PLUGIN, // the plugin type (see include/mysql/plugin.h) + &Show::spatial_ref_sys_plugin, // pointer to type-specific plugin descriptor + "SPATIAL_REF_SYS", // plugin name + "MariaDB", // plugin author + "Lists all geometry columns", // the plugin description + PLUGIN_LICENSE_GPL, // the plugin license (see include/mysql/plugin.h) + Show::plugin_init_spatial_ref_sys, // Pointer to plugin initialization function + 0, // Pointer to plugin deinitialization function + 0x0100, // Numeric version 0xAABB means AA.BB veriosn + NULL, // Status variables + NULL, // System variables + "1.0", // String version representation + MariaDB_PLUGIN_MATURITY_ALPHA // Maturity (see include/mysql/plugin.h)*/ +}, +{ + MYSQL_INFORMATION_SCHEMA_PLUGIN, // the plugin type (see include/mysql/plugin.h) + &Show::geometry_columns_plugin, // pointer to type-specific plugin descriptor + "GEOMETRY_COLUMNS", // plugin name + "MariaDB", // plugin author + "Lists all geometry columns", // the plugin description + PLUGIN_LICENSE_GPL, // the plugin license (see include/mysql/plugin.h) + Show::plugin_init_geometry_columns,// Pointer to plugin initialization function + 0, // Pointer to plugin deinitialization function + 0x0100, // Numeric version 0xAABB means AA.BB veriosn + NULL, // Status variables + NULL, // System variables + "1.0", // String version representation + MariaDB_PLUGIN_MATURITY_ALPHA // Maturity (see include/mysql/plugin.h) +} +maria_declare_plugin_end; diff --git a/sql/field.h b/sql/field.h index 9a581c83a14..3653f4e1e92 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4326,7 +4326,7 @@ public: bool load_data_set_null(THD *thd); bool load_data_set_no_data(THD *thd, bool fixed_format); - uint get_srid() { return srid; } + uint get_srid() const { return srid; } void print_key_value(String *out, uint32 length) { out->append(STRING_WITH_LEN("unprintable_geometry_value")); diff --git a/sql/handler.h b/sql/handler.h index 01dc9a345e7..3407321bac1 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1022,11 +1022,7 @@ enum enum_schema_tables SCH_TABLE_PRIVILEGES, SCH_TRIGGERS, SCH_USER_PRIVILEGES, - SCH_VIEWS, -#ifdef HAVE_SPATIAL - SCH_GEOMETRY_COLUMNS, - SCH_SPATIAL_REF_SYS, -#endif /*HAVE_SPATIAL*/ + SCH_VIEWS }; struct TABLE_SHARE; diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 9f541c775fa..e6dcfed0412 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -1009,3 +1009,13 @@ bool is_sqlstate_valid(const LEX_CSTRING *sqlstate) return true; } + + +void convert_error_to_warning(THD *thd) +{ + DBUG_ASSERT(thd->is_error()); + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, + thd->get_stmt_da()->sql_errno(), + thd->get_stmt_da()->message()); + thd->clear_error(); +} diff --git a/sql/sql_error.h b/sql/sql_error.h index 5055c1a61cf..a0497af78cb 100644 --- a/sql/sql_error.h +++ b/sql/sql_error.h @@ -1260,6 +1260,7 @@ private: /////////////////////////////////////////////////////////////////////////// +void convert_error_to_warning(THD *thd); void push_warning(THD *thd, Sql_condition::enum_warning_level level, uint code, const char *msg); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 48276d9fe58..3fc662ed954 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -376,127 +376,6 @@ int fill_all_plugins(THD *thd, TABLE_LIST *tables, COND *cond) } -#ifdef HAVE_SPATIAL -static int fill_spatial_ref_sys(THD *thd, TABLE_LIST *tables, COND *cond) -{ - DBUG_ENTER("fill_spatial_ref_sys"); - TABLE *table= tables->table; - CHARSET_INFO *cs= system_charset_info; - int result= 1; - - restore_record(table, s->default_values); - - table->field[0]->store(-1, FALSE); /*SRID*/ - table->field[1]->store(STRING_WITH_LEN("Not defined"), cs); /*AUTH_NAME*/ - table->field[2]->store(-1, FALSE); /*AUTH_SRID*/ - table->field[3]->store(STRING_WITH_LEN( - "LOCAL_CS[\"Spatial reference wasn't specified\"," - "LOCAL_DATUM[\"Unknown\",0]," "UNIT[\"m\",1.0]," "AXIS[\"x\",EAST]," - "AXIS[\"y\",NORTH]]"), cs);/*SRTEXT*/ - if (schema_table_store_record(thd, table)) - goto exit; - - table->field[0]->store(0, TRUE); /*SRID*/ - table->field[1]->store(STRING_WITH_LEN("EPSG"), cs); /*AUTH_NAME*/ - table->field[2]->store(404000, TRUE); /*AUTH_SRID*/ - table->field[3]->store(STRING_WITH_LEN( - "LOCAL_CS[\"Wildcard 2D cartesian plane in metric unit\"," - "LOCAL_DATUM[\"Unknown\",0]," "UNIT[\"m\",1.0]," - "AXIS[\"x\",EAST]," "AXIS[\"y\",NORTH]," - "AUTHORITY[\"EPSG\",\"404000\"]]"), cs);/*SRTEXT*/ - if (schema_table_store_record(thd, table)) - goto exit; - - result= 0; - -exit: - DBUG_RETURN(result); -} - - -static int get_geometry_column_record(THD *thd, TABLE_LIST *tables, - TABLE *table, bool res, - const LEX_CSTRING *db_name, - const LEX_CSTRING *table_name) -{ - CHARSET_INFO *cs= system_charset_info; - TABLE *show_table; - Field **ptr, *field; - DBUG_ENTER("get_geometry_column_record"); - - if (res) - { - if (thd->lex->sql_command != SQLCOM_SHOW_FIELDS) - { - /* - I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS - rather than in SHOW COLUMNS - */ - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, - thd->get_stmt_da()->sql_errno(), - thd->get_stmt_da()->message()); - thd->clear_error(); - res= 0; - } - DBUG_RETURN(res); - } - - if (tables->schema_table) - goto exit; - show_table= tables->table; - ptr= show_table->field; - show_table->use_all_columns(); // Required for default - restore_record(show_table, s->default_values); - -#ifdef HAVE_SPATIAL - for (; (field= *ptr) ; ptr++) - if (field->type() == MYSQL_TYPE_GEOMETRY) - { - Field_geom *fg= (Field_geom *) field; - const Type_handler_geometry *gth= fg->type_handler_geom(); - - DEBUG_SYNC(thd, "get_schema_column"); - - /* Get default row, with all NULL fields set to NULL */ - restore_record(table, s->default_values); - - /*F_TABLE_CATALOG*/ - table->field[0]->store(STRING_WITH_LEN("def"), cs); - /*F_TABLE_SCHEMA*/ - table->field[1]->store(db_name->str, db_name->length, cs); - /*F_TABLE_NAME*/ - table->field[2]->store(table_name->str, table_name->length, cs); - /*G_TABLE_CATALOG*/ - table->field[4]->store(STRING_WITH_LEN("def"), cs); - /*G_TABLE_SCHEMA*/ - table->field[5]->store(db_name->str, db_name->length, cs); - /*G_TABLE_NAME*/ - table->field[6]->store(table_name->str, table_name->length, cs); - /*G_GEOMETRY_COLUMN*/ - table->field[7]->store(field->field_name.str, field->field_name.length, - cs); - /*STORAGE_TYPE*/ - table->field[8]->store(1LL, TRUE); /*Always 1 (binary implementation)*/ - /*GEOMETRY_TYPE*/ - table->field[9]->store((longlong) (gth->geometry_type()), TRUE); - /*COORD_DIMENSION*/ - table->field[10]->store(2LL, TRUE); - /*MAX_PPR*/ - table->field[11]->set_null(); - /*SRID*/ - table->field[12]->store((longlong) (fg->get_srid()), TRUE); - - if (schema_table_store_record(thd, table)) - DBUG_RETURN(1); - } -#endif - -exit: - DBUG_RETURN(0); -} -#endif /*HAVE_SPATIAL*/ - - /*************************************************************************** ** List all Authors. ** If you can update it, you get to be in it :) @@ -5959,10 +5838,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS rather than in SHOW COLUMNS */ - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, - thd->get_stmt_da()->sql_errno(), - thd->get_stmt_da()->message()); - thd->clear_error(); + convert_error_to_warning(thd); res= 0; } DBUG_RETURN(res); @@ -8541,7 +8417,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel, */ -static bool optimize_for_get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) +bool optimize_for_get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) { SELECT_LEX *lsel= tables->schema_select_lex; ST_SCHEMA_TABLE *schema_table= tables->schema_table; @@ -9543,37 +9419,6 @@ ST_FIELD_INFO show_explain_fields_info[]= }; -#ifdef HAVE_SPATIAL -ST_FIELD_INFO geometry_columns_fields_info[]= -{ - Column("F_TABLE_CATALOG", Catalog(), NOT_NULL, OPEN_FRM_ONLY), - Column("F_TABLE_SCHEMA", Name(), NOT_NULL, OPEN_FRM_ONLY), - Column("F_TABLE_NAME", Name(), NOT_NULL, OPEN_FRM_ONLY), - Column("F_GEOMETRY_COLUMN", Name(), NOT_NULL, "Field", OPEN_FRM_ONLY), - Column("G_TABLE_CATALOG", Catalog(), NOT_NULL, OPEN_FRM_ONLY), - Column("G_TABLE_SCHEMA", Name(), NOT_NULL, OPEN_FRM_ONLY), - Column("G_TABLE_NAME", Name(), NOT_NULL, OPEN_FRM_ONLY), - Column("G_GEOMETRY_COLUMN", Name(), NOT_NULL, "Field", OPEN_FRM_ONLY), - Column("STORAGE_TYPE", STiny(2), NOT_NULL, OPEN_FRM_ONLY), - Column("GEOMETRY_TYPE", SLong(7), NOT_NULL, OPEN_FRM_ONLY), - Column("COORD_DIMENSION", STiny(2), NOT_NULL, OPEN_FRM_ONLY), - Column("MAX_PPR", STiny(2), NOT_NULL, OPEN_FRM_ONLY), - Column("SRID", SShort(5), NOT_NULL, OPEN_FRM_ONLY), - CEnd() -}; - - -ST_FIELD_INFO spatial_ref_sys_fields_info[]= -{ - Column("SRID", SShort(5), NOT_NULL), - Column("AUTH_NAME", Varchar(FN_REFLEN), NOT_NULL), - Column("AUTH_SRID", SLong(5), NOT_NULL), - Column("SRTEXT", Varchar(2048), NOT_NULL), - CEnd() -}; -#endif /*HAVE_SPATIAL*/ - - ST_FIELD_INFO check_constraints_fields_info[]= { Column("CONSTRAINT_CATALOG", Catalog(), NOT_NULL, OPEN_FULL_TABLE), @@ -9698,13 +9543,6 @@ ST_SCHEMA_TABLE schema_tables[]= {"VIEWS", Show::view_fields_info, 0, get_all_tables, 0, get_schema_views_record, 1, 2, 0, OPEN_VIEW_ONLY|OPTIMIZE_I_S_TABLE}, -#ifdef HAVE_SPATIAL - {"GEOMETRY_COLUMNS", Show::geometry_columns_fields_info, 0, - get_all_tables, make_columns_old_format, get_geometry_column_record, - 1, 2, 0, OPTIMIZE_I_S_TABLE|OPEN_VIEW_FULL}, - {"SPATIAL_REF_SYS", Show::spatial_ref_sys_fields_info, 0, - fill_spatial_ref_sys, make_old_format, 0, -1, -1, 0, 0}, -#endif /*HAVE_SPATIAL*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; diff --git a/sql/sql_show.h b/sql/sql_show.h index bc566bffad0..fc3024c5a8b 100644 --- a/sql/sql_show.h +++ b/sql/sql_show.h @@ -76,6 +76,10 @@ typedef struct system_status_var STATUS_VAR; #define IS_FILES_EXTRA 37 typedef enum { WITHOUT_DB_NAME, WITH_DB_NAME } enum_with_db_name; + +int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond); +bool optimize_for_get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond); + int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, Table_specification_st *create_info_arg, enum_with_db_name with_db_name);