Skip to content

Commit f6360ea

Browse files
committed
WL12227: Indexing array fields
This WL is about creating indexes on document fields which contain arrays.
1 parent f270d59 commit f6360ea

File tree

4 files changed

+54
-35
lines changed

4 files changed

+54
-35
lines changed

lib/mysqlx/crud.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ def create_index(self, index_name, fields_desc):
395395
{"fields": [{"field": member_path,
396396
"type": member_type,
397397
"required": member_required,
398+
"array": array,
398399
"collation": collation,
399400
"options": options,
400401
"srid": srid},

lib/mysqlx/expr.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,6 @@ def parse_place_holder(self, token):
899899
raise ValueError("Invalid placeholder name at token pos {0}"
900900
"".format(self.pos))
901901

902-
place_holder_name = place_holder_name.lower()
903902
msg_expr = Message("Mysqlx.Expr.Expr")
904903
msg_expr["type"] = mysqlxpb_enum("Mysqlx.Expr.Expr.Type.PLACEHOLDER")
905904
if place_holder_name in self.placeholder_name_to_position:

lib/mysqlx/statement.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,12 +1354,12 @@ def execute(self):
13541354

13551355
# Validate members that constraint the index
13561356
if not self._fields_desc:
1357-
raise ProgrammingError("Required member \"fields\" not found in "
1357+
raise ProgrammingError("Required member 'fields' not found in "
13581358
"the given index description: {}"
13591359
"".format(self._index_desc))
13601360

13611361
if not isinstance(self._fields_desc, list):
1362-
raise ProgrammingError("Required member \"fields\" must contain a "
1362+
raise ProgrammingError("Required member 'fields' must contain a "
13631363
"list.")
13641364

13651365
args = {}
@@ -1386,37 +1386,42 @@ def execute(self):
13861386
constraint["member"] = field_desc.pop("field")
13871387
constraint["type"] = field_desc.pop("type")
13881388
constraint["required"] = field_desc.pop("required", False)
1389+
constraint["array"] = field_desc.pop("array", False)
1390+
if not isinstance(constraint["required"], bool):
1391+
raise TypeError("Field member 'required' must be Boolean")
1392+
if not isinstance(constraint["array"], bool):
1393+
raise TypeError("Field member 'array' must be Boolean")
13891394
if args["type"].upper() == "SPATIAL" and \
13901395
not constraint["required"]:
1391-
raise ProgrammingError('Field member "required" must be '
1392-
'set to "True" when index type is'
1393-
' set to "SPATIAL"')
1396+
raise ProgrammingError(
1397+
"Field member 'required' must be set to 'True' when "
1398+
"index type is set to 'SPATIAL'")
13941399
if args["type"].upper() == "INDEX" and \
1395-
constraint["type"] == 'GEOJSON':
1396-
raise ProgrammingError('Index "type" must be set to '
1397-
'"SPATIAL" when field type is set '
1398-
'to "GEOJSON"')
1400+
constraint["type"] == "GEOJSON":
1401+
raise ProgrammingError(
1402+
"Index 'type' must be set to 'SPATIAL' when field "
1403+
"type is set to 'GEOJSON'")
13991404
if "collation" in field_desc:
14001405
if not constraint["type"].upper().startswith("TEXT"):
14011406
raise ProgrammingError(
1402-
"The \"collation\" member can only be used when "
1403-
"field type is set to \"GEOJSON\"")
1407+
"The 'collation' member can only be used when "
1408+
"field type is set to 'GEOJSON'")
14041409
else:
14051410
constraint["collation"] = field_desc.pop("collation")
14061411
# "options" and "srid" fields in IndexField can be
14071412
# present only if "type" is set to "GEOJSON"
14081413
if "options" in field_desc:
1409-
if constraint["type"].upper() != 'GEOJSON':
1414+
if constraint["type"].upper() != "GEOJSON":
14101415
raise ProgrammingError(
1411-
"The \"options\" member can only be used when "
1412-
"index type is set to \"GEOJSON\"")
1416+
"The 'options' member can only be used when "
1417+
"index type is set to 'GEOJSON'")
14131418
else:
14141419
constraint["options"] = field_desc.pop("options")
14151420
if "srid" in field_desc:
1416-
if constraint["type"].upper() != 'GEOJSON':
1421+
if constraint["type"].upper() != "GEOJSON":
14171422
raise ProgrammingError(
1418-
"The \"srid\" member can only be used when index"
1419-
" type is set to \"GEOJSON\"")
1423+
"The 'srid' member can only be used when index "
1424+
"type is set to 'GEOJSON'")
14201425
else:
14211426
constraint["srid"] = field_desc.pop("srid")
14221427
args["constraint"].append(constraint)

tests/test_mysqlx_crud.py

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
_CREATE_VIEW_QUERY = "CREATE VIEW `{0}`.`{1}` AS {2}"
5050
_DROP_TABLE_QUERY = "DROP TABLE IF EXISTS `{0}`.`{1}`"
5151
_DROP_VIEW_QUERY = "DROP VIEW IF EXISTS `{0}`.`{1}`"
52+
_SHOW_INDEXES_QUERY = "SHOW INDEXES FROM `{0}`.`{1}` WHERE Key_name='{2}'"
5253
_PREP_STMT_QUERY = (
5354
"SELECT p.sql_text, p.count_execute "
5455
"FROM performance_schema.prepared_statements_instances AS p "
@@ -1785,12 +1786,8 @@ def test_create_index(self):
17851786
"required": True}],
17861787
"unique": False}).execute()
17871788

1788-
show_indexes_sql = (
1789-
"SHOW INDEXES FROM `{0}`.`{1}` WHERE Key_name='{2}'"
1790-
"".format(self.schema_name, collection_name, index_name)
1791-
)
1792-
1793-
result = self.session.sql(show_indexes_sql).execute()
1789+
result = self.session.sql(_SHOW_INDEXES_QUERY.format(
1790+
self.schema_name, collection_name, index_name)).execute()
17941791
rows = result.fetch_all()
17951792
self.assertEqual(1, len(rows))
17961793

@@ -1805,12 +1802,8 @@ def test_create_index(self):
18051802
"required": True}],
18061803
"unique": False}).execute()
18071804

1808-
show_indexes_sql = (
1809-
"SHOW INDEXES FROM `{0}`.`{1}` WHERE Key_name='{2}'"
1810-
"".format(self.schema_name, collection_name, index_name)
1811-
)
1812-
1813-
result = self.session.sql(show_indexes_sql).execute()
1805+
result = self.session.sql(_SHOW_INDEXES_QUERY.format(
1806+
self.schema_name, collection_name, index_name)).execute()
18141807
rows = result.fetch_all()
18151808
self.assertEqual(2, len(rows))
18161809

@@ -1825,12 +1818,19 @@ def test_create_index(self):
18251818
"unique": False,
18261819
"type":'SPATIAL'}).execute()
18271820

1828-
show_indexes_sql = (
1829-
"SHOW INDEXES FROM `{0}`.`{1}` WHERE Key_name='{2}'"
1830-
"".format(self.schema_name, collection_name, index_name)
1831-
)
1821+
result = self.session.sql(_SHOW_INDEXES_QUERY.format(
1822+
self.schema_name, collection_name, index_name)).execute()
1823+
rows = result.fetch_all()
1824+
self.assertEqual(1, len(rows))
18321825

1833-
result = self.session.sql(show_indexes_sql).execute()
1826+
# Create an index on document fields which contain arrays
1827+
index_name = "emails_idx"
1828+
index_desc = {"fields": [{"field": "$.emails", "type": "CHAR(128)",
1829+
"array": True}]}
1830+
collection.create_index(index_name, index_desc).execute()
1831+
1832+
result = self.session.sql(_SHOW_INDEXES_QUERY.format(
1833+
self.schema_name, collection_name, index_name)).execute()
18341834
rows = result.fetch_all()
18351835
self.assertEqual(1, len(rows))
18361836

@@ -1976,6 +1976,20 @@ def test_create_index(self):
19761976
create_index = collection.create_index(index_name, index_desc)
19771977
self.assertRaises(mysqlx.ProgrammingError, create_index.execute)
19781978

1979+
# "required" fields must be Boolean
1980+
index_name = "age_idx"
1981+
index_desc = {"fields": [{"field": "$.age", "type": "INT",
1982+
"required": "True"}], "unique": False}
1983+
create_index = collection.create_index(index_name, index_desc)
1984+
self.assertRaises(TypeError, create_index.execute)
1985+
1986+
# "array" fields must be Boolean
1987+
index_name = "emails_idx"
1988+
index_desc = {"fields": [{"field": "$.emails", "type": "CHAR(128)",
1989+
"array": "True"}]}
1990+
create_index = collection.create_index(index_name, index_desc)
1991+
self.assertRaises(TypeError, create_index.execute)
1992+
19791993
self.schema.drop_collection(collection_name)
19801994

19811995
@unittest.skipIf(tests.MYSQL_VERSION < (8, 0, 4), "Dev API change")

0 commit comments

Comments
 (0)