@@ -87,7 +87,7 @@ typedef struct parsing_info_st
87
87
static THD* get_or_create_thd_for_parsing (MYSQL* mysql, char * query_str);
88
88
static unsigned long set_client_flags (MYSQL* mysql);
89
89
static bool create_parse_tree (THD* thd);
90
- static uint32_t resolve_query_type (THD* thd);
90
+ static uint32_t resolve_query_type (parsing_info_t *, THD* thd);
91
91
static bool skygw_stmt_causes_implicit_commit (LEX* lex, int * autocommit_stmt);
92
92
93
93
static int is_autocommit_stmt (LEX* lex);
@@ -167,7 +167,7 @@ uint32_t qc_get_type(GWBUF* querybuf)
167
167
/* * Find out the query type */
168
168
if (mysql != NULL )
169
169
{
170
- qtype = resolve_query_type ((THD *) mysql->thd );
170
+ qtype = resolve_query_type (pi , (THD *) mysql->thd );
171
171
}
172
172
}
173
173
}
@@ -435,9 +435,102 @@ static bool create_parse_tree(THD* thd)
435
435
return failp;
436
436
}
437
437
438
+ /* *
439
+ * Sniff whether the statement is
440
+ *
441
+ * SET ROLE ...
442
+ * SET NAMES ...
443
+ * SET PASSWORD ...
444
+ * SET CHARACTER ...
445
+ *
446
+ * Depending on what kind of SET statement it is, the parser of the embedded
447
+ * library creates instances of set_var_user, set_var, set_var_password,
448
+ * set_var_role, etc. that all are derived from set_var_base. However, there
449
+ * is no type-information available in set_var_base, which is the type of the
450
+ * instances when accessed from the lexer. Consequently, we cannot know what
451
+ * kind of statment it is based on that, only whether it is a system variable
452
+ * or not.
453
+ *
454
+ * Consequently, we just look at the string and deduce whether it is a
455
+ * set [ROLE|NAMES|PASSWORD|CHARACTER] statement.
456
+ */
457
+ bool is_set_specific (const char * s)
458
+ {
459
+ bool rv = false ;
460
+
461
+ // Remove space from the beginning.
462
+ while (isspace (*s))
463
+ {
464
+ ++s;
465
+ }
466
+
467
+ const char * token = s;
468
+
469
+ // Find next non-space character.
470
+ while (!isspace (*s) && (*s != 0 ))
471
+ {
472
+ ++s;
473
+ }
474
+
475
+ if (s - token == 3 ) // Might be "set"
476
+ {
477
+ if (strncasecmp (token, " set" , 3 ) == 0 )
478
+ {
479
+ // YES it was!
480
+ while (isspace (*s))
481
+ {
482
+ ++s;
483
+ }
484
+
485
+ token = s;
486
+
487
+ while (!isspace (*s) && (*s != 0 ) && (*s != ' =' ))
488
+ {
489
+ ++s;
490
+ }
491
+
492
+ if (s - token == 4 ) // Might be "role"
493
+ {
494
+ if (strncasecmp (token, " role" , 4 ) == 0 )
495
+ {
496
+ // YES it was!
497
+ rv = true ;
498
+ }
499
+ }
500
+ else if (s - token == 5 ) // Might be "names"
501
+ {
502
+ if (strncasecmp (token, " names" , 5 ) == 0 )
503
+ {
504
+ // YES it was!
505
+ rv = true ;
506
+ }
507
+ }
508
+ else if (s - token == 8 ) // Might be "password
509
+ {
510
+ if (strncasecmp (token, " password" , 8 ) == 0 )
511
+ {
512
+ // YES it was!
513
+ rv = true ;
514
+ }
515
+ }
516
+ else if (s - token == 9 ) // Might be "character"
517
+ {
518
+ if (strncasecmp (token, " character" , 9 ) == 0 )
519
+ {
520
+ // YES it was!
521
+ rv = true ;
522
+ }
523
+ }
524
+ }
525
+ }
526
+
527
+ return rv;
528
+ }
529
+
438
530
/* *
439
531
* Detect query type by examining parsed representation of it.
440
532
*
533
+ * @param pi The parsing info.
441
534
* @param thd MariaDB thread context.
442
535
*
443
536
* @return Copy of query type value.
@@ -449,7 +542,7 @@ static bool create_parse_tree(THD* thd)
449
542
* the resulting type may be different.
450
543
*
451
544
*/
452
- static uint32_t resolve_query_type (THD* thd)
545
+ static uint32_t resolve_query_type (parsing_info_t * pi , THD* thd)
453
546
{
454
547
qc_query_type_t qtype = QUERY_TYPE_UNKNOWN;
455
548
uint32_t type = QUERY_TYPE_UNKNOWN;
@@ -565,7 +658,33 @@ static uint32_t resolve_query_type(THD* thd)
565
658
else if (lex->sql_command == SQLCOM_SET_OPTION)
566
659
{
567
660
/* * Either user- or system variable write */
568
- type |= QUERY_TYPE_GSYSVAR_WRITE;
661
+ if (is_set_specific (pi ->pi_query_plain_str ))
662
+ {
663
+ type |= QUERY_TYPE_GSYSVAR_WRITE;
664
+ }
665
+ else
666
+ {
667
+ List_iterator<set_var_base> ilist (lex->var_list );
668
+ size_t n = 0 ;
669
+
670
+ while (set_var_base *var = ilist++)
671
+ {
672
+ if (var->is_system ())
673
+ {
674
+ type |= QUERY_TYPE_GSYSVAR_WRITE;
675
+ }
676
+ else
677
+ {
678
+ type |= QUERY_TYPE_USERVAR_WRITE;
679
+ }
680
+ ++n;
681
+ }
682
+
683
+ if (n == 0 )
684
+ {
685
+ type |= QUERY_TYPE_GSYSVAR_WRITE;
686
+ }
687
+ }
569
688
}
570
689
571
690
goto return_qtype;
@@ -812,12 +931,7 @@ static uint32_t resolve_query_type(THD* thd)
812
931
813
932
/* * User-defined variable modification */
814
933
case Item_func::SUSERVAR_FUNC:
815
- /* *
816
- * Really it is user variable but we
817
- * don't separate sql variables atm.
818
- * 15.9.14
819
- */
820
- func_qtype |= QUERY_TYPE_GSYSVAR_WRITE;
934
+ func_qtype |= QUERY_TYPE_USERVAR_WRITE;
821
935
MXS_DEBUG (" %lu [resolve_query_type] "
822
936
" functype SUSERVAR_FUNC, user "
823
937
" variable write." ,
0 commit comments