summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2019-02-14 14:29:55 +0400
committerAlexander Barkov <bar@mariadb.com>2019-02-15 19:46:58 +0400
commit62c0ac2da66f8e26d5bbf79f3a7dac56cad34f5e (patch)
tree236c9941fda1fc889ccc9f684c418bf1720f9a17 /sql
parent568dd5293ca7ef34f74d5d0529288edba6b7281e (diff)
downloadmariadb-git-62c0ac2da66f8e26d5bbf79f3a7dac56cad34f5e.tar.gz
A cleanup for MDEV-13916 Enforce check constraint on JSON type
1. Renaming Type_handler_json to Type_handler_json_longtext There will be other JSON handlers soon, e.g. Type_handler_json_varchar. 2. Making the code more symmetric for data types: - Adding a new virtual method Type_handler::Column_definition_validate_check_constraint() - Moving JSON-specific code from sql_yacc.yy to Type_handler_json_longtext::Column_definition_validate_check_constraint() 3. Adding new files sql_type_json.cc and sql_type_json.h and moving Type_handler+JSON related code into these files.
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt2
-rw-r--r--sql/field.cc12
-rw-r--r--sql/field.h1
-rw-r--r--sql/sql_lex.cc18
-rw-r--r--sql/sql_lex.h3
-rw-r--r--sql/sql_type.cc12
-rw-r--r--sql/sql_type.h15
-rw-r--r--sql/sql_type_json.cc55
-rw-r--r--sql/sql_type_json.h38
-rw-r--r--sql/sql_yacc.yy7
-rw-r--r--sql/sql_yacc_ora.yy7
11 files changed, 125 insertions, 45 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 0befcd25204..18b7cc3176d 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -132,7 +132,7 @@ SET (SQL_SOURCE
rpl_gtid.cc rpl_parallel.cc
semisync.cc semisync_master.cc semisync_slave.cc
semisync_master_ack_receiver.cc
- sql_type.cc
+ sql_type.cc sql_type_json.cc
item_windowfunc.cc sql_window.cc
sql_cte.cc
item_vers.cc
diff --git a/sql/field.cc b/sql/field.cc
index 89b04c4d795..5289798cebf 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -10501,6 +10501,13 @@ bool Column_definition::fix_attributes_temporal_with_time(uint int_part_length)
}
+bool Column_definition::validate_check_constraint(THD *thd)
+{
+ return check_constraint &&
+ check_expression(check_constraint, &field_name, VCOL_CHECK_FIELD);
+}
+
+
bool Column_definition::check(THD *thd)
{
DBUG_ENTER("Column_definition::check");
@@ -10515,9 +10522,8 @@ bool Column_definition::check(THD *thd)
DBUG_RETURN(TRUE);
}
- if (check_constraint &&
- check_expression(check_constraint, &field_name, VCOL_CHECK_FIELD))
- DBUG_RETURN(1);
+ if (type_handler()->Column_definition_validate_check_constraint(thd, this))
+ DBUG_RETURN(TRUE);
if (default_value)
{
diff --git a/sql/field.h b/sql/field.h
index 25d9f0e0ca4..30098afe953 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -4675,6 +4675,7 @@ public:
bool fix_attributes_bit();
bool check(THD *thd);
+ bool validate_check_constraint(THD *thd);
bool stored_in_db() const { return !vcol_info || vcol_info->stored_in_db; }
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index f5e37446b58..df4d8d7b94c 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -9587,21 +9587,3 @@ bool LEX::sp_proc_stmt_statement_finalize(THD *thd, bool no_lookahead)
lip->get_tok_start());
return LEX::sp_proc_stmt_statement_finalize_buf(thd, qbuf);
}
-
-
-/**
- Create JSON_VALID(field_name) expression
-*/
-
-Virtual_column_info *make_json_valid_expr(THD *thd, LEX_CSTRING *field_name)
-{
- Lex_ident_sys_st str;
- Item *field, *expr;
- str.set_valid_utf8(field_name);
- if (unlikely(!(field= thd->lex->create_item_ident_field(thd, NullS, NullS,
- &str))))
- return 0;
- if (unlikely(!(expr= new (thd->mem_root) Item_func_json_valid(thd, field))))
- return 0;
- return add_virtual_expression(thd, expr);
-}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index fc451b21816..3f3fef8a414 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -148,7 +148,7 @@ public:
bool copy_or_convert(THD *thd, const Lex_ident_cli_st *str, CHARSET_INFO *cs);
bool is_null() const { return str == NULL; }
bool to_size_number(ulonglong *to) const;
- void set_valid_utf8(LEX_CSTRING *name)
+ void set_valid_utf8(const LEX_CSTRING *name)
{
DBUG_ASSERT(Well_formed_prefix(system_charset_info, name->str,
name->length).length() == name->length);
@@ -4640,6 +4640,5 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
void sp_create_assignment_lex(THD *thd, bool no_lookahead);
bool sp_create_assignment_instr(THD *thd, bool no_lookahead);
-Virtual_column_info *make_json_valid_expr(THD *thd, LEX_CSTRING *field_name);
#endif /* MYSQL_SERVER */
#endif /* SQL_LEX_INCLUDED */
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 1812294ed46..4906eee064d 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -66,7 +66,6 @@ Type_handler_tiny_blob type_handler_tiny_blob;
Type_handler_medium_blob type_handler_medium_blob;
Type_handler_long_blob type_handler_long_blob;
Type_handler_blob type_handler_blob;
-Type_handler_json type_handler_json;
static Type_handler_blob_compressed type_handler_blob_compressed;
Type_handler_interval_DDhhmmssff type_handler_interval_DDhhmmssff;
@@ -2328,6 +2327,17 @@ Field *Type_handler_set::make_conversion_table_field(TABLE *table,
((const Field_enum*) target)->typelib, target->charset());
}
+
+/*************************************************************************/
+
+bool Type_handler::
+ Column_definition_validate_check_constraint(THD *thd,
+ Column_definition * c) const
+{
+ return c->validate_check_constraint(thd);
+}
+
+
/*************************************************************************/
bool Type_handler_null::
Column_definition_fix_attributes(Column_definition *def) const
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 7216b24835d..23a3f7fccb7 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -78,6 +78,7 @@ struct Schema_specification_st;
struct TABLE;
struct SORT_FIELD_ATTR;
class Vers_history_point;
+class Virtual_column_info;
#define my_charset_numeric my_charset_latin1
@@ -3280,7 +3281,6 @@ public:
return true;
}
virtual bool is_scalar_type() const { return true; }
- virtual bool is_json_type() const { return false; }
virtual bool can_return_int() const { return true; }
virtual bool can_return_decimal() const { return true; }
virtual bool can_return_real() const { return true; }
@@ -3338,6 +3338,10 @@ public:
// Automatic upgrade, e.g. for ALTER TABLE t1 FORCE
virtual void Column_definition_implicit_upgrade(Column_definition *c) const
{ }
+ // Validate CHECK constraint after the parser
+ virtual bool Column_definition_validate_check_constraint(THD *thd,
+ Column_definition *c)
+ const;
// Fix attributes after the parser
virtual bool Column_definition_fix_attributes(Column_definition *c) const= 0;
/*
@@ -5895,14 +5899,6 @@ public:
};
-class Type_handler_json: public Type_handler_long_blob
-{
-public:
- virtual ~Type_handler_json() {}
- virtual bool is_json_type() const { return true; }
-};
-
-
class Type_handler_blob: public Type_handler_blob_common
{
static const Name m_name_blob;
@@ -6231,7 +6227,6 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_hex_hybrid type_handler_hex_hybrid;
extern MYSQL_PLUGIN_IMPORT Type_handler_tiny_blob type_handler_tiny_blob;
extern MYSQL_PLUGIN_IMPORT Type_handler_medium_blob type_handler_medium_blob;
extern MYSQL_PLUGIN_IMPORT Type_handler_long_blob type_handler_long_blob;
-extern MYSQL_PLUGIN_IMPORT Type_handler_json type_handler_json;
extern MYSQL_PLUGIN_IMPORT Type_handler_blob type_handler_blob;
extern MYSQL_PLUGIN_IMPORT Type_handler_bool type_handler_bool;
diff --git a/sql/sql_type_json.cc b/sql/sql_type_json.cc
new file mode 100644
index 00000000000..f53a247d816
--- /dev/null
+++ b/sql/sql_type_json.cc
@@ -0,0 +1,55 @@
+/*
+ Copyright (c) 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 "sql_type_json.h"
+#include "sql_class.h"
+
+
+Type_handler_json_longtext type_handler_json_longtext;
+
+
+/**
+ Create JSON_VALID(field_name) expression
+*/
+
+Virtual_column_info *
+Type_handler_json_longtext::make_json_valid_expr(THD *thd,
+ const LEX_CSTRING *field_name)
+ const
+{
+ Lex_ident_sys_st str;
+ Item *field, *expr;
+ str.set_valid_utf8(field_name);
+ if (unlikely(!(field= thd->lex->create_item_ident_field(thd, NullS, NullS,
+ &str))))
+ return 0;
+ if (unlikely(!(expr= new (thd->mem_root) Item_func_json_valid(thd, field))))
+ return 0;
+ return add_virtual_expression(thd, expr);
+}
+
+
+bool Type_handler_json_longtext::
+ Column_definition_validate_check_constraint(THD *thd,
+ Column_definition * c) const
+{
+ if (!c->check_constraint &&
+ !(c->check_constraint= make_json_valid_expr(thd, &c->field_name)))
+ return true;
+ return Type_handler::Column_definition_validate_check_constraint(thd, c);
+}
diff --git a/sql/sql_type_json.h b/sql/sql_type_json.h
new file mode 100644
index 00000000000..6c4ee8cb2eb
--- /dev/null
+++ b/sql/sql_type_json.h
@@ -0,0 +1,38 @@
+#ifndef SQL_TYPE_JSON_INCLUDED
+#define SQL_TYPE_JSON_INCLUDED
+/*
+ Copyright (c) 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 "mariadb.h"
+#include "sql_type.h"
+
+class Type_handler_json_longtext: public Type_handler_long_blob
+{
+ Virtual_column_info *make_json_valid_expr(THD *thd,
+ const LEX_CSTRING *field_name)
+ const;
+public:
+ virtual ~Type_handler_json_longtext() {}
+ bool Column_definition_validate_check_constraint(THD *thd,
+ Column_definition *c) const;
+};
+
+extern MYSQL_PLUGIN_IMPORT
+ Type_handler_json_longtext type_handler_json_longtext;
+
+#endif // SQL_TYPE_JSON_INCLUDED
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 0a2961b8154..00566c463e8 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -68,6 +68,7 @@
#include "sql_lex.h"
#include "sql_sequence.h"
#include "my_base.h"
+#include "sql_type_json.h"
/* this is to get the bison compilation windows warnings out */
#ifdef _MSC_VER
@@ -6689,10 +6690,6 @@ field_spec:
$$= $<create_field>2;
$$->check_constraint= $4;
- if (!$4 && lex->last_field->type_handler()->is_json_type() &&
- !($$->check_constraint= make_json_valid_expr(thd,
- &$$->field_name)))
- MYSQL_YYABORT;
if (unlikely($$->check(thd)))
MYSQL_YYABORT;
@@ -7086,7 +7083,7 @@ field_type_lob:
| JSON_SYM
{
Lex->charset= &my_charset_utf8mb4_bin;
- $$.set(&type_handler_json);
+ $$.set(&type_handler_json_longtext);
}
;
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 3bfb8347b13..025241f8e93 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -68,6 +68,7 @@
#include "sql_lex.h"
#include "sql_sequence.h"
#include "my_base.h"
+#include "sql_type_json.h"
/* this is to get the bison compilation windows warnings out */
#ifdef _MSC_VER
@@ -6627,10 +6628,6 @@ field_spec:
$$= $<create_field>2;
$$->check_constraint= $4;
- if (!$4 && lex->last_field->type_handler()->is_json_type() &&
- !($$->check_constraint= make_json_valid_expr(thd,
- &$$->field_name)))
- MYSQL_YYABORT;
if (unlikely($$->check(thd)))
MYSQL_YYABORT;
@@ -7076,7 +7073,7 @@ field_type_lob:
| JSON_SYM
{
Lex->charset= &my_charset_utf8mb4_bin;
- $$.set(&type_handler_json);
+ $$.set(&type_handler_json_longtext);
}
;