pydpm_xl 0.1.10__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.
- py_dpm/AST/ASTConstructor.py +503 -0
- py_dpm/AST/ASTObjects.py +827 -0
- py_dpm/AST/ASTTemplate.py +101 -0
- py_dpm/AST/ASTVisitor.py +13 -0
- py_dpm/AST/MLGeneration.py +588 -0
- py_dpm/AST/ModuleAnalyzer.py +79 -0
- py_dpm/AST/ModuleDependencies.py +203 -0
- py_dpm/AST/WhereClauseChecker.py +12 -0
- py_dpm/AST/__init__.py +0 -0
- py_dpm/AST/check_operands.py +302 -0
- py_dpm/DataTypes/ScalarTypes.py +324 -0
- py_dpm/DataTypes/TimeClasses.py +370 -0
- py_dpm/DataTypes/TypePromotion.py +195 -0
- py_dpm/DataTypes/__init__.py +0 -0
- py_dpm/Exceptions/__init__.py +0 -0
- py_dpm/Exceptions/exceptions.py +84 -0
- py_dpm/Exceptions/messages.py +114 -0
- py_dpm/OperationScopes/OperationScopeService.py +247 -0
- py_dpm/OperationScopes/__init__.py +0 -0
- py_dpm/Operators/AggregateOperators.py +138 -0
- py_dpm/Operators/BooleanOperators.py +30 -0
- py_dpm/Operators/ClauseOperators.py +159 -0
- py_dpm/Operators/ComparisonOperators.py +69 -0
- py_dpm/Operators/ConditionalOperators.py +362 -0
- py_dpm/Operators/NumericOperators.py +101 -0
- py_dpm/Operators/Operator.py +388 -0
- py_dpm/Operators/StringOperators.py +27 -0
- py_dpm/Operators/TimeOperators.py +53 -0
- py_dpm/Operators/__init__.py +0 -0
- py_dpm/Utils/ValidationsGenerationUtils.py +429 -0
- py_dpm/Utils/__init__.py +0 -0
- py_dpm/Utils/operands_mapping.py +73 -0
- py_dpm/Utils/operator_mapping.py +89 -0
- py_dpm/Utils/tokens.py +172 -0
- py_dpm/Utils/utils.py +2 -0
- py_dpm/ValidationsGeneration/PropertiesConstraintsProcessor.py +190 -0
- py_dpm/ValidationsGeneration/Utils.py +364 -0
- py_dpm/ValidationsGeneration/VariantsProcessor.py +265 -0
- py_dpm/ValidationsGeneration/__init__.py +0 -0
- py_dpm/ValidationsGeneration/auxiliary_functions.py +98 -0
- py_dpm/__init__.py +61 -0
- py_dpm/api/__init__.py +140 -0
- py_dpm/api/ast_generator.py +438 -0
- py_dpm/api/complete_ast.py +241 -0
- py_dpm/api/data_dictionary_validation.py +577 -0
- py_dpm/api/migration.py +77 -0
- py_dpm/api/semantic.py +224 -0
- py_dpm/api/syntax.py +182 -0
- py_dpm/client.py +106 -0
- py_dpm/data_handlers.py +99 -0
- py_dpm/db_utils.py +117 -0
- py_dpm/grammar/__init__.py +0 -0
- py_dpm/grammar/dist/__init__.py +0 -0
- py_dpm/grammar/dist/dpm_xlLexer.interp +428 -0
- py_dpm/grammar/dist/dpm_xlLexer.py +804 -0
- py_dpm/grammar/dist/dpm_xlLexer.tokens +106 -0
- py_dpm/grammar/dist/dpm_xlParser.interp +249 -0
- py_dpm/grammar/dist/dpm_xlParser.py +5224 -0
- py_dpm/grammar/dist/dpm_xlParser.tokens +106 -0
- py_dpm/grammar/dist/dpm_xlParserListener.py +742 -0
- py_dpm/grammar/dist/dpm_xlParserVisitor.py +419 -0
- py_dpm/grammar/dist/listeners.py +10 -0
- py_dpm/grammar/dpm_xlLexer.g4 +435 -0
- py_dpm/grammar/dpm_xlParser.g4 +260 -0
- py_dpm/migration.py +282 -0
- py_dpm/models.py +2139 -0
- py_dpm/semantics/DAG/DAGAnalyzer.py +158 -0
- py_dpm/semantics/DAG/__init__.py +0 -0
- py_dpm/semantics/SemanticAnalyzer.py +320 -0
- py_dpm/semantics/Symbols.py +223 -0
- py_dpm/semantics/__init__.py +0 -0
- py_dpm/utils/__init__.py +0 -0
- py_dpm/utils/ast_serialization.py +481 -0
- py_dpm/views/data_types.sql +12 -0
- py_dpm/views/datapoints.sql +65 -0
- py_dpm/views/hierarchy_operand_reference.sql +11 -0
- py_dpm/views/hierarchy_preconditions.sql +13 -0
- py_dpm/views/hierarchy_variables.sql +26 -0
- py_dpm/views/hierarchy_variables_context.sql +14 -0
- py_dpm/views/key_components.sql +18 -0
- py_dpm/views/module_from_table.sql +11 -0
- py_dpm/views/open_keys.sql +13 -0
- py_dpm/views/operation_info.sql +27 -0
- py_dpm/views/operation_list.sql +18 -0
- py_dpm/views/operations_versions_from_module_version.sql +30 -0
- py_dpm/views/precondition_info.sql +17 -0
- py_dpm/views/report_type_operand_reference_info.sql +18 -0
- py_dpm/views/subcategory_info.sql +17 -0
- py_dpm/views/table_info.sql +19 -0
- pydpm_xl-0.1.10.dist-info/LICENSE +674 -0
- pydpm_xl-0.1.10.dist-info/METADATA +50 -0
- pydpm_xl-0.1.10.dist-info/RECORD +94 -0
- pydpm_xl-0.1.10.dist-info/WHEEL +4 -0
- pydpm_xl-0.1.10.dist-info/entry_points.txt +3 -0
|
File without changes
|
py_dpm/utils/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
AST to JSON serialization utilities for pyDPM
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from py_dpm.AST.ASTVisitor import NodeVisitor
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ASTToJSONVisitor(NodeVisitor):
|
|
10
|
+
"""Visitor that converts AST nodes to JSON using the existing visitor pattern infrastructure."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, with_context=None):
|
|
13
|
+
self.with_context = with_context
|
|
14
|
+
|
|
15
|
+
def visit(self, node):
|
|
16
|
+
"""Override the base visit to handle None values."""
|
|
17
|
+
if node is None:
|
|
18
|
+
return None
|
|
19
|
+
return super().visit(node)
|
|
20
|
+
|
|
21
|
+
def visit_BinOp(self, node):
|
|
22
|
+
"""Visit BinOp nodes."""
|
|
23
|
+
# Handle match operations as MatchCharactersOp
|
|
24
|
+
if node.op == 'match':
|
|
25
|
+
return {
|
|
26
|
+
'class_name': 'MatchCharactersOp',
|
|
27
|
+
'operand': self.visit(node.left),
|
|
28
|
+
'pattern': self.visit(node.right)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
'class_name': 'BinOp',
|
|
33
|
+
'op': node.op,
|
|
34
|
+
'left': self.visit(node.left),
|
|
35
|
+
'right': self.visit(node.right)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
def visit_UnaryOp(self, node):
|
|
39
|
+
"""Visit UnaryOp nodes."""
|
|
40
|
+
return {
|
|
41
|
+
'class_name': 'UnaryOp',
|
|
42
|
+
'op': node.op,
|
|
43
|
+
'operand': self.visit(node.operand)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
def visit_VarID(self, node):
|
|
47
|
+
"""Visit VarID nodes with context handling."""
|
|
48
|
+
result = {
|
|
49
|
+
'class_name': 'VarID'
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Helper function to check if a value represents multiple items, ranges, or wildcards
|
|
53
|
+
def is_multi_range_or_wildcard(values):
|
|
54
|
+
if not isinstance(values, list):
|
|
55
|
+
return False
|
|
56
|
+
if len(values) != 1:
|
|
57
|
+
return len(values) > 1 # Multiple values
|
|
58
|
+
# Check if single value contains range syntax or wildcards
|
|
59
|
+
single_val = values[0]
|
|
60
|
+
if isinstance(single_val, str):
|
|
61
|
+
return '-' in single_val or single_val == '*'
|
|
62
|
+
return False
|
|
63
|
+
|
|
64
|
+
# Apply context first, then override with node-specific values
|
|
65
|
+
if self.with_context:
|
|
66
|
+
# Handle simple context fields
|
|
67
|
+
for context_attr in ['table', 'interval', 'default']:
|
|
68
|
+
if hasattr(self.with_context, context_attr):
|
|
69
|
+
context_value = getattr(self.with_context, context_attr)
|
|
70
|
+
# Special handling for interval field
|
|
71
|
+
if context_attr == 'interval':
|
|
72
|
+
if context_value is not None:
|
|
73
|
+
# Context has explicit interval value, use it
|
|
74
|
+
result[context_attr] = context_value
|
|
75
|
+
else:
|
|
76
|
+
# Context interval is None, will be handled by node processing
|
|
77
|
+
pass
|
|
78
|
+
elif context_value is not None:
|
|
79
|
+
# Handle AST objects in context (like Constant)
|
|
80
|
+
if hasattr(context_value, 'toJSON'):
|
|
81
|
+
if context_value.__class__.__name__ == 'Constant':
|
|
82
|
+
context_json = context_value.toJSON()
|
|
83
|
+
result[context_attr] = context_json.get('value', context_value)
|
|
84
|
+
else:
|
|
85
|
+
result[context_attr] = self.visit(context_value)
|
|
86
|
+
else:
|
|
87
|
+
result[context_attr] = context_value
|
|
88
|
+
|
|
89
|
+
# Handle array context fields (rows, cols, sheets) - only convert to scalar if single value and not range
|
|
90
|
+
array_mappings = {'rows': 'row', 'cols': 'column', 'sheets': 'sheet'}
|
|
91
|
+
for context_attr, result_key in array_mappings.items():
|
|
92
|
+
if hasattr(self.with_context, context_attr):
|
|
93
|
+
context_value = getattr(self.with_context, context_attr)
|
|
94
|
+
if context_value is not None:
|
|
95
|
+
# Only create scalar field if it's a single non-range, non-wildcard value
|
|
96
|
+
if isinstance(context_value, list) and len(context_value) == 1 and not is_multi_range_or_wildcard(context_value):
|
|
97
|
+
result[result_key] = context_value[0]
|
|
98
|
+
# For multi-value, range, or wildcard contexts, don't create scalar fields
|
|
99
|
+
# The expected JSON has data field instead (handled by database layer)
|
|
100
|
+
|
|
101
|
+
# Override with node-specific values using same logic
|
|
102
|
+
node_array_mappings = {'rows': 'row', 'cols': 'column', 'sheets': 'sheet'}
|
|
103
|
+
|
|
104
|
+
# Handle simple node fields
|
|
105
|
+
for node_attr in ['table', 'interval', 'default']:
|
|
106
|
+
if hasattr(node, node_attr):
|
|
107
|
+
node_value = getattr(node, node_attr)
|
|
108
|
+
# Special handling for interval field
|
|
109
|
+
if node_attr == 'interval':
|
|
110
|
+
if node_value is not None:
|
|
111
|
+
# Node has explicit interval value, use it
|
|
112
|
+
result[node_attr] = node_value
|
|
113
|
+
elif node_attr not in result:
|
|
114
|
+
# No context value and node value is None, default to False
|
|
115
|
+
result[node_attr] = False
|
|
116
|
+
# If context already set this field, don't override
|
|
117
|
+
elif node_value is not None:
|
|
118
|
+
# Handle AST objects (like Constant)
|
|
119
|
+
if hasattr(node_value, 'toJSON'):
|
|
120
|
+
if node_value.__class__.__name__ == 'Constant':
|
|
121
|
+
node_json = node_value.toJSON()
|
|
122
|
+
result[node_attr] = node_json.get('value', node_value)
|
|
123
|
+
else:
|
|
124
|
+
result[node_attr] = self.visit(node_value)
|
|
125
|
+
else:
|
|
126
|
+
result[node_attr] = node_value
|
|
127
|
+
|
|
128
|
+
# Handle array node fields
|
|
129
|
+
for node_attr, result_key in node_array_mappings.items():
|
|
130
|
+
if hasattr(node, node_attr):
|
|
131
|
+
node_value = getattr(node, node_attr)
|
|
132
|
+
if node_value is not None:
|
|
133
|
+
# Only create scalar field if it's a single non-range, non-wildcard value
|
|
134
|
+
if isinstance(node_value, list) and len(node_value) == 1 and not is_multi_range_or_wildcard(node_value):
|
|
135
|
+
result[result_key] = node_value[0]
|
|
136
|
+
|
|
137
|
+
# Handle data field if present (contains datapoint and operand_reference_id)
|
|
138
|
+
if hasattr(node, 'data') and node.data is not None:
|
|
139
|
+
# Convert pandas DataFrame to list of dictionaries
|
|
140
|
+
if hasattr(node.data, 'to_dict'):
|
|
141
|
+
data_records = node.data.to_dict('records')
|
|
142
|
+
# Transform the data to match expected JSON structure
|
|
143
|
+
transformed_data = []
|
|
144
|
+
for record in data_records:
|
|
145
|
+
# Map database columns to expected JSON fields
|
|
146
|
+
transformed_record = {}
|
|
147
|
+
if 'variable_id' in record:
|
|
148
|
+
transformed_record['datapoint'] = record['variable_id']
|
|
149
|
+
if 'cell_id' in record:
|
|
150
|
+
transformed_record['operand_reference_id'] = record['cell_id']
|
|
151
|
+
# Include additional fields if they exist
|
|
152
|
+
for field in ['cell_code', 'table_code', 'row_code', 'column_code', 'sheet_code', 'data_type', 'table_vid']:
|
|
153
|
+
if field in record:
|
|
154
|
+
transformed_record[field] = record[field]
|
|
155
|
+
transformed_data.append(transformed_record)
|
|
156
|
+
result['data'] = transformed_data
|
|
157
|
+
else:
|
|
158
|
+
# Handle other data formats if needed
|
|
159
|
+
result['data'] = node.data
|
|
160
|
+
|
|
161
|
+
# Filter out None values and internal fields
|
|
162
|
+
filtered_result = {k: v for k, v in result.items() if v is not None}
|
|
163
|
+
return filtered_result
|
|
164
|
+
|
|
165
|
+
def visit_AggregationOp(self, node):
|
|
166
|
+
"""Visit AggregationOp nodes."""
|
|
167
|
+
return {
|
|
168
|
+
'class_name': 'AggregationOp',
|
|
169
|
+
'op': node.op,
|
|
170
|
+
'operand': self.visit(node.operand)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
def visit_Constant(self, node):
|
|
174
|
+
"""Visit Constant nodes."""
|
|
175
|
+
return {
|
|
176
|
+
'class_name': 'Constant',
|
|
177
|
+
'type_': getattr(node, 'type_', getattr(node, 'type', None)),
|
|
178
|
+
'value': node.value
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
def visit_ParExpr(self, node):
|
|
182
|
+
"""Visit ParExpr nodes."""
|
|
183
|
+
return {
|
|
184
|
+
'class_name': 'ParExpr',
|
|
185
|
+
'expression': self.visit(node.expression)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
def visit_ConditionalOp(self, node):
|
|
189
|
+
"""Visit ConditionalOp nodes."""
|
|
190
|
+
result = {
|
|
191
|
+
'class_name': 'ConditionalOp',
|
|
192
|
+
'condition': self.visit(node.condition),
|
|
193
|
+
'then_expr': self.visit(node.then_expr)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if hasattr(node, 'else_expr') and node.else_expr is not None:
|
|
197
|
+
result['else_expr'] = self.visit(node.else_expr)
|
|
198
|
+
|
|
199
|
+
return result
|
|
200
|
+
|
|
201
|
+
def visit_Function(self, node):
|
|
202
|
+
"""Visit Function nodes."""
|
|
203
|
+
result = {
|
|
204
|
+
'class_name': 'Function',
|
|
205
|
+
'name': node.name
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if hasattr(node, 'args') and node.args:
|
|
209
|
+
result['args'] = [self.visit(arg) for arg in node.args]
|
|
210
|
+
|
|
211
|
+
return result
|
|
212
|
+
|
|
213
|
+
def visit_Scalar(self, node):
|
|
214
|
+
"""Visit Scalar nodes with item name normalization."""
|
|
215
|
+
result = {
|
|
216
|
+
'class_name': 'Scalar'
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
# Apply item name normalization for version compatibility
|
|
220
|
+
if hasattr(node, 'item') and node.item:
|
|
221
|
+
item_name = node.item
|
|
222
|
+
# Handle version differences in scalar naming
|
|
223
|
+
# e.g., eba_qEC -> eba_EC, eba_qLR -> eba_LR
|
|
224
|
+
if isinstance(item_name, str) and item_name.startswith('eba_q'):
|
|
225
|
+
normalized_item = item_name.replace('eba_q', 'eba_')
|
|
226
|
+
result['item'] = normalized_item
|
|
227
|
+
else:
|
|
228
|
+
result['item'] = item_name
|
|
229
|
+
|
|
230
|
+
if hasattr(node, 'member') and node.member:
|
|
231
|
+
result['member'] = node.member
|
|
232
|
+
|
|
233
|
+
return result
|
|
234
|
+
|
|
235
|
+
def generic_visit(self, node):
|
|
236
|
+
"""Generic visit method for nodes without specific visitors."""
|
|
237
|
+
result = {
|
|
238
|
+
'class_name': node.__class__.__name__
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
# Try to get common attributes
|
|
242
|
+
for attr in ['op', 'name', 'value', 'type_', 'item', 'member']:
|
|
243
|
+
if hasattr(node, attr):
|
|
244
|
+
attr_value = getattr(node, attr)
|
|
245
|
+
if attr_value is not None:
|
|
246
|
+
result[attr] = attr_value
|
|
247
|
+
|
|
248
|
+
# Handle child nodes
|
|
249
|
+
for attr in ['left', 'right', 'operand', 'expression', 'condition', 'then_expr', 'else_expr']:
|
|
250
|
+
if hasattr(node, attr):
|
|
251
|
+
attr_value = getattr(node, attr)
|
|
252
|
+
if attr_value is not None:
|
|
253
|
+
result[attr] = self.visit(attr_value)
|
|
254
|
+
|
|
255
|
+
# Handle lists of child nodes
|
|
256
|
+
for attr in ['children', 'args']:
|
|
257
|
+
if hasattr(node, attr):
|
|
258
|
+
attr_value = getattr(node, attr)
|
|
259
|
+
if attr_value and isinstance(attr_value, list):
|
|
260
|
+
result[attr] = [self.visit(child) for child in attr_value]
|
|
261
|
+
|
|
262
|
+
return result
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
# Original serialization functions (kept for backward compatibility)
|
|
266
|
+
import json
|
|
267
|
+
from py_dpm.AST import ASTObjects
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def expand_with_expression(node):
|
|
271
|
+
"""
|
|
272
|
+
Recursively expand WithExpression nodes by merging partial selections into cell references.
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
node: AST node to process
|
|
276
|
+
|
|
277
|
+
Returns:
|
|
278
|
+
Expanded AST node
|
|
279
|
+
"""
|
|
280
|
+
if node is None:
|
|
281
|
+
return None
|
|
282
|
+
|
|
283
|
+
if isinstance(node, list):
|
|
284
|
+
return [expand_with_expression(item) for item in node]
|
|
285
|
+
|
|
286
|
+
if isinstance(node, dict):
|
|
287
|
+
return {key: expand_with_expression(value) for key, value in node.items()}
|
|
288
|
+
|
|
289
|
+
# Handle WithExpression expansion
|
|
290
|
+
if isinstance(node, ASTObjects.WithExpression):
|
|
291
|
+
partial_selection = node.partial_selection
|
|
292
|
+
expression = expand_with_expression(node.expression)
|
|
293
|
+
|
|
294
|
+
# Apply partial selection to all VarID nodes in the expression
|
|
295
|
+
return apply_partial_selection(expression, partial_selection)
|
|
296
|
+
|
|
297
|
+
# Handle Start node - check if it contains WithExpression
|
|
298
|
+
if isinstance(node, ASTObjects.Start):
|
|
299
|
+
expanded_children = []
|
|
300
|
+
for child in node.children:
|
|
301
|
+
if isinstance(child, ASTObjects.WithExpression):
|
|
302
|
+
# Expand the WithExpression and return just the expanded expression
|
|
303
|
+
expanded = expand_with_expression(child)
|
|
304
|
+
expanded_children.append(expanded)
|
|
305
|
+
else:
|
|
306
|
+
expanded_children.append(expand_with_expression(child))
|
|
307
|
+
|
|
308
|
+
# If we have a single expanded child that came from a WithExpression,
|
|
309
|
+
# return the expanded expression directly (no Start wrapper)
|
|
310
|
+
if len(expanded_children) == 1:
|
|
311
|
+
return expanded_children[0]
|
|
312
|
+
else:
|
|
313
|
+
return ASTObjects.Start(children=expanded_children)
|
|
314
|
+
|
|
315
|
+
# For other node types, recursively expand children
|
|
316
|
+
if hasattr(node, '__dict__'):
|
|
317
|
+
expanded_node = type(node).__new__(type(node))
|
|
318
|
+
for attr_name, attr_value in node.__dict__.items():
|
|
319
|
+
setattr(expanded_node, attr_name, expand_with_expression(attr_value))
|
|
320
|
+
return expanded_node
|
|
321
|
+
|
|
322
|
+
return node
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def apply_partial_selection(expression, partial_selection):
|
|
326
|
+
"""
|
|
327
|
+
Apply partial selection to VarID nodes in the expression.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
expression: Expression AST node
|
|
331
|
+
partial_selection: Partial selection VarID node
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
Modified expression with partial selection applied
|
|
335
|
+
"""
|
|
336
|
+
if expression is None:
|
|
337
|
+
return None
|
|
338
|
+
|
|
339
|
+
if isinstance(expression, list):
|
|
340
|
+
return [apply_partial_selection(item, partial_selection) for item in expression]
|
|
341
|
+
|
|
342
|
+
if isinstance(expression, dict):
|
|
343
|
+
return {key: apply_partial_selection(value, partial_selection) for key, value in expression.items()}
|
|
344
|
+
|
|
345
|
+
# Apply partial selection to VarID nodes
|
|
346
|
+
if isinstance(expression, ASTObjects.VarID):
|
|
347
|
+
# Create a new VarID with merged properties
|
|
348
|
+
new_varid = ASTObjects.VarID(
|
|
349
|
+
table=partial_selection.table if expression.table is None else expression.table,
|
|
350
|
+
rows=partial_selection.rows if expression.rows is None else expression.rows,
|
|
351
|
+
cols=expression.cols, # Keep the original cols from the expression
|
|
352
|
+
sheets=partial_selection.sheets if expression.sheets is None else expression.sheets,
|
|
353
|
+
interval=partial_selection.interval if expression.interval is None else expression.interval,
|
|
354
|
+
default=partial_selection.default if expression.default is None else expression.default,
|
|
355
|
+
is_table_group=partial_selection.is_table_group if hasattr(partial_selection, 'is_table_group') else False
|
|
356
|
+
)
|
|
357
|
+
return new_varid
|
|
358
|
+
|
|
359
|
+
# For other node types, recursively apply to children
|
|
360
|
+
if hasattr(expression, '__dict__'):
|
|
361
|
+
modified_expr = type(expression).__new__(type(expression))
|
|
362
|
+
for attr_name, attr_value in expression.__dict__.items():
|
|
363
|
+
setattr(modified_expr, attr_name, apply_partial_selection(attr_value, partial_selection))
|
|
364
|
+
return modified_expr
|
|
365
|
+
|
|
366
|
+
return expression
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def serialize_ast(ast_obj):
|
|
370
|
+
"""
|
|
371
|
+
Serialize an AST object to a JSON-serializable dictionary.
|
|
372
|
+
Expands WithExpression nodes before serialization.
|
|
373
|
+
|
|
374
|
+
Args:
|
|
375
|
+
ast_obj: An AST object instance
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
dict: JSON-serializable dictionary representation
|
|
379
|
+
"""
|
|
380
|
+
if ast_obj is None:
|
|
381
|
+
return None
|
|
382
|
+
|
|
383
|
+
# First expand any WithExpression nodes
|
|
384
|
+
expanded_obj = expand_with_expression(ast_obj)
|
|
385
|
+
|
|
386
|
+
if isinstance(expanded_obj, list):
|
|
387
|
+
return [serialize_ast(item) for item in expanded_obj]
|
|
388
|
+
|
|
389
|
+
if isinstance(expanded_obj, dict):
|
|
390
|
+
return {key: serialize_ast(value) for key, value in expanded_obj.items()}
|
|
391
|
+
|
|
392
|
+
if hasattr(expanded_obj, 'toJSON'):
|
|
393
|
+
serialized = expanded_obj.toJSON()
|
|
394
|
+
# Recursively serialize nested AST objects
|
|
395
|
+
for key, value in serialized.items():
|
|
396
|
+
if key != 'class_name':
|
|
397
|
+
serialized[key] = serialize_ast(value)
|
|
398
|
+
return serialized
|
|
399
|
+
|
|
400
|
+
# For basic types (str, int, float, bool)
|
|
401
|
+
if isinstance(expanded_obj, (str, int, float, bool, type(None))):
|
|
402
|
+
return expanded_obj
|
|
403
|
+
|
|
404
|
+
# Fallback: serialize as dict for objects without toJSON
|
|
405
|
+
return expanded_obj.__dict__
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def deserialize_ast(data):
|
|
409
|
+
"""
|
|
410
|
+
Deserialize a JSON dictionary back to an AST object.
|
|
411
|
+
|
|
412
|
+
Args:
|
|
413
|
+
data: Dictionary or list from JSON
|
|
414
|
+
|
|
415
|
+
Returns:
|
|
416
|
+
AST object instance
|
|
417
|
+
"""
|
|
418
|
+
if data is None:
|
|
419
|
+
return None
|
|
420
|
+
|
|
421
|
+
if isinstance(data, list):
|
|
422
|
+
return [deserialize_ast(item) for item in data]
|
|
423
|
+
|
|
424
|
+
if isinstance(data, dict):
|
|
425
|
+
if 'class_name' in data:
|
|
426
|
+
# This is an AST object
|
|
427
|
+
class_name = data['class_name']
|
|
428
|
+
|
|
429
|
+
# Get the class from ASTObjects module
|
|
430
|
+
if hasattr(ASTObjects, class_name):
|
|
431
|
+
cls = getattr(ASTObjects, class_name)
|
|
432
|
+
|
|
433
|
+
# Create a new instance
|
|
434
|
+
obj = object.__new__(cls)
|
|
435
|
+
|
|
436
|
+
# Initialize the base AST attributes
|
|
437
|
+
obj.num = None
|
|
438
|
+
obj.prev = None
|
|
439
|
+
|
|
440
|
+
# Set all the attributes from the serialized data
|
|
441
|
+
for key, value in data.items():
|
|
442
|
+
if key != 'class_name':
|
|
443
|
+
setattr(obj, key, deserialize_ast(value))
|
|
444
|
+
|
|
445
|
+
return obj
|
|
446
|
+
else:
|
|
447
|
+
raise ValueError(f"Unknown AST class: {class_name}")
|
|
448
|
+
else:
|
|
449
|
+
# Regular dictionary, deserialize values
|
|
450
|
+
return {key: deserialize_ast(value) for key, value in data.items()}
|
|
451
|
+
|
|
452
|
+
# For basic types
|
|
453
|
+
return data
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
def ast_to_json_string(ast_obj, indent=None):
|
|
457
|
+
"""
|
|
458
|
+
Convert AST object to JSON string.
|
|
459
|
+
|
|
460
|
+
Args:
|
|
461
|
+
ast_obj: AST object to serialize
|
|
462
|
+
indent: JSON indentation (optional)
|
|
463
|
+
|
|
464
|
+
Returns:
|
|
465
|
+
str: JSON string representation
|
|
466
|
+
"""
|
|
467
|
+
return json.dumps(serialize_ast(ast_obj), indent=indent)
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def ast_from_json_string(json_str):
|
|
471
|
+
"""
|
|
472
|
+
Create AST object from JSON string.
|
|
473
|
+
|
|
474
|
+
Args:
|
|
475
|
+
json_str: JSON string representation
|
|
476
|
+
|
|
477
|
+
Returns:
|
|
478
|
+
AST object instance
|
|
479
|
+
"""
|
|
480
|
+
data = json.loads(json_str)
|
|
481
|
+
return deserialize_ast(data)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
CREATE
|
|
2
|
+
OR ALTER
|
|
3
|
+
VIEW data_types AS
|
|
4
|
+
SELECT vv.VariableID as datapoint,
|
|
5
|
+
dt.Code as data_type,
|
|
6
|
+
vv.StartReleaseID as start_release,
|
|
7
|
+
vv.EndReleaseID as end_release
|
|
8
|
+
from VariableVersion vv
|
|
9
|
+
inner join Property p on
|
|
10
|
+
p.PropertyID = vv.PropertyID
|
|
11
|
+
inner join DataType dt on
|
|
12
|
+
dt.DataTypeID = p.DataTypeID
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
CREATE OR ALTER VIEW datapoints AS
|
|
2
|
+
SELECT distinct tvc.CellCode AS cell_code,
|
|
3
|
+
tv.Code AS table_code,
|
|
4
|
+
hvr.Code AS row_code,
|
|
5
|
+
hvc.Code AS column_code,
|
|
6
|
+
hvs.Code AS sheet_code,
|
|
7
|
+
vv.VariableID AS variable_id,
|
|
8
|
+
dt.Code AS data_type,
|
|
9
|
+
tv.TableVID AS table_vid,
|
|
10
|
+
|
|
11
|
+
p.PropertyID AS property_id,
|
|
12
|
+
mv.StartReleaseID AS start_release,
|
|
13
|
+
mv.EndReleaseID AS end_release,
|
|
14
|
+
tvc.CellID AS cell_id,
|
|
15
|
+
vv.ContextID AS context_id,
|
|
16
|
+
vv.VariableVID AS variable_vid
|
|
17
|
+
|
|
18
|
+
FROM dbo.TableVersionCell AS tvc
|
|
19
|
+
|
|
20
|
+
INNER JOIN dbo.TableVersion AS tv
|
|
21
|
+
ON tvc.TableVID = tv.TableVID AND tvc.IsVoid = 0
|
|
22
|
+
INNER JOIN dbo.ModuleVersionComposition mvc on tv.TableVID = mvc.TableVID
|
|
23
|
+
inner join dbo.ModuleVersion mv on mvc.ModuleVID = mv.ModuleVID
|
|
24
|
+
|
|
25
|
+
LEFT OUTER JOIN dbo.VariableVersion AS vv
|
|
26
|
+
ON tvc.VariableVID = vv.VariableVID
|
|
27
|
+
|
|
28
|
+
LEFT OUTER JOIN dbo.Property AS p ON vv.PropertyID = p.PropertyID
|
|
29
|
+
|
|
30
|
+
LEFT OUTER JOIN dbo.DataType AS dt ON p.DataTypeID = dt.DataTypeID
|
|
31
|
+
|
|
32
|
+
INNER JOIN dbo.Cell AS c ON tvc.CellID = c.CellID
|
|
33
|
+
|
|
34
|
+
LEFT OUTER JOIN
|
|
35
|
+
|
|
36
|
+
(SELECT hv.HeaderVID, hv.HeaderID, hv.Code, hv.EndReleaseID, tvh.TableVID
|
|
37
|
+
|
|
38
|
+
FROM HeaderVersion hv
|
|
39
|
+
|
|
40
|
+
INNER JOIN TableVersionHeader tvh
|
|
41
|
+
ON tvh.HeaderVID = hv.HeaderVID) hvr
|
|
42
|
+
ON hvr.HeaderID = c.RowID AND hvr.EndReleaseID IS NULL AND
|
|
43
|
+
tv.TableVID = hvr.TableVID
|
|
44
|
+
|
|
45
|
+
LEFT OUTER JOIN
|
|
46
|
+
|
|
47
|
+
(SELECT hv.HeaderVID, hv.HeaderID, hv.Code, hv.EndReleaseID, tvh.TableVID
|
|
48
|
+
|
|
49
|
+
FROM HeaderVersion hv
|
|
50
|
+
|
|
51
|
+
INNER JOIN TableVersionHeader tvh
|
|
52
|
+
ON tvh.HeaderVID = hv.HeaderVID) hvc
|
|
53
|
+
ON hvc.HeaderID = c.ColumnID AND hvc.EndReleaseID IS NULL AND
|
|
54
|
+
tv.TableVID = hvc.TableVID
|
|
55
|
+
|
|
56
|
+
LEFT OUTER JOIN
|
|
57
|
+
|
|
58
|
+
(SELECT hv.HeaderVID, hv.HeaderID, hv.Code, hv.EndReleaseID, tvh.TableVID
|
|
59
|
+
|
|
60
|
+
FROM HeaderVersion hv
|
|
61
|
+
|
|
62
|
+
INNER JOIN TableVersionHeader tvh
|
|
63
|
+
ON tvh.HeaderVID = hv.HeaderVID) hvs
|
|
64
|
+
ON hvs.HeaderID = c.SheetID AND hvs.EndReleaseID IS NULL AND
|
|
65
|
+
tv.TableVID = hvs.TableVID
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
CREATE OR ALTER VIEW hierarchy_operand_reference_info AS
|
|
2
|
+
select distinct o.code as operation_code,
|
|
3
|
+
on2.NodeID as operation_node_id,
|
|
4
|
+
orl.CellID as cell_id,
|
|
5
|
+
or2.VariableID as variable_id
|
|
6
|
+
FROM OperandReferenceLocation orl
|
|
7
|
+
inner join OperandReference or2 on orl.OperandReferenceID = or2.OperandReferenceID
|
|
8
|
+
inner join OperationNode on2 on on2.NodeID = or2.NodeID
|
|
9
|
+
inner join OperationVersion ov on ov.OperationVID = on2.OperationVID
|
|
10
|
+
inner join Operation o on o.OperationID = ov.OperationID
|
|
11
|
+
WHERE o.[Source] = 'hierarchy';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
CREATE OR ALTER VIEW hierarchy_preconditions
|
|
2
|
+
AS
|
|
3
|
+
SELECT ov.Expression as expression,
|
|
4
|
+
o.Code as operation_code,
|
|
5
|
+
VV.Code as variable_code
|
|
6
|
+
FROM Operation o
|
|
7
|
+
inner join OperationVersion ov on o.OperationID = ov.OperationID
|
|
8
|
+
inner join dbo.OperationNode N on ov.OperationVID = N.OperationVID
|
|
9
|
+
inner join dbo.OperandReference OR2 on N.NodeID = OR2.NodeID
|
|
10
|
+
inner join dbo.Variable V on OR2.VariableID = V.VariableID
|
|
11
|
+
inner join dbo.VariableVersion VV on V.VariableID = VV.VariableID
|
|
12
|
+
where o.Code like 'p_%'
|
|
13
|
+
and Expression not like '%or%';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
CREATE OR ALTER VIEW hierarchy_variables AS
|
|
2
|
+
SELECT scv.SubCategoryID as subcategory_id,
|
|
3
|
+
vv.VariableVID as variable_vid,
|
|
4
|
+
tvc.CellCode as cell_code,
|
|
5
|
+
mp.Code as main_property_code,
|
|
6
|
+
cp.Code as context_property_code,
|
|
7
|
+
i.Code as item_code,
|
|
8
|
+
mv.StartReleaseID as start_release_id,
|
|
9
|
+
mv.EndReleaseID as end_release_id
|
|
10
|
+
FROM SubCategoryVersion scv
|
|
11
|
+
inner join SubCategoryItem sci
|
|
12
|
+
on sci.SubCategoryVID = scv.SubCategoryVID
|
|
13
|
+
inner join ContextComposition cc on cc.ItemID = sci.ItemID
|
|
14
|
+
inner join VariableVersion vv on vv.ContextID = cc.ContextID
|
|
15
|
+
inner join TableVersionCell tvc on vv.VariableVID = tvc.VariableVID
|
|
16
|
+
inner join Property p on vv.PropertyID = p.PropertyID
|
|
17
|
+
inner join DataType dt on p.DataTypeID = dt.DataTypeID
|
|
18
|
+
left join ItemCategory mp on mp.ItemID = vv.PropertyID and mp.EndReleaseID is Null
|
|
19
|
+
left join ItemCategory cp on cp.ItemID = cc.PropertyID and cp.EndReleaseID is Null
|
|
20
|
+
left join ItemCategory i on i.ItemID = cc.ItemID and i.EndReleaseID is Null
|
|
21
|
+
inner join TableVersion tv on tv.TableVID = tvc.TableVID
|
|
22
|
+
inner join ModuleVersionComposition mvc on tv.TableVID = mvc.TableVID
|
|
23
|
+
inner join ModuleVersion mv on mvc.ModuleVID = mv.ModuleVID
|
|
24
|
+
|
|
25
|
+
where dt.Code in ('m', 'i', 'r')
|
|
26
|
+
and tvc.CellCode is not Null
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
CREATE or ALTER VIEW hierarchy_variables_context as
|
|
2
|
+
SELECT distinct vv.VariableVID as variable_vid,
|
|
3
|
+
cp.Code as context_property_code,
|
|
4
|
+
i.Code as item_code,
|
|
5
|
+
mv.StartReleaseID as start_release_id,
|
|
6
|
+
mv.EndReleaseID as end_release_id
|
|
7
|
+
FROM VariableVersion vv
|
|
8
|
+
inner join ContextComposition cc on cc.ContextID = vv.ContextID
|
|
9
|
+
inner join ItemCategory cp on cp.ItemID = cc.PropertyID and cp.EndReleaseID is Null
|
|
10
|
+
inner join ItemCategory i on i.ItemID = cc.ItemID and i.EndReleaseID is Null
|
|
11
|
+
inner join TableVersionCell tvc on vv.VariableVID = tvc.VariableVID
|
|
12
|
+
inner join TableVersion tv on tvc.TableVID = tv.TableVID
|
|
13
|
+
inner join ModuleVersionComposition mvc on tv.TableVID = mvc.TableVID
|
|
14
|
+
inner join ModuleVersion mv on mvc.ModuleVID = mv.ModuleVID;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
CREATE OR ALTER VIEW key_components AS
|
|
2
|
+
select tv.Code as table_code,
|
|
3
|
+
ic.Code as property_code,
|
|
4
|
+
dt.Code as data_type,
|
|
5
|
+
tv.TableVID as table_version_id,
|
|
6
|
+
ic.StartReleaseID as start_release_ic,
|
|
7
|
+
ic.EndReleaseID as end_release_ic,
|
|
8
|
+
mv.StartReleaseID as start_release_mv,
|
|
9
|
+
mv.EndReleaseID as end_release_mv
|
|
10
|
+
from [dbo].TableVersion tv
|
|
11
|
+
inner join [dbo].KeyComposition kc on tv.KeyID = kc.KeyID
|
|
12
|
+
inner join [dbo].VariableVersion vv on vv.VariableVID = kc.VariableVID
|
|
13
|
+
inner join [dbo].Item i on vv.PropertyID = i.ItemID
|
|
14
|
+
inner join [dbo].ItemCategory ic on ic.ItemID = i.ItemID
|
|
15
|
+
inner join [dbo].Property p on vv.PropertyID = p.PropertyID
|
|
16
|
+
left join [dbo].DataType dt on p.DataTypeID = dt.DataTypeID
|
|
17
|
+
inner join [dbo].ModuleVersionComposition mvc on tv.TableVID = mvc.TableVID
|
|
18
|
+
inner join [dbo].ModuleVersion mv on mvc.ModuleVID = mv.ModuleVID;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
CREATE OR ALTER VIEW module_from_table AS
|
|
2
|
+
SELECT MV.Code as module_code,
|
|
3
|
+
TV.Code as table_code,
|
|
4
|
+
MV.FromReferenceDate as from_date,
|
|
5
|
+
MV.ToReferenceDate as to_date
|
|
6
|
+
from Module m
|
|
7
|
+
inner join ModuleVersion MV on m.ModuleID = MV.ModuleID
|
|
8
|
+
inner join ModuleVersionComposition MVC
|
|
9
|
+
on MV.ModuleVID = MVC.ModuleVID
|
|
10
|
+
inner join TableVersion TV on MVC.TableVID = TV.TableVID
|
|
11
|
+
where TV.Code is not null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
CREATE
|
|
2
|
+
OR ALTER
|
|
3
|
+
VIEW open_keys AS
|
|
4
|
+
select ic.Code as property_code,
|
|
5
|
+
dt.Code as data_type,
|
|
6
|
+
ic.StartReleaseID as start_release,
|
|
7
|
+
ic.EndReleaseID as end_release
|
|
8
|
+
from [dbo].KeyComposition kc
|
|
9
|
+
inner join [dbo].VariableVersion vv on vv.VariableVID = kc.VariableVID
|
|
10
|
+
inner join [dbo].Item i on vv.PropertyID = i.ItemID
|
|
11
|
+
inner join [dbo].ItemCategory ic on ic.ItemID = i.ItemID
|
|
12
|
+
inner join [dbo].Property p on vv.PropertyID = p.PropertyID
|
|
13
|
+
left join [dbo].DataType dt on p.DataTypeID = dt.DataTypeID;
|