Skip to content

Commit

Permalink
Return an error instead of assertion when using document path on a no…
Browse files Browse the repository at this point in the history
…n-document column

Summary: Assertion failure will happen when using document path on a non-document column, e.g. col.k1.k2.k3, while col is not a document column. This logic is wrong, an error should be returned. This diff fixes this.

Test Plan: Jenkins

Reviewers: santoshb, tianx

Reviewed By: tianx
  • Loading branch information
pengtfb authored and jtolmer committed Jan 5, 2016
1 parent eafc5f4 commit 28f6e60
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 8 deletions.
73 changes: 73 additions & 0 deletions mysql-test/suite/json/r/type_document_path.result
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,68 @@ SET @@global.allow_document_type = false;
SELECT @@global.allow_document_type;
@@global.allow_document_type
0
select b.k1 from t1;
ERROR 42S22: Unknown column 'b.k1' in 'field list'
select b.k1.k2 from t1;
ERROR 42S22: Unknown column 'b.k1.k2' in 'field list'
select b.k1.k2.k3 from t1;
ERROR HY000: Invalid field or reference.
SET @@global.allow_document_type = true;
SELECT @@global.allow_document_type;
@@global.allow_document_type
1
select b.k1 from t1;
ERROR 42S22: Unknown column 'b.k1' in 'field list'
select b.k1.k2 from t1;
ERROR 42S22: Unknown column 'b.k1.k2' in 'field list'
select b.k1.k2.k3 from t1;
ERROR 42S22: Unknown column 'b.k1.k2.k3' in 'field list'
select a from t1 where b.k1 = 100;
ERROR 42S22: Unknown column 'b.k1' in 'where clause'
select a from t1 where b.k1.k2 = 100;
ERROR 42S22: Unknown column 'b.k1.k2' in 'where clause'
select a from t1 where b.k1.k2.k3 = 100;
ERROR 42S22: Unknown column 'b.k1.k2.k3' in 'where clause'
select a from t1 order by b.k1;
ERROR 42S22: Unknown column 'b.k1' in 'order clause'
select a from t1 order by b.k1.k2 ;
ERROR 42S22: Unknown column 'b.k1.k2' in 'order clause'
select a from t1 order by b.k1.k2.k3;
ERROR 42S22: Unknown column 'b.k1.k2.k3' in 'order clause'
select count(*), a from t1 group by b.k1;
ERROR 42S22: Unknown column 'b.k1' in 'group statement'
select count(*), a from t1 group by b.k1.k2;
ERROR 42S22: Unknown column 'b.k1.k2' in 'group statement'
select count(*), a from t1 group by b.k1.k2.k3;
ERROR 42S22: Unknown column 'b.k1.k2.k3' in 'group statement'
select count(*), a from t1 group by a having b.k1 = 100;
ERROR 42S22: Unknown column 'b.k1' in 'having clause'
select count(*), a from t1 group by a having b.k1.k2 = 100;
ERROR 42S22: Unknown column 'b.k1.k2' in 'having clause'
select count(*), a from t1 group by a having b.k1.k2.k3 = 100;
ERROR HY000: Invalid field or reference.
select a from t1 having b.k1 = 100;
ERROR 42S22: Unknown column 'b.k1' in 'having clause'
select a from t1 having b.k1.k2 = 100;
ERROR 42S22: Unknown column 'b.k1.k2' in 'having clause'
select a from t1 having b.k1.k2.k3 = 100;
ERROR HY000: Invalid field or reference.
select a from t1 where substr(b.k1, 1, 10) like 'abc';
ERROR 42S22: Unknown column 'b.k1' in 'where clause'
select a from t1 where substr(b.k1.k2, 1, 10) like 'abc';
ERROR 42S22: Unknown column 'b.k1.k2' in 'where clause'
select a from t1 where substr(b.k1.k2.k3, 1, 10) like 'abc';
ERROR 42S22: Unknown column 'b.k1.k2.k3' in 'where clause'
select sum(b.k1) from t1 where a = 100;
ERROR 42S22: Unknown column 'b.k1' in 'field list'
select sum(b.k1.k2) from t1 where a = 100;
ERROR 42S22: Unknown column 'b.k1.k2' in 'field list'
select sum(b.k1.k2.k3) from t1 where a = 100;
ERROR 42S22: Unknown column 'b.k1.k2.k3' in 'field list'
SET @@global.allow_document_type = false;
SELECT @@global.allow_document_type;
@@global.allow_document_type
0
update t1 set t1.doc.id = 200 where a = 1;
ERROR 42S22: Unknown column 't1.doc.id' in 'field list'
SET @@global.allow_document_type = true;
Expand Down Expand Up @@ -207,6 +269,17 @@ Warning 1292 Truncated incorrect time value: '2014-11-01'
select test.t1.doc.address.houseNumber from t1 where test.t1.doc.address.zipcode = 98762;
doc
1002
select t1.a, t1.b from t1 where doc.address.zipcode = 98761;
a b
1 @1
update t1 set t1.a = 101, t1.b = '@101' where doc.address.zipcode = 98761;
select t1.a, t1.b from t1 where doc.address.zipcode = 98761;
a b
101 @101
update t1 set t1.a = 1, t1.b = '@1' where doc.address.zipcode = 98761;
select t1.a, t1.b from t1 where doc.address.zipcode = 98761;
a b
1 @1
select a from t1 order by test.t1.doc.NonExistent;
a
1
Expand Down
93 changes: 92 additions & 1 deletion mysql-test/suite/json/t/type_document_path.test
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ select a from t1 where test.t1.doc.id = 102;
--error ER_INVALID_FIELD_OR_REFERENCE
select test.t1.doc.address.houseNumber from t1 where test.t1.doc.address.zipcode = 98762;

### Enable document type
### Enable document type with the new parsing logic
SET @@global.allow_document_type = true;
SELECT @@global.allow_document_type;

Expand All @@ -130,6 +130,90 @@ select t1.doc from test.t1 where t1.a = 2;
select .t1.doc from test.t1 where .t1.a = 4;


################################################################################
###
### Invalid document path: using document path on a non-document column
###

### Disable document type to make parser work as before
SET @@global.allow_document_type = false;
SELECT @@global.allow_document_type;

--error ER_BAD_FIELD_ERROR
select b.k1 from t1;
--error ER_BAD_FIELD_ERROR
select b.k1.k2 from t1;
--error ER_INVALID_FIELD_OR_REFERENCE
select b.k1.k2.k3 from t1;

### Enable document type with the new parsing logic
SET @@global.allow_document_type = true;
SELECT @@global.allow_document_type;

## In SELECT
--error ER_BAD_FIELD_ERROR
select b.k1 from t1;
--error ER_BAD_FIELD_ERROR
select b.k1.k2 from t1;
--error ER_BAD_FIELD_ERROR
select b.k1.k2.k3 from t1;

## In WHERE
--error ER_BAD_FIELD_ERROR
select a from t1 where b.k1 = 100;
--error ER_BAD_FIELD_ERROR
select a from t1 where b.k1.k2 = 100;
--error ER_BAD_FIELD_ERROR
select a from t1 where b.k1.k2.k3 = 100;

## In ORDER BY
--error ER_BAD_FIELD_ERROR
select a from t1 order by b.k1;
--error ER_BAD_FIELD_ERROR
select a from t1 order by b.k1.k2 ;
--error ER_BAD_FIELD_ERROR
select a from t1 order by b.k1.k2.k3;

## In GROUP BY
--error ER_BAD_FIELD_ERROR
select count(*), a from t1 group by b.k1;
--error ER_BAD_FIELD_ERROR
select count(*), a from t1 group by b.k1.k2;
--error ER_BAD_FIELD_ERROR
select count(*), a from t1 group by b.k1.k2.k3;

## In HAVING
--error ER_BAD_FIELD_ERROR
select count(*), a from t1 group by a having b.k1 = 100;
--error ER_BAD_FIELD_ERROR
select count(*), a from t1 group by a having b.k1.k2 = 100;
--error ER_INVALID_FIELD_OR_REFERENCE
select count(*), a from t1 group by a having b.k1.k2.k3 = 100;

## In HAVING without GROUP BY then HAVING clause behaves like WHERE clause
--error ER_BAD_FIELD_ERROR
select a from t1 having b.k1 = 100;
--error ER_BAD_FIELD_ERROR
select a from t1 having b.k1.k2 = 100;
--error ER_INVALID_FIELD_OR_REFERENCE
select a from t1 having b.k1.k2.k3 = 100;

## In Functions
--error ER_BAD_FIELD_ERROR
select a from t1 where substr(b.k1, 1, 10) like 'abc';
--error ER_BAD_FIELD_ERROR
select a from t1 where substr(b.k1.k2, 1, 10) like 'abc';
--error ER_BAD_FIELD_ERROR
select a from t1 where substr(b.k1.k2.k3, 1, 10) like 'abc';

--error ER_BAD_FIELD_ERROR
select sum(b.k1) from t1 where a = 100;
--error ER_BAD_FIELD_ERROR
select sum(b.k1.k2) from t1 where a = 100;
--error ER_BAD_FIELD_ERROR
select sum(b.k1.k2.k3) from t1 where a = 100;


################################################################################
###
### Document partial update by document path is not supported yet
Expand Down Expand Up @@ -266,6 +350,13 @@ select test.t1.doc.dt from t1 where cast(test.t1.doc.dt as time) = cast('2014-11
### Document path in both SELECT and WHERE clause: database.table.field.key1.key2
select test.t1.doc.address.houseNumber from t1 where test.t1.doc.address.zipcode = 98762;

### Document paths in WHERE clause for UPDATE statements
select t1.a, t1.b from t1 where doc.address.zipcode = 98761;
update t1 set t1.a = 101, t1.b = '@101' where doc.address.zipcode = 98761;
select t1.a, t1.b from t1 where doc.address.zipcode = 98761;
update t1 set t1.a = 1, t1.b = '@1' where doc.address.zipcode = 98761;
select t1.a, t1.b from t1 where doc.address.zipcode = 98761;


################################################################################
###
Expand Down
38 changes: 31 additions & 7 deletions sql/item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2471,6 +2471,29 @@ Ident_parsing_info::Ident_parsing_info(THD *thd,
Copy_ident_list(thd, &p.dot_separated_ident_list);
}

const char* Ident_parsing_info::full_name(THD *thd)
{
List_iterator_fast<One_ident> it(dot_separated_ident_list);
uint sz = 0;
for (One_ident *s = NULL; (s= it++);)
{
sz += s->s.length;
++sz; /* for the '.' and the '\0' in the end */
}
char* buf = (char *)thd->alloc(sz);

it.rewind();
char *p = buf;
for (One_ident *s = NULL; (s= it++);)
{
memcpy(p, s->s.str, s->s.length);
p += s->s.length;
*p++ = '.';
}
buf[sz-1] = '\0';
return buf;
}

void Ident_parsing_info::Parse_and_set_document_path_keys(
THD *thd, List<Document_key>& list)
{
Expand Down Expand Up @@ -5618,15 +5641,16 @@ bool Item_field::fix_fields(THD *thd, Item **reference)

DBUG_ASSERT(!ret);

if (field)
if (field && parsing_info.num_unresolved_idents > 0)
{
DBUG_ASSERT(field->type() == MYSQL_TYPE_DOCUMENT ||
parsing_info.num_unresolved_idents == 0);
}
if (field->type() != MYSQL_TYPE_DOCUMENT)
{
/* syntax error when using document path on a non-document column */
my_error(ER_BAD_FIELD_ERROR, MYF(0),
parsing_info.full_name(thd), thd->where);
return true;
}

if (field && field->type() == MYSQL_TYPE_DOCUMENT &&
parsing_info.num_unresolved_idents > 0)
{
/* If the type of the field is document and there are still unresolved
dot separated identifiers then this whole expression will be treated
as a document virutal field.
Expand Down
5 changes: 5 additions & 0 deletions sql/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -2221,6 +2221,11 @@ class Ident_parsing_info
Ident_parsing_info(THD *thd,
Ident_parsing_info& p);

/*
generate the string of the dot separated expression
*/
const char* full_name(THD *thd);

/*
parse the original dot-separated key tokens and
set the document path keys
Expand Down

0 comments on commit 28f6e60

Please sign in to comment.