api-foundry-query-engine 0.0.1__py3-none-any.whl

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.
Files changed (27) hide show
  1. api_foundry_query_engine/adapters/adapter.py +67 -0
  2. api_foundry_query_engine/adapters/case_change_adapter.py +79 -0
  3. api_foundry_query_engine/adapters/gateway_adapter.py +112 -0
  4. api_foundry_query_engine/connectors/connection.py +32 -0
  5. api_foundry_query_engine/connectors/connection_factory.py +110 -0
  6. api_foundry_query_engine/connectors/oracle_connector.py +29 -0
  7. api_foundry_query_engine/connectors/postgres_connection.py +105 -0
  8. api_foundry_query_engine/dao/dao.py +23 -0
  9. api_foundry_query_engine/dao/operation_dao.py +141 -0
  10. api_foundry_query_engine/dao/sql_custom_query_handler.py +66 -0
  11. api_foundry_query_engine/dao/sql_delete_query_handler.py +36 -0
  12. api_foundry_query_engine/dao/sql_insert_query_handler.py +102 -0
  13. api_foundry_query_engine/dao/sql_query_handler.py +386 -0
  14. api_foundry_query_engine/dao/sql_select_query_handler.py +305 -0
  15. api_foundry_query_engine/dao/sql_subselect_query_handler.py +63 -0
  16. api_foundry_query_engine/dao/sql_update_query_handler.py +59 -0
  17. api_foundry_query_engine/handler.py +48 -0
  18. api_foundry_query_engine/operation.py +15 -0
  19. api_foundry_query_engine/services/service.py +60 -0
  20. api_foundry_query_engine/services/transactional_service.py +43 -0
  21. api_foundry_query_engine/utils/api_model.py +175 -0
  22. api_foundry_query_engine/utils/app_exception.py +22 -0
  23. api_foundry_query_engine/utils/logger.py +60 -0
  24. api_foundry_query_engine-0.0.1.dist-info/METADATA +14 -0
  25. api_foundry_query_engine-0.0.1.dist-info/RECORD +27 -0
  26. api_foundry_query_engine-0.0.1.dist-info/WHEEL +4 -0
  27. api_foundry_query_engine-0.0.1.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,63 @@
1
+ from typing import Optional
2
+
3
+ from api_foundry_query_engine.dao.sql_query_handler import SQLSchemaQueryHandler
4
+ from api_foundry_query_engine.dao.sql_select_query_handler import SQLSelectSchemaQueryHandler
5
+ from api_foundry_query_engine.operation import Operation
6
+ from api_foundry_query_engine.utils.api_model import SchemaObjectAssociation
7
+
8
+
9
+ class SQLSubselectSchemaQueryHandler(SQLSelectSchemaQueryHandler):
10
+ def __init__(
11
+ self,
12
+ operation: Operation,
13
+ relation: SchemaObjectAssociation,
14
+ parent_generator: SQLSchemaQueryHandler,
15
+ ) -> None:
16
+ super().__init__(
17
+ operation, relation.child_schema_object, parent_generator.engine
18
+ )
19
+ self.relation = relation
20
+ self.parent_generator = parent_generator
21
+
22
+ def selection_result_map(self) -> dict:
23
+ filter_str = self.operation.metadata_params.get("properties", "")
24
+ result = {self.relation.child_property: self.relation.child_property}
25
+
26
+ for relation_name, reg_exs in self.get_regex_map(filter_str).items():
27
+ if relation_name != self.relation.api_name:
28
+ continue
29
+
30
+ schema_object = self.relation.child_schema_object
31
+
32
+ # Filter and prefix keys for the current entity and regular expressions
33
+ filtered_keys = self.filter_and_prefix_keys(
34
+ reg_exs, schema_object.properties
35
+ )
36
+
37
+ # Extend the result map with the filtered keys
38
+ result.update(filtered_keys)
39
+
40
+ return result
41
+
42
+ @property
43
+ def placeholders(self) -> dict:
44
+ return self.search_placeholders
45
+
46
+ @property
47
+ def sql(self) -> Optional[str]:
48
+ if len(self.select_list_columns) == 1: # then it only contains the key
49
+ return None
50
+
51
+ sql = (
52
+ f"SELECT {self.select_list} "
53
+ + f"FROM {self.relation.child_schema_object.table_name} "
54
+ + f"WHERE {self.relation.child_property} "
55
+ + f"IN ( SELECT {self.relation.parent_property} "
56
+ + f"FROM {self.parent_generator.table_expression}"
57
+ + f"{self.parent_generator.search_condition} "
58
+ # + f"{order_by} {limit} {offset})"
59
+ + ")"
60
+ )
61
+ self.search_placeholders = self.parent_generator.search_placeholders
62
+ # self._execute_sql(args["cursor"], sql, query_parameters)
63
+ return sql
@@ -0,0 +1,59 @@
1
+ from api_foundry_query_engine.dao.sql_query_handler import SQLSchemaQueryHandler
2
+ from api_foundry_query_engine.operation import Operation
3
+ from api_foundry_query_engine.utils.app_exception import ApplicationException
4
+ from api_foundry_query_engine.utils.api_model import SchemaObject
5
+
6
+
7
+ class SQLUpdateSchemaQueryHandler(SQLSchemaQueryHandler):
8
+ def __init__(
9
+ self, operation: Operation, schema_object: SchemaObject, engine: str
10
+ ) -> None:
11
+ super().__init__(operation, schema_object, engine)
12
+
13
+ @property
14
+ def sql(self) -> str:
15
+ concurrency_property = self.schema_object.concurrency_property
16
+ if not concurrency_property:
17
+ return (
18
+ f"UPDATE {self.table_expression}{self.update_values}"
19
+ + f"{self.search_condition} RETURNING {self.select_list}"
20
+ )
21
+
22
+ if not self.operation.query_params.get(concurrency_property.api_name):
23
+ raise ApplicationException(
24
+ 400,
25
+ "Missing required concurrency management property. "
26
+ + f"schema_object: {self.schema_object.api_name}, "
27
+ + f"property: {concurrency_property.api_name}",
28
+ )
29
+ if self.operation.store_params.get(concurrency_property.api_name):
30
+ raise ApplicationException(
31
+ 400,
32
+ "For updating concurrency managed schema objects the current version "
33
+ + " may not be supplied as a storage parameter. "
34
+ + f"schema_object: {self.schema_object.api_name}, "
35
+ + f"property: {concurrency_property.api_name}",
36
+ )
37
+
38
+ return f"UPDATE {self.table_expression}{self.update_values}, {concurrency_property.column_name} = {self.concurrency_generator(concurrency_property)} {self.search_condition} RETURNING {self.select_list}" # noqa E501
39
+
40
+ @property
41
+ def update_values(self) -> str:
42
+ self.store_placeholders = {}
43
+ columns = []
44
+
45
+ for name, value in self.operation.store_params.items():
46
+ try:
47
+ property = self.schema_object.properties[name]
48
+ except KeyError:
49
+ raise ApplicationException(
50
+ 400, f"Search condition column not found {name}"
51
+ )
52
+
53
+ placeholder = property.api_name
54
+ column_name = property.column_name
55
+
56
+ columns.append(f"{column_name} = {self.placeholder(property, placeholder)}")
57
+ self.store_placeholders[placeholder] = property.convert_to_db_value(value)
58
+
59
+ return f" SET {', '.join(columns)}"
@@ -0,0 +1,48 @@
1
+ import json
2
+ import logging
3
+ import os
4
+ import yaml
5
+
6
+ from api_foundry_query_engine.utils.app_exception import ApplicationException
7
+ from api_foundry_query_engine.utils.api_model import APIModel
8
+
9
+ from api_foundry_query_engine.adapters.gateway_adapter import GatewayAdapter
10
+
11
+ log = logging.getLogger(__name__)
12
+
13
+ api_model = None
14
+ adapter = GatewayAdapter()
15
+
16
+
17
+ def lambda_handler(event, _):
18
+ log.debug(f"event: {event}")
19
+ try:
20
+ if not api_model:
21
+ with open(os.environ.get("API_SPEC", "/var/task/api_spec.yaml"), "r") as file:
22
+ api_model = APIModel(yaml.safe_load(file))
23
+
24
+ response = adapter.process_event(event)
25
+
26
+ # Ensure the response conforms to API Gateway requirements
27
+ return {
28
+ "isBase64Encoded": False,
29
+ "statusCode": 200,
30
+ "headers": {"Content-Type": "application/json"},
31
+ "body": json.dumps(response),
32
+ }
33
+ except ApplicationException as e:
34
+ log.error(f"exception: {e}", exc_info=True)
35
+ return {
36
+ "isBase64Encoded": False,
37
+ "statusCode": e.status_code,
38
+ "headers": {"Content-Type": "application/json"},
39
+ "body": json.dumps({"message": f"exception: {e}"}),
40
+ }
41
+ except Exception as e:
42
+ log.error(f"exception: {e}", exc_info=True)
43
+ return {
44
+ "isBase64Encoded": False,
45
+ "statusCode": 500,
46
+ "headers": {"Content-Type": "application/json"},
47
+ "body": json.dumps({"message": f"exception: {e}"}),
48
+ }
@@ -0,0 +1,15 @@
1
+ class Operation:
2
+ def __init__(
3
+ self,
4
+ *,
5
+ entity: str,
6
+ action: str,
7
+ query_params={},
8
+ store_params={},
9
+ metadata_params={},
10
+ ):
11
+ self.entity = entity
12
+ self.action = action
13
+ self.query_params = query_params
14
+ self.store_params = store_params
15
+ self.metadata_params = metadata_params
@@ -0,0 +1,60 @@
1
+ import hashlib
2
+ import json
3
+ import os
4
+
5
+ from api_foundry_query_engine.utils.logger import logger
6
+ from api_foundry_query_engine.operation import Operation
7
+
8
+ log = logger(__name__)
9
+
10
+
11
+ class Service:
12
+ def execute(self, operation: Operation) -> list[dict]:
13
+ raise NotImplementedError
14
+
15
+
16
+ class ServiceAdapter(Service):
17
+ def execute(self, operation):
18
+ super().execute(operation)
19
+
20
+
21
+ class MutationPublisher(ServiceAdapter):
22
+ def execute(self, operation):
23
+ result = super().execute(operation)
24
+ self.publish_notification(operation)
25
+ return result
26
+
27
+ def publish_notification(self, operation):
28
+ topic_arn = os.environ.get("BROADCAST_TOPIC", None)
29
+ log.debug(f"Topic ARN: {topic_arn}")
30
+
31
+ if topic_arn is not None:
32
+ log.debug("Sending message")
33
+ message = {
34
+ "entity": operation.api_name,
35
+ "action": operation.action,
36
+ "store_params": operation.store_params,
37
+ "query_params": operation.query_params,
38
+ }
39
+
40
+ message_str = json.dumps({"default": json.dumps(message)})
41
+ log.debug(f"message_str: {message_str}")
42
+ hash_object = hashlib.sha256(message_str.encode("utf-8"))
43
+ hex_dig = hash_object.hexdigest()
44
+
45
+ msg_id = self.__client("sns").publish(
46
+ TopicArn=topic_arn,
47
+ MessageStructure="json",
48
+ MessageDeduplicationId=hex_dig,
49
+ MessageGroupId=operation.api_name,
50
+ Message=message_str,
51
+ )
52
+ log.info(f"publish msg id {msg_id}")
53
+
54
+ def __client(client_type, region: str = os.environ.get("AWS_REGION", "us-east-1")):
55
+ import boto3
56
+
57
+ session = boto3.session.Session()
58
+ if session:
59
+ return session.client(client_type, region_name=region)
60
+ return boto3.client(client_type, region_name=region)
@@ -0,0 +1,43 @@
1
+ import traceback
2
+
3
+ from api_foundry_query_engine.utils.logger import logger
4
+ from api_foundry_query_engine.utils.app_exception import ApplicationException
5
+ from api_foundry_query_engine.operation import Operation
6
+ from api_foundry_query_engine.services.service import ServiceAdapter
7
+ from api_foundry_query_engine.connectors.connection_factory import connection_factory
8
+ from api_foundry_query_engine.dao.operation_dao import OperationDAO
9
+ from api_foundry_query_engine.utils.api_model import get_path_operation, get_schema_object
10
+
11
+ log = logger(__name__)
12
+
13
+
14
+ class TransactionalService(ServiceAdapter):
15
+ def execute(self, operation: Operation):
16
+ path_operation = get_path_operation(operation.entity, operation.action)
17
+ if path_operation:
18
+ database = path_operation.database
19
+ else:
20
+ schema_object = get_schema_object(operation.entity)
21
+ if schema_object:
22
+ database = schema_object.database
23
+ else:
24
+ raise ApplicationException(500, f"Unknown operation: {operation.entity}")
25
+
26
+ connection = connection_factory.get_connection(database)
27
+
28
+ try:
29
+ result = None
30
+ cursor = connection.cursor()
31
+ try:
32
+ result = OperationDAO(operation, connection.engine()).execute(cursor)
33
+ finally:
34
+ cursor.close()
35
+ if operation.action != "read":
36
+ connection.commit()
37
+ return result
38
+ except Exception as error:
39
+ log.error(f"transaction exception: {error}")
40
+ log.error(f"traceback: {traceback.format_exc()}")
41
+ raise error
42
+ finally:
43
+ connection.close()
@@ -0,0 +1,175 @@
1
+ from datetime import datetime
2
+ from typing import Any, Dict, Optional
3
+
4
+ from api_foundry_query_engine.utils.logger import logger
5
+
6
+ log = logger(__name__)
7
+
8
+
9
+ class SchemaObjectProperty:
10
+ """Represents a property of a schema object."""
11
+
12
+ def __init__(self, data: Dict[str, Any]):
13
+ self.api_name = data.get("api_name")
14
+ self.column_name = data.get("column_name")
15
+ self.type = data.get("type")
16
+ self.api_type = data.get("api_type")
17
+ self.column_type = data.get("column_type")
18
+ self.required = data.get("required", False)
19
+ self.min_length = data.get("min_length")
20
+ self.max_length = data.get("max_length")
21
+ self.pattern = data.get("pattern")
22
+ self.default = data.get("default")
23
+ self.key_type = data.get("key_type")
24
+ self.sequence_name = data.get("sequence_name")
25
+ self.concurrency_control = data.get("concurrency_control")
26
+
27
+ def __repr__(self):
28
+ return f"SchemaObjectProperty(api_name={self.api_name}, column_name={self.column_name}, type={self.type})"
29
+
30
+ def convert_to_db_value(self, value: str) -> Optional[Any]:
31
+ if value is None:
32
+ return None
33
+ conversion_mapping = {
34
+ "string": lambda x: x,
35
+ "number": float,
36
+ "float": float,
37
+ "integer": int,
38
+ "boolean": lambda x: x.lower() == "true",
39
+ "date": lambda x: datetime.strptime(x, "%Y-%m-%d").date() if x else None,
40
+ "date-time": lambda x: datetime.fromisoformat(x) if x else None,
41
+ "time": lambda x: datetime.strptime(x, "%H:%M:%S").time() if x else None,
42
+ }
43
+ conversion_func = conversion_mapping.get(self.column_type, lambda x: x)
44
+ return conversion_func(value)
45
+
46
+ def convert_to_api_value(self, value) -> Optional[Any]:
47
+ if value is None:
48
+ return None
49
+ conversion_mapping = {
50
+ "string": lambda x: x,
51
+ "number": float,
52
+ "float": float,
53
+ "integer": int,
54
+ "boolean": str,
55
+ "date": lambda x: x.date().isoformat() if x else None,
56
+ "date-time": lambda x: x.isoformat() if x else None,
57
+ "time": lambda x: x.time().isoformat() if x else None,
58
+ }
59
+ conversion_func = conversion_mapping.get(self.api_type, lambda x: x)
60
+ return conversion_func(value)
61
+
62
+
63
+
64
+ class SchemaObjectAssociation:
65
+ """Represents an association (relationship) between schema objects."""
66
+
67
+ def __init__(self, parent_schema: str, data: Dict[str, Any]):
68
+ self.parent_schema = parent_schema
69
+ self.schema_name = data.get("schema_name")
70
+ self.api_name = data.get("api_name")
71
+ self.type = data.get("type")
72
+ self._child_property = data.get("child_property")
73
+ self._parent_property = data.get("parent_property")
74
+
75
+ @property
76
+ def child_property(self) -> str:
77
+ return self._child_property if self._child_property else get_schema_object(self.schema_name).primary_key.column_name
78
+
79
+ @property
80
+ def parent_property(self) -> str:
81
+ return self._parent_property if self._parent_property else get_schema_object(self.parent_schema).primary_key.column_name
82
+
83
+ def __repr__(self):
84
+ return f"SchemaObjectAssociation(name={self.api_name}, child_property={self._child_property}, parent_property={self.parent_property})"
85
+
86
+ @property
87
+ def child_schema_object(self) -> "SchemaObject":
88
+ return get_schema_object(self.schema_name)
89
+
90
+
91
+
92
+ class SchemaObject:
93
+ """Represents a schema object in the API configuration."""
94
+
95
+ def __init__(self, data: Dict[str, Any]):
96
+ self.api_name = data.get("api_name")
97
+ self.database = data.get("database")
98
+ self.table_name = data.get("table_name")
99
+ self.properties = {
100
+ name: SchemaObjectProperty(prop_data)
101
+ for name, prop_data in data.get("properties", {}).items()
102
+ }
103
+ self.relations = {
104
+ name: SchemaObjectAssociation(self.api_name, assoc_data)
105
+ for name, assoc_data in data.get("relations", {}).items()
106
+ }
107
+ self.concurrency_property = (
108
+ self.properties[data.get("concurrency_property")]
109
+ if data.get("concurrency_property")
110
+ else None
111
+ )
112
+ self._primary_key = data.get("primary_key")
113
+
114
+ def __repr__(self):
115
+ return f"SchemaObject(table_name={self.table_name}, primary_key={self.primary_key})"
116
+
117
+ @property
118
+ def primary_key(self):
119
+ return self.properties.get(self._primary_key)
120
+
121
+ class PathOperation:
122
+ """Represents a path operation in the API configuration."""
123
+
124
+ def __init__(self, data: Dict[str, Any]):
125
+ self.entity = data["entity"]
126
+ self.action = data["action"]
127
+ self.sql = data["sql"]
128
+ self.database = data["database"]
129
+ self.inputs = {
130
+ name: SchemaObjectProperty(input_data)
131
+ for name, input_data in data.get("inputs", {}).items()
132
+ }
133
+ self.outputs = {
134
+ name: SchemaObjectProperty(output_data)
135
+ for name, output_data in data.get("outputs", {}).items()
136
+ }
137
+
138
+ def __repr__(self):
139
+ return f"PathOperation(entity={self.entity}, method={self.method})"
140
+
141
+
142
+ schema_objects = None
143
+ path_operations = None
144
+
145
+ def get_schema_object(name: str) -> Optional[SchemaObject]:
146
+ """Returns a schema object by name."""
147
+ global schema_objects
148
+ return schema_objects.get(name)
149
+
150
+ def get_path_operation(path: str, method:str) -> Optional[PathOperation]:
151
+ """Returns a path operation by name."""
152
+ log.info(f"path: {path}, method: {method}")
153
+ global path_operations
154
+ return path_operations.get(f"{path}_{method}")
155
+
156
+
157
+ class APIModel:
158
+ """Class to load and expose the API configuration as objects."""
159
+
160
+ def __init__(self, config: Dict[str, Any]):
161
+ print("building api_model")
162
+ global schema_objects
163
+ schema_objects = {
164
+ name: SchemaObject(schema_data)
165
+ for name, schema_data in config.get("schema_objects", {}).items()
166
+ }
167
+ global path_operations
168
+ path_operations = {
169
+ name: PathOperation(path_data)
170
+ for name, path_data in config.get("path_operations", {}).items()
171
+ }
172
+
173
+ def __repr__(self):
174
+ return f"APIModel(schema_objects={list(self.schema_objects.keys())}, path_operations={list(self.path_operations.keys())})"
175
+
@@ -0,0 +1,22 @@
1
+ class ApplicationException(Exception):
2
+ """Custom exception class for application errors."""
3
+
4
+ def __init__(self, status_code: int, message: str):
5
+ """
6
+ Initialize the ApplicationException.
7
+
8
+ Args:
9
+ - status_code (int): The HTTP status code associated with the
10
+ exception.
11
+ - message (str): The error message.
12
+ """
13
+ super().__init__(message)
14
+ self.status_code = status_code
15
+ self.message = message
16
+
17
+ def __str__(self):
18
+ """Return a string representation of the exception."""
19
+ return (
20
+ f"ApplicationException(status_code={self.status_code}, "
21
+ + f"message='{self.message}')"
22
+ )
@@ -0,0 +1,60 @@
1
+ import logging
2
+ import os
3
+
4
+ # Configuring the logging module with basic settings, including format and log level,
5
+ # where the log level is obtained from the environment variable LOGGING_LEVEL
6
+ # with a default of DEBUG, and force=True to ensure the configuration is applied immediately.
7
+ logging.basicConfig(
8
+ format="%(name)s:%(lineno)s - %(levelname)s - %(message)s",
9
+ level=os.getenv("LOGGING_LEVEL", "DEBUG").upper(),
10
+ force=True,
11
+ )
12
+
13
+ WARN = logging.WARN
14
+ INFO = logging.INFO
15
+ DEBUG = logging.DEBUG
16
+
17
+
18
+ def logger(name=None):
19
+ """
20
+ Function to create a logger with a specified name or default name.
21
+
22
+ Parameters:
23
+ name (str): Name of the logger. If not provided, the root logger is returned.
24
+
25
+ Returns:
26
+ logging.Logger: Logger object with the specified name or the root logger.
27
+
28
+ """
29
+ # Retrieving the logging level from the environment variable LOGGING_LEVEL
30
+ # with a default of DEBUG, and converting it to uppercase
31
+ loggingLevel = os.getenv("LOGGING_LEVEL", "DEBUG").upper()
32
+
33
+ # Setting the logging level for the root logger to the obtained logging level
34
+ logging.getLogger().setLevel(loggingLevel)
35
+
36
+ # Returning a logger object with the specified name or the root logger
37
+ return logging.getLogger(name)
38
+
39
+
40
+ def write_logging_file(file_name, content):
41
+ """
42
+ Function to write a given string to a file in the temp/logging folder.
43
+
44
+ Parameters:
45
+ file_name (str): Name of the file to write the content to.
46
+ content (str): The string content to write to the file.
47
+
48
+ """
49
+ # Define the directory path
50
+ dir_path = os.path.join("temp", "logging")
51
+
52
+ # Ensure the directory exists
53
+ os.makedirs(dir_path, exist_ok=True)
54
+
55
+ # Define the file path
56
+ file_path = os.path.join(dir_path, file_name)
57
+
58
+ # Write the content to the file
59
+ with open(file_path, "w") as file:
60
+ file.write(content + "\n")
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.3
2
+ Name: api-foundry-query-engine
3
+ Version: 0.0.1
4
+ Summary: The AWS lambda service handler use by the `api_foundry` project is a powerful tool designed to automate the deployment of REST APIs on AWS using Lambda services to access and interact with relational databases (RDBMS). This project leverages the OpenAPI specification to define and manage the APIs
5
+ Project-URL: Documentation, https://github.com/DanRepik/api-foundry
6
+ Project-URL: Source, https://github.com/DanRepik/api-foundry
7
+ Author-email: Daniel Repik <danrepik@icloud.com>
8
+ License-File: LICENSE
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Requires-Python: >=3.9
12
+ Requires-Dist: boto3
13
+ Requires-Dist: pyhumps
14
+ Requires-Dist: pyyaml
@@ -0,0 +1,27 @@
1
+ api_foundry_query_engine/handler.py,sha256=f7mo67G4rFE-WZq8nldrWbt2qjGR_OXygbXz6_Oh5us,1535
2
+ api_foundry_query_engine/operation.py,sha256=otkRKUfyTW2mWpy5mt2tM7k1w_a-4S068sjYtOeNqRM,374
3
+ api_foundry_query_engine/adapters/adapter.py,sha256=c4X7U3zWh5feR4NbIAPL-oY7-hLd2tiHITGPSXR7ZMQ,1901
4
+ api_foundry_query_engine/adapters/case_change_adapter.py,sha256=JhVOl3b4Dp2n5-u_-4MaO9FgCwCOnDzQ0oyJJYcTAMc,2314
5
+ api_foundry_query_engine/adapters/gateway_adapter.py,sha256=bUZvDM28QEEVjFnI1SBrwyY9iazY-QD1hQgMyBc3wq4,3168
6
+ api_foundry_query_engine/connectors/connection.py,sha256=aGm6R5wt1MW8_5wsrPYW6DI3jnaDhFc9a6CYzLuNVlk,702
7
+ api_foundry_query_engine/connectors/connection_factory.py,sha256=3Dj5qYT_bwzfl8XxQzqoe32qkGioXYo65BfQT3fBckM,3958
8
+ api_foundry_query_engine/connectors/oracle_connector.py,sha256=EtRoOqM8puUS62hoKyd2Gu2ghwPHXbXCtdlnOP50UcU,1020
9
+ api_foundry_query_engine/connectors/postgres_connection.py,sha256=0yM5Q6jaIT2hrYuiQxMftZkMYihrefMQVFKpn6XC4OE,3349
10
+ api_foundry_query_engine/dao/dao.py,sha256=aBFJ0WT0PhMitCJa5_PRBjDeBNj9hLDePRa-awnLtRg,684
11
+ api_foundry_query_engine/dao/operation_dao.py,sha256=LZN22vZ0WVjLIQk0SjSFw4aiU1_Ej2k7luPITwVS9eo,5376
12
+ api_foundry_query_engine/dao/sql_custom_query_handler.py,sha256=C7lXAzOkN4TdVByoOXZ2qLrc8vznilkbHh7mOiYNl5M,2423
13
+ api_foundry_query_engine/dao/sql_delete_query_handler.py,sha256=WByOIUQ83qlzcSFgppxxOWTodvV1cj7t3JZo2u3Oqbs,1656
14
+ api_foundry_query_engine/dao/sql_insert_query_handler.py,sha256=VF1TRsodNUoTR6MzOaujHTslLjEttg2poBj_z5e-WP8,4423
15
+ api_foundry_query_engine/dao/sql_query_handler.py,sha256=r7Car7KznJ3gI2E5bzjgw2TH4Sew12rWG3pAb4nAfno,12566
16
+ api_foundry_query_engine/dao/sql_select_query_handler.py,sha256=ZwqBE0cibsOT-AKrY1DMBwreqRIhytTe0oVcxGJk3vE,11841
17
+ api_foundry_query_engine/dao/sql_subselect_query_handler.py,sha256=URDe-p4k2csP5ncGnJkPQCxwITpWGXRqzXJH5st4Wgw,2392
18
+ api_foundry_query_engine/dao/sql_update_query_handler.py,sha256=1gz44r-PhpqGamC_subZ0zSSd5Wr9EnZQLkQoEj0-jg,2585
19
+ api_foundry_query_engine/services/service.py,sha256=0imMvYgNVgNPlyiZ70pC1ZhIvFCCZIcj8igtGum07Mg,1915
20
+ api_foundry_query_engine/services/transactional_service.py,sha256=Pf08l7uhlvZ2JqFkBb89FDMXnwj_OjWhQDFLUAu3PxM,1692
21
+ api_foundry_query_engine/utils/api_model.py,sha256=xB8IY-y2FgE08llWTkm6EDDc-qyAD_mKh54FByfaGjI,6388
22
+ api_foundry_query_engine/utils/app_exception.py,sha256=8F5DEL8ovY0vJBXE3RERTA26u7kthcSX0VqViplZhdE,704
23
+ api_foundry_query_engine/utils/logger.py,sha256=24u7AAVyzaPuS2nHSCq1SDemerJ8pCF5lde2NtIbwuo,1892
24
+ api_foundry_query_engine-0.0.1.dist-info/METADATA,sha256=dqfJMtvB1Ruoy-3djxzfTcsfyMqADpubZpIcSwgJ3yw,761
25
+ api_foundry_query_engine-0.0.1.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
26
+ api_foundry_query_engine-0.0.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
27
+ api_foundry_query_engine-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.25.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any