← Back to team overview

maria-developers team mailing list archive

GSoc2015

 

hii, please find a patch for MDEV-8343
<https://mariadb.atlassian.net/browse/MDEV-8343> attached to this mail. I
have also included a test case in the patch.

regards
Diwas Joshi
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index 4373925..58be47e 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -2866,3 +2866,9 @@ SELECT @msg;
 DROP FUNCTION f1;
 DROP FUNCTION f2;
 DROP TABLE t1;
+CREATE FUNCTION f1(a INT, b VARCHAR(11))
+RETURNS TABLE t1(id INT, name VARCHAR(11))
+BEGIN
+INSERT INTO t1 SELECT id, name FROM t2 WHERE id = a;
+END|
+ERROR 42000: This version of MariaDB doesn't yet support '%s' near 'Table functions' at line 3
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index c1a21c8..580f2b4 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -3845,3 +3845,14 @@ SELECT @msg;
 DROP FUNCTION f1;
 DROP FUNCTION f2;
 DROP TABLE t1;
+
+
+delimiter |;
+--error 1064
+CREATE FUNCTION f1(a INT, b VARCHAR(11))
+RETURNS TABLE t1(id INT, name VARCHAR(11))
+BEGIN
+INSERT INTO t1 SELECT id, name FROM t2 WHERE id = a;
+END|
+
+DELIMITER ;|
diff --git a/sql/sp.h b/sql/sp.h
index eb3291f..149077f 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -45,7 +45,8 @@ enum stored_procedure_type
   TYPE_ENUM_FUNCTION=1,
   TYPE_ENUM_PROCEDURE=2,
   TYPE_ENUM_TRIGGER=3,
-  TYPE_ENUM_PROXY=4
+  TYPE_ENUM_PROXY=4,
+  TYPE_ENUM_TABLE=5
 };
 
 /* Tells what SP_DEFAULT_ACCESS should be mapped to */
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 8efeeab..f705930 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -2360,6 +2360,34 @@ void sp_head::recursion_level_error(THD *thd)
   return FALSE;
 }
 
+bool
+sp_head::fill_resultset_definition(THD *thd, List<Create_field> *create_list)
+{
+    List_iterator_fast<Create_field> it(*create_list);
+    Create_field *field;
+    while ((field= it++))
+    {
+      Create_field *new_field = field->clone(thd->mem_root);
+      switch (new_field->sql_type) {
+        case MYSQL_TYPE_DATE:
+        case MYSQL_TYPE_NEWDATE:
+        case MYSQL_TYPE_TIME:
+        case MYSQL_TYPE_DATETIME:
+        case MYSQL_TYPE_TIMESTAMP:
+          new_field->charset= &my_charset_bin;
+        default: break;
+      }
+      if (!new_field->charset)
+         new_field->charset= default_charset_info;
+      if (!new_field->charset)
+         new_field->charset= system_charset_info;
+      if (new_field->interval_list.elements)
+          new_field->interval= create_typelib(thd->mem_root, new_field, &new_field->interval_list);
+      sp_prepare_create_field(thd, new_field);
+      if(m_cols_list.push_back(new_field, thd->mem_root))
+          return TRUE;
+    }
+}
 
 int
 sp_head::new_cont_backpatch(sp_instr_opt_meta *i)
diff --git a/sql/sp_head.h b/sql/sp_head.h
index dbdb957..4b2fe31 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -182,6 +182,7 @@ class sp_head :private Query_arena
   uint m_flags;                 // Boolean attributes of a stored routine
 
   Create_field m_return_field_def; /**< This is used for FUNCTIONs only. */
+  List<Create_field> m_cols_list; /**< Used for TABLE FUNCTIONs only. */
 
   const char *m_tmp_query;	///< Temporary pointer to sub query string
   st_sp_chistics *m_chistics;
@@ -196,6 +197,7 @@ class sp_head :private Query_arena
   LEX_STRING m_defstr;
   LEX_STRING m_definer_user;
   LEX_STRING m_definer_host;
+  LEX_STRING m_table_alias;
 
   /**
     Is this routine being executed?
@@ -420,6 +422,7 @@ class sp_head :private Query_arena
   bool fill_field_definition(THD *thd, LEX *lex,
                              enum enum_field_types field_type,
                              Create_field *field_def);
+  bool fill_resultset_definition(THD *thd, List<Create_field> *create_list);
 
   void set_info(longlong created, longlong modified,
 		st_sp_chistics *chistics, ulonglong sql_mode);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index cf933e0b..d3d905b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1731,7 +1731,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
 %type <string>
         text_string hex_or_bin_String opt_gconcat_separator
 
-%type <field_type> type_with_opt_collate int_type real_type field_type
+%type <field_type> type_with_opt_collate sf_type_with_opt_collate int_type real_type field_type
 
 %type <geom_type> spatial_type
 
@@ -6644,7 +6644,25 @@ type_with_opt_collate:
         }
         ;
 
-
+sf_type_with_opt_collate:
+          type_with_opt_collate
+          {
+            $$ = $1;
+          }
+        | TABLE_SYM ident '(' field_list ')'
+          {
+            Lex->sphead->m_table_alias= $2;
+            // table functions, we need to store the return types
+            Lex->sphead->m_type= TYPE_ENUM_TABLE;
+            if(Lex->sphead->fill_resultset_definition(thd, &Lex->alter_info.create_list))
+              MYSQL_YYABORT;
+            if (Lex->sphead->m_cols_list.is_empty())
+            {
+              my_parse_error(ER(ER_SYNTAX_ERROR));
+              MYSQL_YYABORT;
+            }
+          }
+        ;
 now_or_signed_literal:
           NOW_SYM opt_default_time_precision
           {
@@ -16283,11 +16301,15 @@ sf_tail:
             lex->init_last_field(&lex->sphead->m_return_field_def, NULL,
                                  thd->variables.collation_database);
           }
-          type_with_opt_collate /* $11 */
+          sf_type_with_opt_collate /* $11 */
           { /* $12 */
-            if (Lex->sphead->fill_field_definition(thd, Lex, $11,
-                                                   Lex->last_field))
-              MYSQL_YYABORT;
+            if (!(Lex->sphead->m_type== TYPE_ENUM_TABLE))
+            {
+                Lex->sphead->m_type = TYPE_ENUM_FUNCTION;
+                if (Lex->sphead->fill_field_definition(thd, Lex, $11,
+                                                       Lex->last_field))
+                  MYSQL_YYABORT;
+            }
           }
           sp_c_chistics /* $13 */
           { /* $14 */
@@ -16295,6 +16317,12 @@ sf_tail:
             Lex_input_stream *lip= YYLIP;
 
             lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
+            
+            if (Lex->sphead->m_type== TYPE_ENUM_TABLE) //to be removed later.
+            {
+              my_parse_error(ER(ER_NOT_SUPPORTED_YET), "Table functions");
+              MYSQL_YYABORT;
+            }
           }
           sp_proc_stmt /* $15 */
           {
@@ -16306,7 +16334,7 @@ sf_tail:
 
             lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
             sp->set_stmt_end(thd);
-            if (!(sp->m_flags & sp_head::HAS_RETURN))
+            if (!(sp->m_flags & sp_head::HAS_RETURN) && !(Lex->sphead->m_type== TYPE_ENUM_TABLE))
             {
               my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
               MYSQL_YYABORT;

Follow ups