Saving changes now that most things have been migrated to CRUD V3 and appear to be working. This still needs testing though.
This commit is contained in:
@@ -723,7 +723,7 @@ def sql_select(
|
||||
sql_search_qry = ''
|
||||
if search_query:
|
||||
log.info('Creating partial SQL string for complex SearchQuery.')
|
||||
sql_search_qry, data_search = sql_search_qry_part(search_query, searchable_fields=searchable_fields)
|
||||
sql_search_qry, data_search = sql_search_qry_part(search_query, searchable_fields=searchable_fields, table_name=table_name)
|
||||
data = {**data, **data_search}
|
||||
|
||||
sql = text(
|
||||
@@ -830,7 +830,7 @@ def sql_select(
|
||||
sql_search_qry = ''
|
||||
if search_query:
|
||||
log.info('Creating partial SQL string for complex SearchQuery.')
|
||||
sql_search_qry, data_search = sql_search_qry_part(search_query, searchable_fields=searchable_fields)
|
||||
sql_search_qry, data_search = sql_search_qry_part(search_query, searchable_fields=searchable_fields, table_name=table_name)
|
||||
data = {**data, **data_search}
|
||||
|
||||
# # NOTE: Version 3 of the fulltext search
|
||||
@@ -2052,7 +2052,7 @@ def sql_enable_part(table_name: str, enabled: str) -> bool|dict:
|
||||
sql = f'AND `{table_name}`.enable = false'
|
||||
enable = False
|
||||
elif enabled == 'all':
|
||||
sql = f'AND (`{table_name}`.enable = true OR `{table_name}`.enable = false OR `{table_name}`.enable IS NULL)'
|
||||
sql = ''
|
||||
enable = None
|
||||
log.debug(sql)
|
||||
|
||||
@@ -2080,7 +2080,7 @@ def sql_hidden_part(table_name: str, hidden: str) -> bool|dict:
|
||||
sql = f'AND (`{table_name}`.hide = false OR `{table_name}`.hide IS NULL)'
|
||||
hide = False
|
||||
elif hidden == 'all':
|
||||
sql = f'AND (`{table_name}`.hide = true OR `{table_name}`.hide = false OR `{table_name}`.hide IS NULL)'
|
||||
sql = ''
|
||||
hide = None
|
||||
log.debug(sql)
|
||||
|
||||
@@ -2109,11 +2109,13 @@ def sql_limit_offset_part(limit: int, offset: int = 0) -> bool|str:
|
||||
# ### BEGIN ### API DB SQL Methods ### sql_search_qry_part() ###
|
||||
# NEW 2026-01-02
|
||||
# Updated to support complex POST-based searches with recursive logical grouping.
|
||||
# Updated 2026-01-06 to handle missing default_qry_str column gracefully.
|
||||
@logger_reset
|
||||
def sql_search_qry_part(
|
||||
search_query: Any, # SearchQuery model instance
|
||||
searchable_fields: List[str]|None = None, # List of allowed fields
|
||||
max_depth: int = 5, # Maximum recursion depth
|
||||
table_name: str|None = None, # Target table for schema validation
|
||||
) -> tuple[str, dict]:
|
||||
"""
|
||||
Recursively builds a SQL WHERE clause from a SearchQuery model.
|
||||
@@ -2157,9 +2159,35 @@ def sql_search_qry_part(
|
||||
|
||||
# Process 'query_string' (Standardized Full-Text Search)
|
||||
if hasattr(query_node, 'query_string') and query_node.query_string:
|
||||
p_name = get_param_name()
|
||||
clauses.append(f"MATCH( default_qry_str ) AGAINST( :{p_name} IN BOOLEAN MODE )")
|
||||
data[p_name] = query_node.query_string
|
||||
if query_node.query_string == '%':
|
||||
# Wildcard: Skip filtering for this part
|
||||
pass
|
||||
else:
|
||||
# Check if default_qry_str exists in this table/view
|
||||
use_match = True
|
||||
if table_name:
|
||||
try:
|
||||
db.execute(text(f"SELECT default_qry_str FROM `{table_name}` LIMIT 0"))
|
||||
except:
|
||||
use_match = False
|
||||
else:
|
||||
use_match = False # Safe default if no table_name
|
||||
|
||||
if use_match:
|
||||
p_name = get_param_name()
|
||||
clauses.append(f"MATCH( default_qry_str ) AGAINST( :{p_name} IN BOOLEAN MODE )")
|
||||
data[p_name] = query_node.query_string
|
||||
elif searchable_fields:
|
||||
# Fallback: OR LIKE across all searchable fields
|
||||
like_clauses = []
|
||||
for field in searchable_fields:
|
||||
# Skip internal/numeric fields for full-text-like search
|
||||
if not any(x in field for x in ['_id', 'enable', 'hide', 'priority', 'sort', 'group', 'created_on', 'updated_on']):
|
||||
f_p_name = get_param_name()
|
||||
like_clauses.append(f"`{field}` LIKE :{f_p_name}")
|
||||
data[f_p_name] = f"%{query_node.query_string}%"
|
||||
if like_clauses:
|
||||
clauses.append(f"({' OR '.join(like_clauses)})")
|
||||
|
||||
# Process 'and' filters
|
||||
if hasattr(query_node, 'and_filters') and query_node.and_filters:
|
||||
|
||||
Reference in New Issue
Block a user