#!/usr/bin/env python3 import json from sqlor.filter import DBFilter result = {'success': False, 'rows': [], 'total': 0} try: dbname = get_module_dbname('llmage') page = int(params_kw.get('page', 1)) rows_per_page = int(params_kw.get('rows', 20)) offset = (page - 1) * rows_per_page # Get data_filter JSON from frontend filterjson_str = params_kw.get('data_filter') filterjson = None if filterjson_str: try: filterjson = json.loads(filterjson_str) except (json.JSONDecodeError, TypeError): filterjson = None async with DBPools().sqlorContext(dbname) as sor: where_clause = '' filterdic = {} if filterjson: # Preprocess LIKE values: add wildcards if user didn't provide them ns = dict(params_kw) for key, val in ns.items(): # Check if this var is used with LIKE op in filterjson if _is_like_var(filterjson, key) and val and '%' not in val: ns[key] = f'%{val}%' dbf = DBFilter(filterjson) conds = dbf.gen(ns) if conds: where_clause = f' WHERE {conds}' filterdic = ns # Total count count_sql = f"select count(*) as cnt from llm{where_clause}" count_rows = await sor.sqlExe(count_sql, filterdic) total = count_rows[0]['cnt'] if count_rows else 0 # Paginated data - JOIN with organization and upapp to get display names # Prefix field references in WHERE clause with table alias 'l.' join_where = '' if where_clause: import re conds_text = where_clause.replace(' WHERE ', '', 1) # Add l. prefix to field names (name, model, providerid, upappid, status) conds_text = re.sub(r'\b(name|model|description|providerid|upappid|status|ownerid)\b', r'l.\1', conds_text) join_where = f' WHERE {conds_text}' data_sql = f""" select l.id, l.name, l.model, l.description, l.iconid, l.upappid, l.providerid, l.ownerid, l.enabled_date, l.expired_date, l.min_balance, l.status, u.name as upappid_text, o.orgname as providerid_text from llm l left join uapi.upapp u on l.upappid = u.id left join rbac.organization o on l.providerid = o.id {join_where} order by l.model limit ${limit}$ offset ${offset}$ """ rows = await sor.sqlExe(data_sql, {**filterdic, 'limit': rows_per_page, 'offset': offset}) result['rows'] = [dict(r) for r in (rows or [])] result['total'] = total result['success'] = True except Exception as e: result['error'] = str(e) return json.dumps(result, ensure_ascii=False, default=str) def _is_like_var(filterjson, varname): """Check if a var is used with LIKE operator in the filter tree.""" if not filterjson: return False for key, val in filterjson.items(): if key.upper() in ('AND', 'OR') and isinstance(val, list): for item in val: if _is_like_var(item, varname): return True elif key.upper() == 'NOT' and isinstance(val, dict): if _is_like_var(val, varname): return True elif isinstance(val, dict) and val.get('var') == varname: if val.get('op', '').upper() == 'LIKE': return True return False