Skip to content

Commit 8ccd404

Browse files
Aleksander Wasazniknryeng
Aleksander Wasaznik
authored andcommitted
WL#9059: [5/8] CREATE SPATIAL REFERENCE SYSTEM
Add SQL command CREATE [OR REPLACE] SPATIAL REFERENCE SYSTEM. This includes: - New keywords (none of them are reserved words) - New grammar for CREATE statements - Modification of some existing grammar to avoid conflicts - Class Sql_cmd_create_srs to implement the actual SRS creation - A number of new error messages for situations that may occur during SRS creation Change-Id: Ifdaf83a52923556b068be7c3d76c905d12c14260
1 parent 50a22e1 commit 8ccd404

17 files changed

+741
-15
lines changed

include/my_sqlcommand.h

+1
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ enum enum_sql_command {
193193
SQLCOM_LOCK_INSTANCE,
194194
SQLCOM_UNLOCK_INSTANCE,
195195
SQLCOM_RESTART_SERVER,
196+
SQLCOM_CREATE_SRS,
196197
/* This should be the last !!! */
197198
SQLCOM_END
198199
};

include/mysql/plugin_audit.h.pp

+1
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@
330330
SQLCOM_LOCK_INSTANCE,
331331
SQLCOM_UNLOCK_INSTANCE,
332332
SQLCOM_RESTART_SERVER,
333+
SQLCOM_CREATE_SRS,
333334
SQLCOM_END
334335
};
335336
typedef enum

mysql-test/r/mysqld--help-notwin.result

+1-1
Original file line numberDiff line numberDiff line change
@@ -1562,7 +1562,7 @@ performance-schema-max-socket-classes 10
15621562
performance-schema-max-socket-instances -1
15631563
performance-schema-max-sql-text-length 1024
15641564
performance-schema-max-stage-classes 150
1565-
performance-schema-max-statement-classes 210
1565+
performance-schema-max-statement-classes 211
15661566
performance-schema-max-statement-stack 10
15671567
performance-schema-max-table-handles -1
15681568
performance-schema-max-table-instances -1

mysql-test/r/mysqld--help-win.result

+1-1
Original file line numberDiff line numberDiff line change
@@ -1557,7 +1557,7 @@ performance-schema-max-socket-classes 10
15571557
performance-schema-max-socket-instances -1
15581558
performance-schema-max-sql-text-length 1024
15591559
performance-schema-max-stage-classes 150
1560-
performance-schema-max-statement-classes 210
1560+
performance-schema-max-statement-classes 211
15611561
performance-schema-max-statement-stack 10
15621562
performance-schema-max-table-handles -1
15631563
performance-schema-max-table-instances -1

share/errmsg-utf8.txt

+33
Original file line numberDiff line numberDiff line change
@@ -11514,6 +11514,39 @@ ER_RESTART_SERVER_FAILED
1151411514
ER_RESTART_RECEIVED_INFO
1151511515
eng "Received RESTART from user %s. Restarting mysqld (Version: %s)."
1151611516

11517+
ER_SRS_MISSING_MANDATORY_ATTRIBUTE SR006
11518+
eng "Missing mandatory attribute %s."
11519+
11520+
ER_SRS_MULTIPLE_ATTRIBUTE_DEFINITIONS SR006
11521+
eng "Multiple definitions of attribute %s."
11522+
11523+
ER_SRS_NAME_CANT_BE_EMPTY_OR_WHITESPACE SR006
11524+
eng "The spatial reference system name can't be an empty string or start or end with whitespace."
11525+
11526+
ER_SRS_ORGANIZATION_CANT_BE_EMPTY_OR_WHITESPACE SR006
11527+
eng "The organization name can't be an empty string or start or end with whitespace."
11528+
11529+
ER_SRS_ID_ALREADY_EXISTS SR004
11530+
eng "There is already a spatial reference system with SRID %u."
11531+
11532+
ER_WARN_SRS_ID_ALREADY_EXISTS 01S00
11533+
eng "There is already a spatial reference system with SRID %u."
11534+
11535+
ER_CANT_MODIFY_SRID_0 SR000
11536+
eng "SRID 0 is not modifiable."
11537+
11538+
ER_WARN_RESERVED_SRID_RANGE 01S01
11539+
eng "The SRID range [%u, %u] has been reserved for system use. SRSs in this range may be added, modified or removed without warning during upgrade."
11540+
11541+
ER_CANT_MODIFY_SRS_USED_BY_COLUMN SR005
11542+
eng "Can't modify SRID %u. There is at least one column depending on it."
11543+
11544+
ER_SRS_INVALID_CHARACTER_IN_ATTRIBUTE SR006
11545+
eng "Invalid character in attribute %s."
11546+
11547+
ER_SRS_ATTRIBUTE_STRING_TOO_LONG SR006
11548+
eng "Attribute %s is too long. The maximum length is %u characters."
11549+
1151711550
#
1151811551
# End of 8.0 error messages.
1151911552
#

sql/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ SET(SQL_SHARED_SOURCES
388388
sql_class.cc
389389
sql_component.cc
390390
sql_cmd_ddl_table.cc
391+
sql_cmd_srs.cc
391392
sql_connect.cc
392393
sql_cursor.cc
393394
sql_data_change.cc

sql/dd/impl/tables/spatial_reference_systems.cc

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ const Spatial_reference_systems & Spatial_reference_systems::instance()
3838

3939
Spatial_reference_systems::Spatial_reference_systems()
4040
{
41+
// Note: The maximum length of various strings is hard-coded here. These
42+
// lengths must match those in sql/sql_cmd_srs.cc.
43+
4144
m_target_def.table_name(table_name());
4245

4346
m_target_def.add_field(FIELD_ID,

sql/lex.h

+4
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,13 @@ static const SYMBOL symbols[] = {
186186
{ SYM("DEFAULT", DEFAULT_SYM)},
187187
{ SYM("DEFAULT_AUTH", DEFAULT_AUTH_SYM)},
188188
{ SYM("DEFINER", DEFINER_SYM)},
189+
{ SYM("DEFINITION", DEFINITION_SYM)},
189190
{ SYM("DELAYED", DELAYED_SYM)},
190191
{ SYM("DELAY_KEY_WRITE", DELAY_KEY_WRITE_SYM)},
191192
{ SYM("DENSE_RANK", DENSE_RANK_SYM)},
192193
{ SYM("DESC", DESC)},
193194
{ SYM("DESCRIBE", DESCRIBE)},
195+
{ SYM("DESCRIPTION", DESCRIPTION_SYM)},
194196
{ SYM("DETERMINISTIC", DETERMINISTIC_SYM)},
195197
{ SYM("DIAGNOSTICS", DIAGNOSTICS_SYM)},
196198
{ SYM("DIRECTORY", DIRECTORY_SYM)},
@@ -458,6 +460,7 @@ static const SYMBOL symbols[] = {
458460
{ SYM("OPTION", OPTION)},
459461
{ SYM("OPTIONALLY", OPTIONALLY)},
460462
{ SYM("OR", OR_SYM)},
463+
{ SYM("ORGANIZATION", ORGANIZATION_SYM)},
461464
{ SYM("OTHERS", OTHERS_SYM)},
462465
{ SYM("ORDER", ORDER_SYM)},
463466
{ SYM("ORDINALITY", ORDINALITY_SYM)},
@@ -515,6 +518,7 @@ static const SYMBOL symbols[] = {
515518
{ SYM("RECURSIVE", RECURSIVE_SYM)},
516519
{ SYM("REDO_BUFFER_SIZE", REDO_BUFFER_SIZE_SYM)},
517520
{ SYM("REDUNDANT", REDUNDANT_SYM)},
521+
{ SYM("REFERENCE", REFERENCE_SYM)},
518522
{ SYM("REFERENCES", REFERENCES)},
519523
{ SYM("REGEXP", REGEXP)},
520524
{ SYM("RELAY", RELAY)},

sql/mysqld.cc

+1
Original file line numberDiff line numberDiff line change
@@ -3136,6 +3136,7 @@ SHOW_VAR com_status_vars[]= {
31363136
{"create_udf", (char*) offsetof(System_status_var, com_stat[(uint) SQLCOM_CREATE_FUNCTION]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
31373137
{"create_user", (char*) offsetof(System_status_var, com_stat[(uint) SQLCOM_CREATE_USER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
31383138
{"create_view", (char*) offsetof(System_status_var, com_stat[(uint) SQLCOM_CREATE_VIEW]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3139+
{"create_spatial_reference_system", (char*) offsetof(System_status_var, com_stat[(uint) SQLCOM_CREATE_SRS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
31393140
{"dealloc_sql", (char*) offsetof(System_status_var, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
31403141
{"delete", (char*) offsetof(System_status_var, com_stat[(uint) SQLCOM_DELETE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
31413142
{"delete_multi", (char*) offsetof(System_status_var, com_stat[(uint) SQLCOM_DELETE_MULTI]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},

sql/parse_tree_nodes.h

+222
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#ifndef PARSE_TREE_NODES_INCLUDED
1717
#define PARSE_TREE_NODES_INCLUDED
1818

19+
#include <cctype> // std::isspace
20+
#include <limits>
1921
#include <stddef.h>
2022
#include <sys/types.h>
2123

@@ -56,6 +58,7 @@
5658
#include "sql/sql_admin.h" // Sql_cmd_shutdown etc.
5759
#include "sql/sql_alter.h"
5860
#include "sql/sql_class.h" // THD
61+
#include "sql/sql_cmd_srs.h"
5962
#include "sql/sql_exchange.h"
6063
#include "sql/sql_lex.h" // LEX
6164
#include "sql/sql_list.h"
@@ -2723,6 +2726,225 @@ class PT_shutdown final : public Parse_tree_root
27232726
};
27242727

27252728

2729+
/**
2730+
Top-level node for the CREATE [OR REPLACE] SPATIAL REFERENCE SYSTEM statement.
2731+
2732+
@ingroup ptn_stmt
2733+
*/
2734+
class PT_create_srs final : public Parse_tree_root
2735+
{
2736+
/// The SQL command object.
2737+
Sql_cmd_create_srs sql_cmd;
2738+
/// Whether OR REPLACE is specified.
2739+
bool m_or_replace;
2740+
/// Whether IF NOT EXISTS is specified.
2741+
bool m_if_not_exists;
2742+
/// SRID of the SRS to create.
2743+
///
2744+
/// The range is larger than that of gis::srid_t, so it must be
2745+
/// verified to be less than the uint32 maximum value.
2746+
unsigned long long m_srid;
2747+
/// All attributes except SRID.
2748+
const Sql_cmd_srs_attributes &m_attributes;
2749+
2750+
/// Check if a UTF-8 string contains control characters.
2751+
///
2752+
/// @note This function only checks single byte control characters (U+0000 to
2753+
/// U+001F, and U+007F). There are some control characters at U+0080 to U+00A0
2754+
/// that are not detected by this function.
2755+
///
2756+
/// @param str The string.
2757+
/// @param length Length of the string.
2758+
///
2759+
/// @retval false The string contains no control characters.
2760+
/// @retval true The string contains at least one control character.
2761+
bool contains_control_char(char *str, size_t length)
2762+
{
2763+
for (size_t pos= 0; pos < length; pos++)
2764+
{
2765+
if (std::iscntrl(str[pos]))
2766+
return true;
2767+
}
2768+
return false;
2769+
}
2770+
2771+
public:
2772+
PT_create_srs (unsigned long long srid,
2773+
const Sql_cmd_srs_attributes &attributes,
2774+
bool or_replace, bool if_not_exists)
2775+
: m_or_replace(or_replace), m_if_not_exists(if_not_exists), m_srid(srid),
2776+
m_attributes(attributes)
2777+
{}
2778+
2779+
Sql_cmd *make_cmd(THD *thd) override
2780+
{
2781+
// Note: This function hard-codes the maximum length of various
2782+
// strings. These lengths must match those in
2783+
// sql/dd/impl/tables/spatial_reference_systems.cc.
2784+
2785+
thd->lex->sql_command= SQLCOM_CREATE_SRS;
2786+
2787+
if (m_srid > std::numeric_limits<gis::srid_t>::max())
2788+
{
2789+
my_error(ER_DATA_OUT_OF_RANGE, MYF(0), "SRID",
2790+
m_or_replace ? "CREATE OR REPLACE SPATIAL REFERENCE SYSTEM"
2791+
: "CREATE SPATIAL REFERENCE SYSTEM");
2792+
return nullptr;
2793+
}
2794+
if (m_srid == 0)
2795+
{
2796+
my_error(ER_CANT_MODIFY_SRID_0, MYF(0));
2797+
return nullptr;
2798+
}
2799+
2800+
if (m_attributes.srs_name.str == nullptr)
2801+
{
2802+
my_error(ER_SRS_MISSING_MANDATORY_ATTRIBUTE, MYF(0), "NAME");
2803+
return nullptr;
2804+
}
2805+
MYSQL_LEX_STRING srs_name_utf8= {nullptr, 0};
2806+
if (thd->convert_string(&srs_name_utf8,
2807+
&my_charset_utf8_bin,
2808+
m_attributes.srs_name.str,
2809+
m_attributes.srs_name.length,
2810+
thd->charset()))
2811+
{
2812+
/* purecov: begin inspected */
2813+
my_error(ER_OOM, MYF(0));
2814+
return nullptr;
2815+
/* purecov: end */
2816+
}
2817+
if (srs_name_utf8.length == 0 ||
2818+
std::isspace(srs_name_utf8.str[0]) ||
2819+
std::isspace(srs_name_utf8.str[srs_name_utf8.length - 1]))
2820+
{
2821+
my_error(ER_SRS_NAME_CANT_BE_EMPTY_OR_WHITESPACE, MYF(0));
2822+
return nullptr;
2823+
}
2824+
if (contains_control_char(srs_name_utf8.str, srs_name_utf8.length))
2825+
{
2826+
my_error(ER_SRS_INVALID_CHARACTER_IN_ATTRIBUTE, MYF(0), "NAME");
2827+
return nullptr;
2828+
}
2829+
String srs_name_str(srs_name_utf8.str, srs_name_utf8.length,
2830+
&my_charset_utf8_bin);
2831+
if (srs_name_str.numchars() > 80)
2832+
{
2833+
my_error(ER_SRS_ATTRIBUTE_STRING_TOO_LONG, MYF(0), "NAME", 80);
2834+
return nullptr;
2835+
}
2836+
2837+
if (m_attributes.definition.str == nullptr)
2838+
{
2839+
my_error(ER_SRS_MISSING_MANDATORY_ATTRIBUTE, MYF(0), "DEFINITION");
2840+
return nullptr;
2841+
}
2842+
MYSQL_LEX_STRING definition_utf8= {nullptr, 0};
2843+
if (thd->convert_string(&definition_utf8,
2844+
&my_charset_utf8_bin,
2845+
m_attributes.definition.str,
2846+
m_attributes.definition.length,
2847+
thd->charset()))
2848+
{
2849+
/* purecov: begin inspected */
2850+
my_error(ER_OOM, MYF(0));
2851+
return nullptr;
2852+
/* purecov: end */
2853+
}
2854+
String definition_str(definition_utf8.str, definition_utf8.length,
2855+
&my_charset_utf8_bin);
2856+
if (contains_control_char(definition_utf8.str, definition_utf8.length))
2857+
{
2858+
my_error(ER_SRS_INVALID_CHARACTER_IN_ATTRIBUTE, MYF(0), "DEFINITION");
2859+
return nullptr;
2860+
}
2861+
if (definition_str.numchars() > 4096)
2862+
{
2863+
my_error(ER_SRS_ATTRIBUTE_STRING_TOO_LONG, MYF(0), "DEFINITION", 4096);
2864+
return nullptr;
2865+
}
2866+
2867+
MYSQL_LEX_STRING organization_utf8= {nullptr, 0};
2868+
if (m_attributes.organization.str != nullptr)
2869+
{
2870+
if (thd->convert_string(&organization_utf8,
2871+
&my_charset_utf8_bin,
2872+
m_attributes.organization.str,
2873+
m_attributes.organization.length,
2874+
thd->charset()))
2875+
{
2876+
/* purecov: begin inspected */
2877+
my_error(ER_OOM, MYF(0));
2878+
return nullptr;
2879+
/* purecov: end */
2880+
}
2881+
if (organization_utf8.length == 0 ||
2882+
std::isspace(organization_utf8.str[0]) ||
2883+
std::isspace(organization_utf8.str[organization_utf8.length - 1]))
2884+
{
2885+
my_error(ER_SRS_ORGANIZATION_CANT_BE_EMPTY_OR_WHITESPACE, MYF(0));
2886+
return nullptr;
2887+
}
2888+
String organization_str(organization_utf8.str, organization_utf8.length,
2889+
&my_charset_utf8_bin);
2890+
if (contains_control_char(organization_utf8.str,
2891+
organization_utf8.length))
2892+
{
2893+
my_error(ER_SRS_INVALID_CHARACTER_IN_ATTRIBUTE, MYF(0), "ORGANIZATION");
2894+
return nullptr;
2895+
}
2896+
if (organization_str.numchars() > 256)
2897+
{
2898+
my_error(ER_SRS_ATTRIBUTE_STRING_TOO_LONG, MYF(0), "ORGANIZATION", 256);
2899+
return nullptr;
2900+
}
2901+
2902+
if (m_attributes.organization_coordsys_id >
2903+
std::numeric_limits<gis::srid_t>::max())
2904+
{
2905+
my_error(ER_DATA_OUT_OF_RANGE, MYF(0), "IDENTIFIED BY",
2906+
m_or_replace ? "CREATE OR REPLACE SPATIAL REFERENCE SYSTEM"
2907+
: "CREATE SPATIAL REFERENCE SYSTEM");
2908+
return nullptr;
2909+
}
2910+
}
2911+
2912+
MYSQL_LEX_STRING description_utf8= {nullptr, 0};
2913+
if (m_attributes.description.str != nullptr)
2914+
{
2915+
if (thd->convert_string(&description_utf8,
2916+
&my_charset_utf8_bin,
2917+
m_attributes.description.str,
2918+
m_attributes.description.length,
2919+
thd->charset()))
2920+
{
2921+
/* purecov: begin inspected */
2922+
my_error(ER_OOM, MYF(0));
2923+
return nullptr;
2924+
/* purecov: end */
2925+
}
2926+
String description_str(description_utf8.str, description_utf8.length,
2927+
&my_charset_utf8_bin);
2928+
if (contains_control_char(description_utf8.str, description_utf8.length))
2929+
{
2930+
my_error(ER_SRS_INVALID_CHARACTER_IN_ATTRIBUTE, MYF(0), "DESCRIPTION");
2931+
return nullptr;
2932+
}
2933+
if (description_str.numchars() > 2048)
2934+
{
2935+
my_error(ER_SRS_ATTRIBUTE_STRING_TOO_LONG, MYF(0), "DESCRIPTION", 2048);
2936+
return nullptr;
2937+
}
2938+
}
2939+
2940+
sql_cmd.init(m_or_replace, m_if_not_exists, m_srid, srs_name_utf8,
2941+
definition_utf8, organization_utf8,
2942+
m_attributes.organization_coordsys_id, description_utf8);
2943+
return &sql_cmd;
2944+
}
2945+
};
2946+
2947+
27262948
/**
27272949
Top-level node for the ALTER INSTANCE statement
27282950

sql/sp.cc

+1
Original file line numberDiff line numberDiff line change
@@ -2530,6 +2530,7 @@ uint sp_get_flags_for_command(LEX *lex)
25302530
case SQLCOM_ALTER_INSTANCE:
25312531
case SQLCOM_CREATE_ROLE:
25322532
case SQLCOM_DROP_ROLE:
2533+
case SQLCOM_CREATE_SRS:
25332534
flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
25342535
break;
25352536
default:

0 commit comments

Comments
 (0)