quillsql 2.2.1__tar.gz → 2.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {quillsql-2.2.1 → quillsql-2.2.3}/PKG-INFO +1 -1
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/core.py +50 -43
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql.egg-info/PKG-INFO +1 -1
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql.egg-info/SOURCES.txt +2 -1
- {quillsql-2.2.1 → quillsql-2.2.3}/setup.py +1 -1
- quillsql-2.2.3/tests/test_core.py +53 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/README.md +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/__init__.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/assets/__init__.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/assets/pgtypes.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/db/__init__.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/db/bigquery.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/db/cached_connection.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/db/db_helper.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/db/postgres.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/error.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/utils/__init__.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/utils/filters.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/utils/pivot_template.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/utils/run_query_processes.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/utils/schema_conversion.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql/utils/tenants.py +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql.egg-info/dependency_links.txt +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql.egg-info/requires.txt +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/quillsql.egg-info/top_level.txt +0 -0
- {quillsql-2.2.1 → quillsql-2.2.3}/setup.cfg +0 -0
|
@@ -113,8 +113,9 @@ class Quill:
|
|
|
113
113
|
**metadata,
|
|
114
114
|
"tenants": tenants,
|
|
115
115
|
"flags": flags,
|
|
116
|
-
"adminEnabled": admin_enabled,
|
|
117
116
|
}
|
|
117
|
+
if admin_enabled is not None:
|
|
118
|
+
pivot_payload["adminEnabled"] = admin_enabled
|
|
118
119
|
if filters is not None:
|
|
119
120
|
pivot_payload["sdkFilters"] = [
|
|
120
121
|
convert_custom_filter(f) for f in filters
|
|
@@ -212,17 +213,16 @@ class Quill:
|
|
|
212
213
|
tenants[0] != SINGLE_TENANT
|
|
213
214
|
):
|
|
214
215
|
|
|
215
|
-
|
|
216
|
-
'
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
)
|
|
216
|
+
tenant_flags_payload = {
|
|
217
|
+
'reportId': metadata.get('reportId') or metadata.get('dashboardItemId'),
|
|
218
|
+
'clientId': metadata.get('clientId'),
|
|
219
|
+
'dashboardName': metadata.get('name'),
|
|
220
|
+
'tenants': tenants,
|
|
221
|
+
'flags': flags,
|
|
222
|
+
}
|
|
223
|
+
if admin_enabled is not None:
|
|
224
|
+
tenant_flags_payload['adminEnabled'] = admin_enabled
|
|
225
|
+
response = self.post_quill('tenant-mapped-flags', tenant_flags_payload)
|
|
226
226
|
|
|
227
227
|
if response.get('error'):
|
|
228
228
|
return {
|
|
@@ -236,16 +236,22 @@ class Quill:
|
|
|
236
236
|
self.target_connection.database_type,
|
|
237
237
|
)
|
|
238
238
|
|
|
239
|
-
tenant_flags = [
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
239
|
+
tenant_flags = []
|
|
240
|
+
query_order = response.get('metadata', {}).get('queryOrder') or []
|
|
241
|
+
query_results = (flag_query_results or {}).get('queryResults') or []
|
|
242
|
+
for tenant_field, query_result in zip(query_order, query_results):
|
|
243
|
+
rows = []
|
|
244
|
+
if isinstance(query_result, dict):
|
|
245
|
+
rows = query_result.get('rows') or []
|
|
246
|
+
flags = {
|
|
247
|
+
row.get('quill_flag')
|
|
248
|
+
for row in rows
|
|
249
|
+
if isinstance(row, dict) and row.get('quill_flag') is not None
|
|
243
250
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
)
|
|
248
|
-
]
|
|
251
|
+
tenant_flags.append({
|
|
252
|
+
'tenantField': tenant_field,
|
|
253
|
+
'flags': list(flags),
|
|
254
|
+
})
|
|
249
255
|
elif tenants[0] == SINGLE_TENANT and flags:
|
|
250
256
|
if flags and isinstance(flags[0], dict):
|
|
251
257
|
tenant_flags = [{'tenantField': SINGLE_TENANT, 'flags': flags}]
|
|
@@ -277,14 +283,15 @@ class Quill:
|
|
|
277
283
|
and metadata.get("runQueryConfig").get("getColumns")
|
|
278
284
|
else None
|
|
279
285
|
)
|
|
280
|
-
payload = {
|
|
286
|
+
payload: dict = {
|
|
281
287
|
**metadata,
|
|
282
288
|
"tenants": tenants,
|
|
283
289
|
"flags": tenant_flags,
|
|
284
290
|
"viewQuery": view_query,
|
|
285
291
|
"preQueryResultsColumns": pre_query_columns,
|
|
286
|
-
"adminEnabled": admin_enabled,
|
|
287
292
|
}
|
|
293
|
+
if admin_enabled is not None:
|
|
294
|
+
payload["adminEnabled"] = admin_enabled
|
|
288
295
|
if filters is not None:
|
|
289
296
|
payload["sdkFilters"] = [convert_custom_filter(f) for f in filters]
|
|
290
297
|
quill_results = self.post_quill(metadata.get("task"), payload)
|
|
@@ -329,17 +336,18 @@ class Quill:
|
|
|
329
336
|
normalized_results.get("queryResults") or []
|
|
330
337
|
)
|
|
331
338
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
339
|
+
run_query_config = responseMetadata.get("runQueryConfig") or {}
|
|
340
|
+
array_to_map = run_query_config.get("arrayToMap")
|
|
341
|
+
if normalized_results.get("mapped_array") and array_to_map:
|
|
342
|
+
target_collection = responseMetadata.get(array_to_map.get("arrayName"))
|
|
343
|
+
if isinstance(target_collection, list):
|
|
344
|
+
for index, mapped_rows in enumerate(normalized_results["mapped_array"]):
|
|
345
|
+
if index >= len(target_collection):
|
|
346
|
+
continue
|
|
347
|
+
target_entry = target_collection[index]
|
|
348
|
+
if isinstance(target_entry, dict):
|
|
349
|
+
target_entry[array_to_map.get("field")] = mapped_rows
|
|
350
|
+
normalized_results.pop("mapped_array", None)
|
|
343
351
|
|
|
344
352
|
query_results_list = normalized_results.get("queryResults") or []
|
|
345
353
|
if len(query_results_list) == 1:
|
|
@@ -354,15 +362,14 @@ class Quill:
|
|
|
354
362
|
|
|
355
363
|
except Exception as err:
|
|
356
364
|
if task == "update-view":
|
|
357
|
-
|
|
358
|
-
"
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
)
|
|
365
|
+
broken_view_payload = {
|
|
366
|
+
"table": metadata.get("name"),
|
|
367
|
+
"clientId": metadata.get("clientId"),
|
|
368
|
+
"error": str(err),
|
|
369
|
+
}
|
|
370
|
+
if admin_enabled is not None:
|
|
371
|
+
broken_view_payload["adminEnabled"] = admin_enabled
|
|
372
|
+
self.post_quill("set-broken-view", broken_view_payload)
|
|
366
373
|
return {
|
|
367
374
|
"error": str(err).splitlines()[0],
|
|
368
375
|
"status": "error",
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from unittest.mock import MagicMock, patch
|
|
4
|
+
|
|
5
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
|
6
|
+
|
|
7
|
+
from quillsql.core import Quill
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@patch("quillsql.core.CachedConnection")
|
|
11
|
+
def test_query_handles_none_tenant_flag_responses(mock_cached_connection):
|
|
12
|
+
mock_connection = MagicMock()
|
|
13
|
+
mock_connection.database_type = "PostgreSQL"
|
|
14
|
+
mock_cached_connection.return_value = mock_connection
|
|
15
|
+
|
|
16
|
+
quill = Quill(
|
|
17
|
+
private_key="test-key",
|
|
18
|
+
database_type="PostgreSQL",
|
|
19
|
+
database_config={},
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
quill.run_queries = MagicMock(
|
|
23
|
+
side_effect=[
|
|
24
|
+
{"queryResults": [None]},
|
|
25
|
+
{"queryResults": []},
|
|
26
|
+
]
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def post_quill_side_effect(path, payload):
|
|
30
|
+
if path == "tenant-mapped-flags":
|
|
31
|
+
return {
|
|
32
|
+
"queries": [
|
|
33
|
+
'SELECT * FROM (SELECT "id" AS "customer_id", "name" AS "quill_label", "id" AS "quill_flag" FROM "public"."customers") AS "subq_owner_query" WHERE "customer_id" IN (2)'
|
|
34
|
+
],
|
|
35
|
+
"metadata": {"queryOrder": ["customer_id"]},
|
|
36
|
+
}
|
|
37
|
+
return {"queries": [], "metadata": {}}
|
|
38
|
+
|
|
39
|
+
quill.post_quill = MagicMock(side_effect=post_quill_side_effect)
|
|
40
|
+
|
|
41
|
+
result = quill.query(
|
|
42
|
+
tenants=["tenant-1"],
|
|
43
|
+
metadata={
|
|
44
|
+
"task": "report",
|
|
45
|
+
"clientId": "client-123",
|
|
46
|
+
"reportId": "report-456",
|
|
47
|
+
"databaseType": "PostgreSQL",
|
|
48
|
+
},
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
assert result["status"] == "success"
|
|
52
|
+
assert result["data"] == {}
|
|
53
|
+
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|