Skip to content

Commit 102a043

Browse files
author
Eric Muller
committed
Fix Query fails with more than 10 attributes in a query filter condition. (#751)
1 parent b9d08fc commit 102a043

File tree

2 files changed

+58
-5
lines changed

2 files changed

+58
-5
lines changed

pynamodb/connection/base.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import json
77
import logging
88
import random
9+
import re
910
import sys
1011
import time
1112
import uuid
@@ -1240,11 +1241,12 @@ def query(self,
12401241
# FilterExpression does not allow key attributes. Check for hash and range key name placeholders
12411242
hash_key_placeholder = name_placeholders.get(hash_keyname)
12421243
range_key_placeholder = range_keyname and name_placeholders.get(range_keyname)
1243-
if (
1244-
hash_key_placeholder in filter_expression or
1245-
(range_key_placeholder and range_key_placeholder in filter_expression)
1246-
):
1247-
raise ValueError("'filter_condition' cannot contain key attributes")
1244+
if re.search(hash_key_placeholder + r"\D", filter_expression):
1245+
raise ValueError("'filter_condition' cannot contain hash key. {} found in {}"
1246+
.format(hash_key_placeholder, filter_expression))
1247+
if range_key_placeholder and re.search(range_key_placeholder + r"\D", filter_expression):
1248+
raise ValueError("'filter_condition' cannot contain range key. {} found in {}"
1249+
.format(range_key_placeholder, filter_expression))
12481250
operation_kwargs[FILTER_EXPRESSION] = filter_expression
12491251
if attributes_to_get:
12501252
projection_expression = create_projection_expression(attributes_to_get, name_placeholders)

tests/test_base_connection.py

+51
Original file line numberDiff line numberDiff line change
@@ -1332,6 +1332,57 @@ def test_query(self):
13321332
}
13331333
self.assertEqual(req.call_args[0][1], params)
13341334

1335+
with patch(PATCH_METHOD) as req:
1336+
req.return_value = {}
1337+
conn.query(
1338+
table_name=table_name,
1339+
hash_key="FooForum",
1340+
range_key_condition=Path('Subject').startswith('thread'),
1341+
filter_condition=Path('a2').exists()
1342+
| Path('a3').exists()
1343+
| Path('a4').exists()
1344+
| Path('a5').exists()
1345+
| Path('a6').exists()
1346+
| Path('a7').exists()
1347+
| Path('a8').exists()
1348+
| Path('a9').exists()
1349+
| Path('a10').exists()
1350+
)
1351+
1352+
params = {
1353+
'TableName': 'Thread',
1354+
'KeyConditionExpression': '(#0 = :0 AND begins_with (#1, :1))',
1355+
'FilterExpression':
1356+
'((((((((attribute_exists (#2) '
1357+
'OR attribute_exists (#3)) '
1358+
'OR attribute_exists (#4)) '
1359+
'OR attribute_exists (#5)) '
1360+
'OR attribute_exists (#6)) '
1361+
'OR attribute_exists (#7)) '
1362+
'OR attribute_exists (#8)) '
1363+
'OR attribute_exists (#9)) '
1364+
'OR attribute_exists (#10))',
1365+
'ExpressionAttributeNames': {
1366+
'#0': 'ForumName',
1367+
'#1': 'Subject',
1368+
'#2': 'a2',
1369+
'#3': 'a3',
1370+
'#4': 'a4',
1371+
'#5': 'a5',
1372+
'#6': 'a6',
1373+
'#7': 'a7',
1374+
'#8': 'a8',
1375+
'#9': 'a9',
1376+
'#10': 'a10'
1377+
},
1378+
'ExpressionAttributeValues': {
1379+
':0': {'S': 'FooForum'},
1380+
':1': {'S': 'thread'}
1381+
},
1382+
'ReturnConsumedCapacity': 'TOTAL'
1383+
}
1384+
self.assertEqual(req.call_args[0][1], params)
1385+
13351386
def test_scan(self):
13361387
"""
13371388
Connection.scan

0 commit comments

Comments
 (0)