|
9 | 9 | SearchTargetTables,
|
10 | 10 | )
|
11 | 11 | from submodules.model.enums import LabelSource
|
| 12 | +from submodules.model.business_objects import attribute |
| 13 | +from submodules.model.enums import DataTypes |
12 | 14 |
|
13 | 15 |
|
14 | 16 | def build_search_condition_value(target: SearchOperators, value) -> str:
|
15 | 17 | if target in __lookup_operator:
|
16 | 18 | operator = __lookup_operator[target]
|
17 | 19 | if target == SearchOperators.IN:
|
18 | 20 | all_in_values = ""
|
19 |
| - for v in value: |
20 |
| - part = v |
21 |
| - if isinstance(v, str): |
22 |
| - part = "'" + part + "'" |
23 |
| - if all_in_values != "": |
24 |
| - all_in_values += ", " + part |
25 |
| - else: |
26 |
| - all_in_values = part |
| 21 | + if value: |
| 22 | + all_in_values = ", ".join( |
| 23 | + [f"'{v}'" if isinstance(v, str) else str(v) for v in value] |
| 24 | + ) |
27 | 25 | return operator.replace("@@VALUES@@", all_in_values)
|
| 26 | + elif target == SearchOperators.BETWEEN: |
| 27 | + value1 = f"'{value[0]}'" if isinstance(value[0], str) else str(value[0]) |
| 28 | + value2 = f"'{value[1]}'" if isinstance(value[1], str) else str(value[1]) |
| 29 | + return operator.replace("@@VALUE1@@", value1).replace("@@VALUE2@@", value2) |
28 | 30 | else:
|
29 | 31 | if target not in __lookup_operator_has_quotes and isinstance(value, str):
|
30 | 32 | value = "'" + value + "'"
|
31 |
| - return operator.replace("@@VALUE@@", value) |
| 33 | + return operator.replace("@@VALUE@@", str(value)) |
32 | 34 | else:
|
33 | 35 | raise ValueError(target.value + " no operator info")
|
34 | 36 |
|
35 | 37 |
|
36 |
| -def build_search_condition(filter_element: Dict[str, str]) -> str: |
| 38 | +def build_search_condition(project_id: str, filter_element: Dict[str, str]) -> str: |
37 | 39 | table = SearchTargetTables[filter_element[FilterDataDictKeys.TARGET_TABLE.value]]
|
38 | 40 | column = SearchColumn[filter_element[FilterDataDictKeys.TARGET_COLUMN.value]]
|
39 |
| - column_text = build_search_column_text(filter_element) |
40 | 41 | operator = SearchOperators[filter_element[FilterDataDictKeys.OPERATOR.value]]
|
41 |
| - |
42 |
| - if operator == SearchOperators.IN: |
43 |
| - if table == SearchTargetTables.RECORD and column == SearchColumn.DATA: |
44 |
| - filter_values = filter_element[FilterDataDictKeys.VALUES.value][1:] |
| 42 | + attr_name = filter_element[FilterDataDictKeys.VALUES.value][0] |
| 43 | + filter_values = filter_element[FilterDataDictKeys.VALUES.value] |
| 44 | + search_column = build_search_column(project_id, table, column, operator, attr_name) |
| 45 | + |
| 46 | + if operator in [SearchOperators.IN_WC, SearchOperators.IN_WC_CS]: |
| 47 | + conditions = [] |
| 48 | + if operator == SearchOperators.IN_WC: |
| 49 | + used_operator = SearchOperators.ILIKE |
45 | 50 | else:
|
46 |
| - filter_values = filter_element[FilterDataDictKeys.VALUES.value] |
47 |
| - return column_text + build_search_condition_value(operator, filter_values) |
| 51 | + used_operator = SearchOperators.LIKE |
| 52 | + for value in filter_values[1:]: |
| 53 | + used_value = value.replace("*", "%").replace("?", "_") |
| 54 | + conditions.append( |
| 55 | + search_column + build_search_condition_value(used_operator, used_value) |
| 56 | + ) |
| 57 | + return " OR ".join(conditions) |
| 58 | + elif operator == SearchOperators.IN: |
| 59 | + if table == SearchTargetTables.RECORD and column == SearchColumn.DATA: |
| 60 | + filter_values = filter_values[1:] |
| 61 | + if not filter_values: |
| 62 | + return "" |
| 63 | + return search_column + build_search_condition_value(operator, filter_values) |
| 64 | + elif operator == SearchOperators.BETWEEN: |
| 65 | + if table == SearchTargetTables.RECORD and column == SearchColumn.DATA: |
| 66 | + filter_values = filter_values[1:] |
| 67 | + if not filter_values[0] and not filter_values[1]: |
| 68 | + return "" |
| 69 | + elif not filter_values[0]: |
| 70 | + return search_column + build_search_condition_value( |
| 71 | + SearchOperators.LESS_EQUAL, filter_values[1] |
| 72 | + ) |
| 73 | + elif not filter_values[1]: |
| 74 | + return search_column + build_search_condition_value( |
| 75 | + SearchOperators.GREATER_EQUAL, filter_values[0] |
| 76 | + ) |
| 77 | + return search_column + build_search_condition_value(operator, filter_values) |
48 | 78 | else:
|
49 | 79 | if table == SearchTargetTables.RECORD and column == SearchColumn.DATA:
|
50 |
| - filter_value = filter_element[FilterDataDictKeys.VALUES.value][1] |
| 80 | + filter_value = filter_values[1] |
| 81 | + attribute_item = attribute.get_by_name(project_id, attr_name) |
| 82 | + if not filter_value and attribute_item.data_type != DataTypes.BOOLEAN.value: |
| 83 | + return "" |
51 | 84 | else:
|
52 |
| - filter_value = filter_element[FilterDataDictKeys.VALUES.value][0] |
53 |
| - |
54 |
| - return column_text + build_search_condition_value(operator, filter_value) |
| 85 | + filter_value = filter_values[0] |
55 | 86 |
|
| 87 | + return search_column + build_search_condition_value(operator, filter_value) |
56 | 88 |
|
57 |
| -def build_search_column_text(filter_element: Dict[str, str]) -> str: |
58 | 89 |
|
59 |
| - table = SearchTargetTables[filter_element[FilterDataDictKeys.TARGET_TABLE.value]] |
| 90 | +def build_search_column( |
| 91 | + project_id: str, table: str, column: str, operator: str, attr_name: str |
| 92 | +) -> str: |
60 | 93 | table_alias = __lookup_table_alias[table]
|
61 |
| - column = SearchColumn[filter_element[FilterDataDictKeys.TARGET_COLUMN.value]] |
62 |
| - |
63 | 94 | if table == SearchTargetTables.RECORD and column == SearchColumn.DATA:
|
64 |
| - col_str = f"{table_alias}.\"data\" ->> '{filter_element[FilterDataDictKeys.VALUES.value][0]}'::TEXT" |
| 95 | + attr_data_type = "TEXT" |
| 96 | + if operator not in __lookup_operator_has_quotes: |
| 97 | + attr_data_type = attribute.get_data_type(project_id, attr_name) |
| 98 | + sql_cast = __lookup_sql_cast_data_type[attr_data_type] |
| 99 | + col_str = f"({table_alias}.\"data\" ->> '{attr_name}')::{sql_cast}" |
65 | 100 | else:
|
66 | 101 | col_str = f"{table_alias}.{column.value}"
|
67 | 102 | return col_str
|
@@ -146,6 +181,9 @@ def build_query_template(
|
146 | 181 | upper = str(upper)
|
147 | 182 | template = template.replace("@@VALUE1@@", lower)
|
148 | 183 | template = template.replace("@@VALUE2@@", upper)
|
| 184 | + elif target == SearchQueryTemplate.SUBQUERY_HAS_COMMENTS: |
| 185 | + template = template.replace("@@USER_ID@@", filter_values[0]) |
| 186 | + |
149 | 187 | template = template.replace("@@PROJECT_ID@@", project_id)
|
150 | 188 | return template
|
151 | 189 |
|
@@ -198,15 +236,40 @@ def build_order_by_table_select(
|
198 | 236 | __lookup_operator = {
|
199 | 237 | SearchOperators.EQUAL: " = @@VALUE@@",
|
200 | 238 | SearchOperators.CONTAINS: " ILIKE '%@@VALUE@@%'",
|
| 239 | + SearchOperators.CONTAINS_CS: " LIKE '%@@VALUE@@%'", |
201 | 240 | SearchOperators.BEGINS_WITH: " ILIKE '@@VALUE@@%'",
|
| 241 | + SearchOperators.BEGINS_WITH_CS: " LIKE '@@VALUE@@%'", |
202 | 242 | SearchOperators.ENDS_WITH: " ILIKE '%@@VALUE@@'",
|
| 243 | + SearchOperators.ENDS_WITH_CS: " LIKE '%@@VALUE@@'", |
203 | 244 | SearchOperators.IN: " IN (@@VALUES@@)",
|
| 245 | + SearchOperators.BETWEEN: " BETWEEN @@VALUE1@@ AND @@VALUE2@@", |
| 246 | + SearchOperators.GREATER: " > @@VALUE@@", |
| 247 | + SearchOperators.GREATER_EQUAL: " >= @@VALUE@@", |
| 248 | + SearchOperators.LESS: " < @@VALUE@@", |
| 249 | + SearchOperators.LESS_EQUAL: " <= @@VALUE@@", |
| 250 | + SearchOperators.LIKE: " LIKE '@@VALUE@@'", |
| 251 | + SearchOperators.ILIKE: " ILIKE '@@VALUE@@'", |
204 | 252 | }
|
205 | 253 |
|
206 | 254 | __lookup_operator_has_quotes = {
|
207 | 255 | SearchOperators.CONTAINS: True,
|
| 256 | + SearchOperators.CONTAINS_CS: True, |
208 | 257 | SearchOperators.BEGINS_WITH: True,
|
| 258 | + SearchOperators.BEGINS_WITH_CS: True, |
209 | 259 | SearchOperators.ENDS_WITH: True,
|
| 260 | + SearchOperators.ENDS_WITH_CS: True, |
| 261 | + SearchOperators.LIKE: True, |
| 262 | + SearchOperators.ILIKE: True, |
| 263 | + SearchOperators.IN_WC: True, |
| 264 | + SearchOperators.IN_WC_CS: True, |
| 265 | +} |
| 266 | + |
| 267 | +__lookup_sql_cast_data_type = { |
| 268 | + DataTypes.INTEGER.value: "INTEGER", |
| 269 | + DataTypes.FLOAT.value: "FLOAT", |
| 270 | + DataTypes.BOOLEAN.value: "BOOLEAN", |
| 271 | + DataTypes.CATEGORY.value: "TEXT", |
| 272 | + DataTypes.TEXT.value: "TEXT", |
210 | 273 | }
|
211 | 274 |
|
212 | 275 |
|
@@ -330,4 +393,12 @@ def build_order_by_table_select(
|
330 | 393 | HAVING COUNT(*) >1
|
331 | 394 |
|
332 | 395 | """,
|
| 396 | + SearchQueryTemplate.SUBQUERY_HAS_COMMENTS: """ |
| 397 | + SELECT cd.project_id pID, cd.xfkey rID |
| 398 | + FROM comment_data cd |
| 399 | + WHERE cd.project_id = '@@PROJECT_ID@@' |
| 400 | + AND cd.xftype = 'RECORD' |
| 401 | + AND (cd.is_private = false OR cd.created_by = '@@USER_ID@@') |
| 402 | + GROUP BY cd.project_id, cd.xfkey |
| 403 | + """, |
333 | 404 | }
|
0 commit comments