sql: get new fts search value when ordering (#74972) #202

Merged
fpeters merged 1 commits from wip/74972-order-by-rank into main 2023-03-27 18:11:25 +02:00
3 changed files with 69 additions and 12 deletions

View File

@ -339,3 +339,52 @@ def test_card_get_file(pub):
assert os.path.exists(thumb_filepath) is True
# again, thumbs_dir already exists
get_app(pub).get(sign_uri(file_url + '&thumbnail=1'), status=200)
def test_api_list_formdata_phone_order_by_rank(pub):
pub.role_class.wipe()
role = pub.role_class(name='test')
role.store()
ApiAccess.wipe()
access = ApiAccess()
access.name = 'test'
access.access_identifier = 'test'
access.access_key = '12345'
access.store()
CardDef.wipe()
carddef = CardDef()
carddef.name = 'test'
carddef.workflow_roles = {'_receiver': role.id}
carddef.fields = [
fields.StringField(id='0', label='a', type='string', display_locations=['listings']),
fields.StringField(id='1', label='b', type='string'),
]
carddef.store()
data_class = carddef.data_class()
data_class.wipe()
# 1st carddata, with phone number
carddata1 = data_class()
carddata1.data = {'1': '+33623456789'}
carddata1.just_created()
carddata1.jump_status('new')
carddata1.store()
# 2nd carddata, with no value
carddata2 = data_class()
carddata2.data = {}
carddata2.just_created()
carddata2.jump_status('new')
carddata2.store()
# check fts
resp = get_app(pub).get(
sign_uri(
'/api/cards/test/list?full=on&q=0623456789', orig=access.access_identifier, key=access.access_key
)
)
assert len(resp.json['data']) == 1
assert [int(x['id']) for x in resp.json['data']] == [carddata1.id]

View File

@ -326,7 +326,7 @@ class ILike(Criteria):
class FtsMatch(Criteria):
def __init__(self, value, extra_normalize=True):
def __init__(self, value, extra_normalize=True, **kwargs):
self.value = self.get_fts_value(value)
self.extra_normalize = extra_normalize # will be handled in sql.FtsMatch
@ -339,7 +339,7 @@ class FtsMatch(Criteria):
class NotNull(Criteria):
def __init__(self, attribute):
def __init__(self, attribute, **kwargs):
self.attribute = attribute
def build_lambda(self):
@ -347,7 +347,7 @@ class NotNull(Criteria):
class Null(Criteria):
def __init__(self, attribute):
def __init__(self, attribute, **kwargs):
self.attribute = attribute
def build_lambda(self):
@ -355,7 +355,7 @@ class Null(Criteria):
class ElementEqual(Criteria):
def __init__(self, attribute, key, value):
def __init__(self, attribute, key, value, **kwargs):
self.attribute = attribute
self.key = key
self.value = value
@ -365,7 +365,7 @@ class ElementEqual(Criteria):
class ElementILike(Criteria):
def __init__(self, attribute, key, value):
def __init__(self, attribute, key, value, **kwargs):
self.attribute = attribute
self.key = key
self.value = value
@ -378,7 +378,7 @@ class ElementILike(Criteria):
class ElementIntersects(Criteria):
def __init__(self, attribute, key, value):
def __init__(self, attribute, key, value, **kwargs):
self.attribute = attribute
self.key = key
self.value = value
@ -405,7 +405,7 @@ class Nothing(Criteria):
class Distance(Criteria):
def __init__(self, point, distance):
def __init__(self, point, distance, **kwargs):
self.point = point # {'lat': ..., 'lon': ...}
self.distance = distance # in meters

View File

@ -330,7 +330,7 @@ class ArrayContains(Contains):
class NotNull(Criteria):
sql_op = 'IS NOT NULL'
def __init__(self, attribute):
def __init__(self, attribute, **kwargs):
self.attribute = attribute
def as_sql(self):
@ -425,7 +425,7 @@ class ILike(Criteria):
class FtsMatch(Criteria):
def __init__(self, value, extra_normalize=True):
def __init__(self, value, extra_normalize=True, **kwargs):
# make Criteria.__repr__ works
self.attribute = 'fts'
self.value = self.get_fts_value(value)
@ -454,7 +454,7 @@ class FtsMatch(Criteria):
class ElementEqual(Criteria):
def __init__(self, attribute, key, value):
def __init__(self, attribute, key, value, **kwargs):
super().__init__(attribute, value)
self.key = key
@ -534,13 +534,21 @@ def parse_clause(clause):
func_clauses = []
where_clauses = []
parameters = {}
for element in clause:
for i, element in enumerate(clause):
if callable(element):
func_clauses.append(element)
else:
sql_class = globals().get(element.__class__.__name__)
if sql_class:
sql_element = sql_class(**element.__dict__)
if isinstance(element, Criteria):
# already SQL
sql_element = element
else:
# criteria from wcs.qommon.storage, replace it with its SQL variant
# (keep extra _label for display in backoffice)
sql_element = sql_class(**element.__dict__)
sql_element._label = getattr(element, '_label', None)
clause[i] = sql_element
where_clauses.append(sql_element.as_sql())
parameters.update(sql_element.as_sql_param())
else: