-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathquery.py
More file actions
941 lines (795 loc) · 30.8 KB
/
query.py
File metadata and controls
941 lines (795 loc) · 30.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
#
# Copyright (c) 2015-2018 LabKey Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
############################################################################
NAME:
LabKey Query API
SUMMARY:
This module provides functions for interacting with data on a LabKey Server.
DESCRIPTION:
This module is designed to simplify querying and manipulating data in LabKey Server.
Its APIs are modeled after the LabKey Server JavaScript APIs of the same names.
Installation and Setup for the LabKey Python API:
https://github.com/LabKey/labkey-api-python/blob/master/README.md
Examples of the LabKey Python API:
https://github.com/LabKey/labkey-api-python/tree/master/samples
Documentation for the LabKey Client APIs:
https://www.labkey.org/Documentation/wiki-page.view?name=viewAPIs
Support questions should be directed to the LabKey Developer forum:
https://www.labkey.org/home/developer/forum/project-start.view
############################################################################
"""
import functools
from typing import List, Literal, NotRequired, TextIO, TypedDict
from .server_context import ServerContext
from .utils import waf_encode
_default_timeout = 60 * 5 # 5 minutes
class Pagination:
"""
Enum of paging styles
"""
PAGINATED = "paginated"
SELECTED = "selected"
UNSELECTED = "unselected"
ALL = "all"
NONE = "none"
# TODO: Provide filter generators.
#
# There are some inconsistencies between the different filter types with multiple values,
# some use ';' and others use ',' to delimit values within string list; and still others use an array of value objects.
# This is a historical artifact of the api and isn't clearly documented.
#
# https://www.labkey.org/download/clientapi_docs/javascript-api/symbols/LABKEY.Filter.html
class QueryFilter:
"""
Filter object to simplify generation of query filters
"""
class Types:
"""
Enumeration of acceptable filter types
"""
# These operators require a data value
EQUAL = "eq"
DATE_EQUAL = "dateeq"
NEQ = "neq"
NOT_EQUAL = "neq"
DATE_NOT_EQUAL = "dateneq"
NEQ_OR_NULL = "neqornull"
NOT_EQUAL_OR_MISSING = "neqornull"
GT = "gt"
GREATER_THAN = "gt"
DATE_GREATER_THAN = "dategt"
LT = "lt"
LESS_THAN = "lt"
DATE_LESS_THAN = "datelt"
GTE = "gte"
GREATER_THAN_OR_EQUAL = "gte"
DATE_GREATER_THAN_OR_EQUAL = "dategte"
LTE = "lte"
LESS_THAN_OR_EQUAL = "lte"
DATE_LESS_THAN_OR_EQUAL = "datelte"
STARTS_WITH = "startswith"
DOES_NOT_START_WITH = "doesnotstartwith"
CONTAINS = "contains"
DOES_NOT_CONTAIN = "doesnotcontain"
CONTAINS_ONE_OF = "containsoneof"
CONTAINS_NONE_OF = "containsnoneof"
ARRAY_CONTAINS_ALL = "arraycontainsall"
ARRAY_CONTAINS_ANY = "arraycontainsany"
ARRAY_CONTAINS_NONE = "arraycontainsnone"
ARRAY_CONTAINS_EXACT = "arraymatches"
ARRAY_CONTAINS_NOT_EXACT = "arraynotmatches"
IN = "in"
EQUALS_ONE_OF = "in"
NOT_IN = "notin"
EQUALS_NONE_OF = "notin"
BETWEEN = "between"
NOT_BETWEEN = "notbetween"
MEMBER_OF = "memberof"
# These are the "no data value" operators
HAS_ANY_VALUE = ""
IS_BLANK = "isblank"
IS_NOT_BLANK = "isnonblank"
HAS_MISSING_VALUE = "hasmvvalue"
DOES_NOT_HAVE_MISSING_VALUE = "nomvvalue"
ARRAY_ISEMPTY = "arrayisempty"
ARRAY_ISNOTEMPTY = "arrayisnotempty"
# Table/Query-wise operators
Q = "q"
# Ontology operators
ONTOLOGY_IN_SUBTREE = "concept:insubtree"
ONTOLOGY_NOT_IN_SUBTREE = "concept:notinsubtree"
# Lineage operators
EXP_CHILD_OF = "exp:childof"
EXP_PARENT_OF = "exp:parentof"
EXP_LINEAGE_OF = "exp:lineageof"
def __init__(self, column, value, filter_type=Types.EQUAL):
self.column_name = column
self.value = value
self.filter_type = filter_type
def get_url_parameter_name(self):
return "query." + self.column_name + "~" + self.filter_type
def get_url_parameter_value(self):
return self.value
def get_column_name(self):
return self.column_name
def __repr__(self):
return "<QueryFilter [{} {} {}]>".format(self.column_name, self.filter_type, self.value)
class AuditBehavior:
"""
Enum of different auditing levels
"""
DETAILED = "DETAILED"
NONE = "NONE"
SUMMARY = "SUMMARY"
def delete_rows(
server_context: ServerContext,
schema_name: str,
query_name: str,
rows: any,
container_path: str = None,
transacted: bool = True,
audit_behavior: AuditBehavior = None,
audit_user_comment: str = None,
timeout: int = _default_timeout,
):
"""
Delete a set of rows from the schema.query
:param server_context: A LabKey server context. See utils.create_server_context.
:param schema_name: schema of table
:param query_name: table name to delete from
:param rows: Set of rows to delete
:param container_path: labkey container path if not already set in context
:param transacted: whether all of the updates should be done in a single transaction
:param audit_behavior: used to override the audit behavior for the update. See class query.AuditBehavior
:param audit_user_comment: used to provide a comment that will be attached to certain detailed audit log records
:param timeout: timeout of request in seconds (defaults to 300s)
:return:
"""
url = server_context.build_url("query", "deleteRows.api", container_path=container_path)
payload = {"schemaName": schema_name, "queryName": query_name, "rows": rows}
if transacted is False:
payload["transacted"] = transacted
if audit_behavior is not None:
payload["auditBehavior"] = audit_behavior
if audit_user_comment is not None:
payload["auditUserComment"] = audit_user_comment
return server_context.make_request(
url,
json=payload,
timeout=timeout,
)
def truncate_table(
server_context: ServerContext,
schema_name: str,
query_name: str,
container_path: str = None,
timeout: int = _default_timeout,
):
"""
Delete all rows from the schema.query
:param server_context: A LabKey server context. See utils.create_server_context.
:param schema_name: schema of table
:param query_name: table name to delete from
:param container_path: labkey container path if not already set in context
:param timeout: timeout of request in seconds (defaults to 300s)
:return:
"""
url = server_context.build_url("query", "truncateTable.api", container_path=container_path)
payload = {"schemaName": schema_name, "queryName": query_name}
return server_context.make_request(
url,
json=payload,
timeout=timeout,
)
def execute_sql(
server_context: ServerContext,
schema_name: str,
sql: str,
container_path: str = None,
max_rows: int = None,
sort: str = None,
offset: int = None,
container_filter: str = None,
save_in_session: bool = None,
parameters: dict = None,
required_version: float = None,
timeout: int = _default_timeout,
waf_encode_sql: bool = True,
):
"""
Execute sql query against a LabKey server.
:param server_context: A LabKey server context. See utils.create_server_context.
:param schema_name: schema of table
:param sql: String of labkey sql to execute
:param container_path: labkey container path if not already set in context
:param max_rows: max number of rows to return
:param sort: comma separated list of column names to sort by
:param offset: number of rows to offset results by
:param container_filter: enumeration of the various container filters available. See:
https://www.labkey.org/download/clientapi_docs/javascript-api/symbols/LABKEY.Query.html#.containerFilter
:param save_in_session: save query result as a named view to the session
:param parameters: parameter values to pass through to a parameterized query
:param required_version: Api version of response
:param timeout: timeout of request in seconds (defaults to 300s)
:param waf_encode_sql: WAF encode sql in request (defaults to True)
:return:
"""
url = server_context.build_url("query", "executeSql.api", container_path=container_path)
payload = {"schemaName": schema_name, "sql": waf_encode(sql) if waf_encode_sql else sql}
if container_filter is not None:
payload["containerFilter"] = container_filter
if max_rows is not None:
payload["maxRows"] = max_rows
if offset is not None:
payload["offset"] = offset
if sort is not None:
payload["query.sort"] = sort
if save_in_session is not None:
payload["saveInSession"] = save_in_session
if parameters is not None:
for key, value in parameters.items():
payload["query.param." + key] = value
if required_version is not None:
payload["apiVersion"] = required_version
return server_context.make_request(url, payload, timeout=timeout)
def insert_rows(
server_context,
schema_name: str,
query_name: str,
rows: List[any],
container_path: str = None,
skip_reselect_rows: bool = False,
transacted: bool = True,
audit_behavior: AuditBehavior = None,
audit_user_comment: str = None,
timeout: int = _default_timeout,
):
"""
Insert row(s) into table
:param server_context: A LabKey server context. See utils.create_server_context.
:param schema_name: schema of table
:param query_name: table name to insert into
:param rows: set of rows to insert
:param container_path: labkey container path if not already set in context
:param skip_reselect_rows: whether the full detailed response for the insert can be skipped
:param transacted: whether all of the updates should be done in a single transaction
:param audit_behavior: used to override the audit behavior for the update. See class query.AuditBehavior
:param audit_user_comment: used to provide a comment that will be attached to certain detailed audit log records
:param timeout: timeout of request in seconds (defaults to 300s)
:return:
"""
url = server_context.build_url("query", "insertRows.api", container_path=container_path)
payload = {"schemaName": schema_name, "queryName": query_name, "rows": rows}
if skip_reselect_rows is True:
payload["skipReselectRows"] = skip_reselect_rows
if transacted is False:
payload["transacted"] = transacted
if audit_behavior is not None:
payload["auditBehavior"] = audit_behavior
if audit_user_comment is not None:
payload["auditUserComment"] = audit_user_comment
return server_context.make_request(
url,
json=payload,
timeout=timeout,
)
def import_rows(
server_context: ServerContext,
schema_name: str,
query_name: str,
data_file: TextIO,
container_path: str = None,
insert_option: str = None,
audit_behavior: str = None,
import_lookup_by_alternate_key: bool = False,
):
"""
Import row(s) into a table
:param server_context: A LabKey server context. See utils.create_server_context.
:param schema_name: schema of table
:param query_name: table name to import into
:param data_file: the file containing the rows to import. The column names in the file must match the column names
from the LabKey server.
:param container_path: labkey container path if not already set in context
:param insert_option: Whether the import action should be done as an insert, creating new rows for each provided row
of the data frame, or a merge. When merging during import, any data you provide for the rows representing records
that already exist will replace the previous values. Note that when updating an existing record, you only need to
provide the columns you wish to update, existing data for other columns will be left as is. Available options are
"INSERT" and "MERGE". Defaults to "INSERT".
:param audit_behavior: Set the level of auditing details for this import action. Available options are "SUMMARY" and
"DETAILED". SUMMARY - Audit log reflects that a change was made, but does not mention the nature of the change.
DETAILED - Provides full details on what change was made, including values before and after the change. Defaults to
the setting as specified by the LabKey query.
:param import_lookup_by_alternate_key: Allows lookup target rows to be resolved by values rather than the target's
primary key. This option will only be available for lookups that are configured with unique column information
:return:
"""
url = server_context.build_url("query", "import.api", container_path=container_path)
file_payload = {"file": data_file}
payload = {
"schemaName": schema_name,
"queryName": query_name,
}
if insert_option is not None:
payload["insertOption"] = insert_option
if audit_behavior is not None:
payload["auditBehavior"] = audit_behavior
if import_lookup_by_alternate_key is not None:
payload["importLookupByAlternateKey"] = import_lookup_by_alternate_key
return server_context.make_request(url, payload, method="POST", file_payload=file_payload)
class Command(TypedDict):
"""
TypedDict representing a command for saveRows API.
"""
audit_behavior: NotRequired[AuditBehavior]
audit_user_comment: NotRequired[str]
command: Literal["insert", "update", "delete"]
container_path: NotRequired[str]
extra_context: NotRequired[dict]
query_name: str
rows: List[any]
schema_name: str
skip_reselect_rows: NotRequired[bool]
def save_rows(
server_context: ServerContext,
commands: List[Command],
api_version: float = None,
container_path: str = None,
extra_context: dict = None,
timeout: int = _default_timeout,
transacted: bool = None,
validate_only: bool = None,
):
"""
Save inserts, updates, and/or deletes to potentially multiple tables with a single request.
:param server_context: A LabKey server context. See utils.create_server_context.
:param commands: A List of the update/insert/delete operations to be performed.
:param api_version: decimal value that indicates the response version of the api. If this is 13.2 or higher, a
request that fails validation will be returned as a successful response. Use the 'errorCount' and 'committed'
properties in the response to tell if it committed or not.
:param container_path: folder path if not already part of server_context
:param extra_context: Extra context object passed into the transformation/validation script environment.
:param timeout: Request timeout in seconds (defaults to 300s)
:param transacted: Whether all the commands should be done in a single transaction, so they all succeed or all
fail. Defaults to true.
:param validate_only: Whether the server should attempt to proceed through all the commands but not commit them to
the database. Useful for scenarios like giving incremental validation feedback as a user fills out a UI form but
does not save anything until they explicitly request a save.
"""
url = server_context.build_url("query", "saveRows.api", container_path=container_path)
json_commands = []
for command in commands:
json_command = {
"command": command["command"],
"queryName": command["query_name"],
"schemaName": command["schema_name"],
"rows": command["rows"],
}
if command.get("audit_behavior") is not None:
json_command["auditBehavior"] = command["audit_behavior"]
if command.get("audit_user_comment") is not None:
json_command["auditUserComment"] = command["audit_user_comment"]
if command.get("container_path") is not None:
json_command["containerPath"] = command["container_path"]
if command.get("extra_context") is not None:
json_command["extraContext"] = command["extra_context"]
if command.get("skip_reselect_rows") is not None:
json_command["skipReselectRows"] = command["skip_reselect_rows"]
json_commands.append(json_command)
payload = {"commands": json_commands}
if api_version is not None:
payload["apiVersion"] = api_version
if extra_context is not None:
payload["extraContext"] = extra_context
if transacted is not None:
payload["transacted"] = transacted
if validate_only is not None:
payload["validateOnly"] = validate_only
return server_context.make_request(url, json=payload, timeout=timeout)
def select_rows(
server_context: ServerContext,
schema_name: str,
query_name: str,
view_name: str = None,
filter_array: List[QueryFilter] = None,
container_path: str = None,
columns=None,
max_rows: int = -1,
sort: str = None,
offset: int = None,
container_filter: str = None,
parameters: dict = None,
show_rows: bool = None,
include_total_count: bool = None,
include_details_column: bool = None,
include_update_column: bool = None,
selection_key: str = None,
required_version: float = None,
timeout: int = _default_timeout,
ignore_filter: bool = None,
):
"""
Query data from a LabKey server
:param server_context: A LabKey server context. See utils.create_server_context.
:param schema_name: schema of table
:param query_name: table name to select from
:param view_name: pre-existing named view
:param filter_array: set of filter objects to apply
:param container_path: folder path if not already part of server_context
:param columns: set of columns to retrieve
:param max_rows: max number of rows to retrieve, defaults to -1 (unlimited)
:param sort: comma separated list of column names to sort by, prefix a column with '-' to sort descending
:param offset: number of rows to offset results by
:param container_filter: enumeration of the various container filters available. See:
https://www.labkey.org/download/clientapi_docs/javascript-api/symbols/LABKEY.Query.html#.containerFilter
:param parameters: Set of parameters to pass along to a parameterized query
:param show_rows: An enumeration of various paging styles
:param include_total_count: Boolean value that indicates whether to include a total count value in response
:param include_details_column: Boolean value that indicates whether to include a Details link column in results
:param include_update_column: Boolean value that indicates whether to include an Update link column in results
:param selection_key:
:param required_version: decimal value that indicates the response version of the api
:param timeout: Request timeout in seconds (defaults to 300s)
:param ignore_filter: Boolean, if true, the command will ignore any filter that may be part of the chosen view.
:return:
"""
url = server_context.build_url("query", "getQuery.api", container_path=container_path)
payload = {"schemaName": schema_name, "query.queryName": query_name}
if view_name is not None:
payload["query.viewName"] = view_name
if filter_array is not None:
for query_filter in filter_array:
prefix = query_filter.get_url_parameter_name()
# Use a list for each prefix, as a prefix may have multiple different
# filter values associated for it.
filters = payload.get(prefix, [])
filters.append(query_filter.get_url_parameter_value())
payload[prefix] = filters
if columns is not None:
payload["query.columns"] = columns
if max_rows is not None:
payload["query.maxRows"] = max_rows
if sort is not None:
payload["query.sort"] = sort
if offset is not None:
payload["query.offset"] = offset
if container_filter is not None:
payload["containerFilter"] = container_filter
if parameters is not None:
for key, value in parameters.items():
payload["query.param." + key] = value
if show_rows is not None:
payload["query.showRows"] = show_rows
if include_total_count is not None:
payload["includeTotalCount"] = include_total_count
if include_details_column is not None:
payload["includeDetailsColumn"] = include_details_column
if include_update_column is not None:
payload["includeUpdateColumn"] = include_update_column
if selection_key is not None:
payload["query.selectionKey"] = selection_key
if required_version is not None:
payload["apiVersion"] = required_version
if ignore_filter is not None and ignore_filter is True:
payload["query.ignoreFilter"] = 1
return server_context.make_request(url, payload, timeout=timeout)
def update_rows(
server_context: ServerContext,
schema_name: str,
query_name: str,
rows: List[any],
container_path: str = None,
transacted: bool = True,
audit_behavior: AuditBehavior = None,
audit_user_comment: str = None,
timeout: int = _default_timeout,
):
"""
Update a set of rows
:param server_context: A LabKey server context. See utils.create_server_context.
:param schema_name: schema of table
:param query_name: table name to update
:param rows: Set of rows to update
:param container_path: labkey container path if not already set in context
:param transacted: whether all of the updates should be done in a single transaction
:param audit_behavior: used to override the audit behavior for the update. See class query.AuditBehavior
:param audit_user_comment: used to provide a comment that will be attached to certain detailed audit log records
:param timeout: timeout of request in seconds (defaults to 300s)
:return:
"""
url = server_context.build_url("query", "updateRows.api", container_path=container_path)
payload = {"schemaName": schema_name, "queryName": query_name, "rows": rows}
if transacted is False:
payload["transacted"] = transacted
if audit_behavior is not None:
payload["auditBehavior"] = audit_behavior
if audit_user_comment is not None:
payload["auditUserComment"] = audit_user_comment
return server_context.make_request(
url,
json=payload,
timeout=timeout,
)
def move_rows(
server_context: ServerContext,
target_container_path: str,
schema_name: str,
query_name: str,
rows: any,
container_path: str = None,
transacted: bool = True,
audit_behavior: AuditBehavior = None,
audit_user_comment: str = None,
timeout: int = _default_timeout,
):
"""
Move a set of rows from the schema.query
:param server_context: A LabKey server context. See utils.create_server_context.
:param target_container_path: target labkey container path for the move
:param schema_name: schema of table
:param query_name: table name to move from
:param rows: Set of rows to move
:param container_path: source labkey container path if not already set in context
:param transacted: whether all of the updates should be done in a single transaction
:param audit_behavior: used to override the audit behavior for the update. See class query.AuditBehavior
:param audit_user_comment: used to provide a comment that will be attached to certain detailed audit log records
:param timeout: timeout of request in seconds (defaults to 300s)
:return:
"""
url = server_context.build_url("query", "moveRows.api", container_path=container_path)
payload = {
"targetContainerPath": target_container_path,
"schemaName": schema_name,
"queryName": query_name,
"rows": rows,
}
if transacted is False:
payload["transacted"] = transacted
if audit_behavior is not None:
payload["auditBehavior"] = audit_behavior
if audit_user_comment is not None:
payload["auditUserComment"] = audit_user_comment
return server_context.make_request(
url,
json=payload,
timeout=timeout,
)
class QueryWrapper:
"""
Wrapper for all of the API methods exposed in the query module. Used by the APIWrapper class.
"""
def __init__(self, server_context: ServerContext):
self.server_context = server_context
@functools.wraps(delete_rows)
def delete_rows(
self,
schema_name: str,
query_name: str,
rows: any,
container_path: str = None,
transacted: bool = True,
audit_behavior: AuditBehavior = None,
audit_user_comment: str = None,
timeout: int = _default_timeout,
):
return delete_rows(
self.server_context,
schema_name,
query_name,
rows,
container_path,
transacted,
audit_behavior,
audit_user_comment,
timeout,
)
@functools.wraps(truncate_table)
def truncate_table(
self, schema_name, query_name, container_path=None, timeout=_default_timeout
):
return truncate_table(self.server_context, schema_name, query_name, container_path, timeout)
@functools.wraps(execute_sql)
def execute_sql(
self,
schema_name: str,
sql: str,
container_path: str = None,
max_rows: int = None,
sort: str = None,
offset: int = None,
container_filter: str = None,
save_in_session: bool = None,
parameters: dict = None,
required_version: float = None,
timeout: int = _default_timeout,
waf_encode_sql: bool = True,
):
return execute_sql(
self.server_context,
schema_name,
sql,
container_path,
max_rows,
sort,
offset,
container_filter,
save_in_session,
parameters,
required_version,
timeout,
waf_encode_sql,
)
@functools.wraps(insert_rows)
def insert_rows(
self,
schema_name: str,
query_name: str,
rows: List[any],
container_path: str = None,
skip_reselect_rows: bool = False,
transacted: bool = True,
audit_behavior: AuditBehavior = None,
audit_user_comment: str = None,
timeout: int = _default_timeout,
):
return insert_rows(
self.server_context,
schema_name,
query_name,
rows,
container_path,
skip_reselect_rows,
transacted,
audit_behavior,
audit_user_comment,
timeout,
)
@functools.wraps(import_rows)
def import_rows(
self,
schema_name: str,
query_name: str,
data_file,
container_path: str = None,
insert_option: str = None,
audit_behavior: str = None,
import_lookup_by_alternate_key: bool = False,
):
return import_rows(
self.server_context,
schema_name,
query_name,
data_file,
container_path,
insert_option,
audit_behavior,
import_lookup_by_alternate_key,
)
@functools.wraps(save_rows)
def save_rows(
self,
commands: List[Command],
api_version: float = None,
container_path: str = None,
extra_context: dict = None,
timeout: int = _default_timeout,
transacted: bool = None,
validate_only: bool = None,
):
return save_rows(
self.server_context,
commands,
api_version,
container_path,
extra_context,
timeout,
transacted,
validate_only,
)
@functools.wraps(select_rows)
def select_rows(
self,
schema_name: str,
query_name: str,
view_name: str = None,
filter_array: List[QueryFilter] = None,
container_path: str = None,
columns=None,
max_rows: int = -1,
sort: str = None,
offset: int = None,
container_filter: str = None,
parameters: dict = None,
show_rows: bool = None,
include_total_count: bool = None,
include_details_column: bool = None,
include_update_column: bool = None,
selection_key: str = None,
required_version: float = None,
timeout: int = _default_timeout,
ignore_filter: bool = None,
):
return select_rows(
self.server_context,
schema_name,
query_name,
view_name,
filter_array,
container_path,
columns,
max_rows,
sort,
offset,
container_filter,
parameters,
show_rows,
include_total_count,
include_details_column,
include_update_column,
selection_key,
required_version,
timeout,
ignore_filter,
)
@functools.wraps(update_rows)
def update_rows(
self,
schema_name: str,
query_name: str,
rows: List[any],
container_path: str = None,
transacted: bool = True,
audit_behavior: AuditBehavior = None,
audit_user_comment: str = None,
timeout: int = _default_timeout,
):
return update_rows(
self.server_context,
schema_name,
query_name,
rows,
container_path,
transacted,
audit_behavior,
audit_user_comment,
timeout,
)
@functools.wraps(move_rows)
def move_rows(
self,
target_container_path: str,
schema_name: str,
query_name: str,
rows: any,
container_path: str = None,
transacted: bool = True,
audit_behavior: AuditBehavior = None,
audit_user_comment: str = None,
timeout: int = _default_timeout,
):
return move_rows(
self.server_context,
target_container_path,
schema_name,
query_name,
rows,
container_path,
transacted,
audit_behavior,
audit_user_comment,
timeout,
)