relationalai 0.13.5__py3-none-any.whl → 1.0.0a2__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.
- relationalai/__init__.py +1 -256
- relationalai/config/__init__.py +56 -0
- relationalai/config/config.py +289 -0
- relationalai/config/config_fields.py +86 -0
- relationalai/config/connections/__init__.py +46 -0
- relationalai/config/connections/base.py +23 -0
- relationalai/config/connections/duckdb.py +29 -0
- relationalai/config/connections/snowflake.py +243 -0
- relationalai/config/external/__init__.py +17 -0
- relationalai/config/external/dbt_converter.py +101 -0
- relationalai/config/external/dbt_models.py +93 -0
- relationalai/config/external/snowflake_converter.py +41 -0
- relationalai/config/external/snowflake_models.py +85 -0
- relationalai/config/external/utils.py +19 -0
- relationalai/config/shims.py +1 -0
- relationalai/semantics/__init__.py +146 -22
- relationalai/semantics/backends/lqp/annotations.py +11 -0
- relationalai/semantics/backends/sql/sql_compiler.py +327 -0
- relationalai/semantics/frontend/base.py +1719 -0
- relationalai/semantics/frontend/core.py +179 -0
- relationalai/semantics/frontend/front_compiler.py +1316 -0
- relationalai/semantics/frontend/pprint.py +408 -0
- relationalai/semantics/metamodel/__init__.py +6 -40
- relationalai/semantics/metamodel/builtins.py +206 -772
- relationalai/semantics/metamodel/metamodel.py +465 -0
- relationalai/semantics/metamodel/metamodel_analyzer.py +519 -0
- relationalai/semantics/metamodel/pprint.py +414 -0
- relationalai/semantics/metamodel/rewriter.py +266 -0
- relationalai/semantics/metamodel/typer.py +1213 -0
- relationalai/semantics/std/__init__.py +60 -40
- relationalai/semantics/std/aggregates.py +148 -0
- relationalai/semantics/std/common.py +44 -0
- relationalai/semantics/std/constraints.py +37 -43
- relationalai/semantics/std/datetime.py +249 -135
- relationalai/semantics/std/decimals.py +45 -52
- relationalai/semantics/std/floats.py +13 -5
- relationalai/semantics/std/integers.py +26 -11
- relationalai/semantics/std/math.py +183 -112
- relationalai/semantics/std/numbers.py +86 -0
- relationalai/semantics/std/re.py +80 -62
- relationalai/semantics/std/strings.py +101 -46
- relationalai/shims/executor.py +179 -0
- relationalai/shims/helpers.py +126 -0
- relationalai/shims/hoister.py +221 -0
- relationalai/shims/mm2v0.py +1394 -0
- relationalai/tools/cli/__init__.py +6 -0
- relationalai/tools/cli/cli.py +90 -0
- relationalai/tools/cli/components/__init__.py +5 -0
- relationalai/tools/cli/components/progress_reader.py +1524 -0
- relationalai/tools/cli/components/utils.py +58 -0
- relationalai/tools/cli/config_template.py +45 -0
- relationalai/tools/cli/dev.py +19 -0
- relationalai/tools/debugger.py +289 -183
- relationalai/tools/typer_debugger.py +93 -0
- relationalai/util/dataclasses.py +43 -0
- relationalai/util/docutils.py +40 -0
- relationalai/util/error.py +199 -0
- relationalai/util/format.py +48 -109
- relationalai/util/naming.py +145 -0
- relationalai/util/python.py +35 -0
- relationalai/util/runtime.py +156 -0
- relationalai/util/schema.py +197 -0
- relationalai/util/source.py +185 -0
- relationalai/util/structures.py +163 -0
- relationalai/util/tracing.py +261 -0
- relationalai-1.0.0a2.dist-info/METADATA +44 -0
- relationalai-1.0.0a2.dist-info/RECORD +489 -0
- relationalai-1.0.0a2.dist-info/WHEEL +5 -0
- relationalai-1.0.0a2.dist-info/entry_points.txt +3 -0
- relationalai-1.0.0a2.dist-info/top_level.txt +2 -0
- v0/relationalai/__init__.py +216 -0
- v0/relationalai/clients/__init__.py +5 -0
- v0/relationalai/clients/azure.py +477 -0
- v0/relationalai/clients/client.py +912 -0
- v0/relationalai/clients/config.py +673 -0
- v0/relationalai/clients/direct_access_client.py +118 -0
- v0/relationalai/clients/hash_util.py +31 -0
- v0/relationalai/clients/local.py +571 -0
- v0/relationalai/clients/profile_polling.py +73 -0
- v0/relationalai/clients/result_helpers.py +420 -0
- v0/relationalai/clients/snowflake.py +3869 -0
- v0/relationalai/clients/types.py +113 -0
- v0/relationalai/clients/use_index_poller.py +980 -0
- v0/relationalai/clients/util.py +356 -0
- v0/relationalai/debugging.py +389 -0
- v0/relationalai/dsl.py +1749 -0
- v0/relationalai/early_access/builder/__init__.py +30 -0
- v0/relationalai/early_access/builder/builder/__init__.py +35 -0
- v0/relationalai/early_access/builder/snowflake/__init__.py +12 -0
- v0/relationalai/early_access/builder/std/__init__.py +25 -0
- v0/relationalai/early_access/builder/std/decimals/__init__.py +12 -0
- v0/relationalai/early_access/builder/std/integers/__init__.py +12 -0
- v0/relationalai/early_access/builder/std/math/__init__.py +12 -0
- v0/relationalai/early_access/builder/std/strings/__init__.py +14 -0
- v0/relationalai/early_access/devtools/__init__.py +12 -0
- v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
- v0/relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
- v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
- v0/relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
- v0/relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
- v0/relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
- v0/relationalai/early_access/dsl/bindings/common.py +402 -0
- v0/relationalai/early_access/dsl/bindings/csv.py +170 -0
- v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
- v0/relationalai/early_access/dsl/bindings/snowflake.py +64 -0
- v0/relationalai/early_access/dsl/codegen/binder.py +411 -0
- v0/relationalai/early_access/dsl/codegen/common.py +79 -0
- v0/relationalai/early_access/dsl/codegen/helpers.py +23 -0
- v0/relationalai/early_access/dsl/codegen/relations.py +700 -0
- v0/relationalai/early_access/dsl/codegen/weaver.py +417 -0
- v0/relationalai/early_access/dsl/core/builders/__init__.py +47 -0
- v0/relationalai/early_access/dsl/core/builders/logic.py +19 -0
- v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
- v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
- v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
- v0/relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
- v0/relationalai/early_access/dsl/core/context.py +13 -0
- v0/relationalai/early_access/dsl/core/cset.py +132 -0
- v0/relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
- v0/relationalai/early_access/dsl/core/exprs/relational.py +18 -0
- v0/relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
- v0/relationalai/early_access/dsl/core/instances.py +44 -0
- v0/relationalai/early_access/dsl/core/logic/__init__.py +193 -0
- v0/relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
- v0/relationalai/early_access/dsl/core/logic/exists.py +223 -0
- v0/relationalai/early_access/dsl/core/logic/helper.py +163 -0
- v0/relationalai/early_access/dsl/core/namespaces.py +32 -0
- v0/relationalai/early_access/dsl/core/relations.py +276 -0
- v0/relationalai/early_access/dsl/core/rules.py +112 -0
- v0/relationalai/early_access/dsl/core/std/__init__.py +45 -0
- v0/relationalai/early_access/dsl/core/temporal/recall.py +6 -0
- v0/relationalai/early_access/dsl/core/types/__init__.py +270 -0
- v0/relationalai/early_access/dsl/core/types/concepts.py +128 -0
- v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
- v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
- v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
- v0/relationalai/early_access/dsl/core/types/standard.py +92 -0
- v0/relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
- v0/relationalai/early_access/dsl/core/types/variables.py +203 -0
- v0/relationalai/early_access/dsl/ir/compiler.py +318 -0
- v0/relationalai/early_access/dsl/ir/executor.py +260 -0
- v0/relationalai/early_access/dsl/ontologies/constraints.py +88 -0
- v0/relationalai/early_access/dsl/ontologies/export.py +30 -0
- v0/relationalai/early_access/dsl/ontologies/models.py +453 -0
- v0/relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
- v0/relationalai/early_access/dsl/ontologies/readings.py +60 -0
- v0/relationalai/early_access/dsl/ontologies/relationships.py +322 -0
- v0/relationalai/early_access/dsl/ontologies/roles.py +87 -0
- v0/relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
- v0/relationalai/early_access/dsl/orm/constraints.py +438 -0
- v0/relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
- v0/relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
- v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
- v0/relationalai/early_access/dsl/orm/measures/measures.py +299 -0
- v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
- v0/relationalai/early_access/dsl/orm/models.py +256 -0
- v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
- v0/relationalai/early_access/dsl/orm/printer.py +469 -0
- v0/relationalai/early_access/dsl/orm/reasoners.py +480 -0
- v0/relationalai/early_access/dsl/orm/relations.py +19 -0
- v0/relationalai/early_access/dsl/orm/relationships.py +251 -0
- v0/relationalai/early_access/dsl/orm/types.py +42 -0
- v0/relationalai/early_access/dsl/orm/utils.py +79 -0
- v0/relationalai/early_access/dsl/orm/verb.py +204 -0
- v0/relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
- v0/relationalai/early_access/dsl/relations.py +170 -0
- v0/relationalai/early_access/dsl/rulesets.py +69 -0
- v0/relationalai/early_access/dsl/schemas/__init__.py +450 -0
- v0/relationalai/early_access/dsl/schemas/builder.py +48 -0
- v0/relationalai/early_access/dsl/schemas/comp_names.py +51 -0
- v0/relationalai/early_access/dsl/schemas/components.py +203 -0
- v0/relationalai/early_access/dsl/schemas/contexts.py +156 -0
- v0/relationalai/early_access/dsl/schemas/exprs.py +89 -0
- v0/relationalai/early_access/dsl/schemas/fragments.py +464 -0
- v0/relationalai/early_access/dsl/serialization.py +79 -0
- v0/relationalai/early_access/dsl/serialize/exporter.py +163 -0
- v0/relationalai/early_access/dsl/snow/api.py +104 -0
- v0/relationalai/early_access/dsl/snow/common.py +76 -0
- v0/relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
- v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
- v0/relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
- v0/relationalai/early_access/dsl/types/__init__.py +40 -0
- v0/relationalai/early_access/dsl/types/concepts.py +12 -0
- v0/relationalai/early_access/dsl/types/entities.py +135 -0
- v0/relationalai/early_access/dsl/types/values.py +17 -0
- v0/relationalai/early_access/dsl/utils.py +102 -0
- v0/relationalai/early_access/graphs/__init__.py +13 -0
- v0/relationalai/early_access/lqp/__init__.py +12 -0
- v0/relationalai/early_access/lqp/compiler/__init__.py +12 -0
- v0/relationalai/early_access/lqp/constructors/__init__.py +18 -0
- v0/relationalai/early_access/lqp/executor/__init__.py +12 -0
- v0/relationalai/early_access/lqp/ir/__init__.py +12 -0
- v0/relationalai/early_access/lqp/passes/__init__.py +12 -0
- v0/relationalai/early_access/lqp/pragmas/__init__.py +12 -0
- v0/relationalai/early_access/lqp/primitives/__init__.py +12 -0
- v0/relationalai/early_access/lqp/types/__init__.py +12 -0
- v0/relationalai/early_access/lqp/utils/__init__.py +12 -0
- v0/relationalai/early_access/lqp/validators/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/__init__.py +58 -0
- v0/relationalai/early_access/metamodel/builtins/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/compiler/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/dependency/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/factory/__init__.py +17 -0
- v0/relationalai/early_access/metamodel/helpers/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/ir/__init__.py +14 -0
- v0/relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
- v0/relationalai/early_access/metamodel/typer/__init__.py +3 -0
- v0/relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/types/__init__.py +15 -0
- v0/relationalai/early_access/metamodel/util/__init__.py +15 -0
- v0/relationalai/early_access/metamodel/visitor/__init__.py +12 -0
- v0/relationalai/early_access/rel/__init__.py +12 -0
- v0/relationalai/early_access/rel/executor/__init__.py +12 -0
- v0/relationalai/early_access/rel/rel_utils/__init__.py +12 -0
- v0/relationalai/early_access/rel/rewrite/__init__.py +7 -0
- v0/relationalai/early_access/solvers/__init__.py +19 -0
- v0/relationalai/early_access/sql/__init__.py +11 -0
- v0/relationalai/early_access/sql/executor/__init__.py +3 -0
- v0/relationalai/early_access/sql/rewrite/__init__.py +3 -0
- v0/relationalai/early_access/tests/logging/__init__.py +12 -0
- v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
- v0/relationalai/early_access/tests/utils/__init__.py +12 -0
- v0/relationalai/environments/__init__.py +35 -0
- v0/relationalai/environments/base.py +381 -0
- v0/relationalai/environments/colab.py +14 -0
- v0/relationalai/environments/generic.py +71 -0
- v0/relationalai/environments/ipython.py +68 -0
- v0/relationalai/environments/jupyter.py +9 -0
- v0/relationalai/environments/snowbook.py +169 -0
- v0/relationalai/errors.py +2478 -0
- v0/relationalai/experimental/SF.py +38 -0
- v0/relationalai/experimental/inspect.py +47 -0
- v0/relationalai/experimental/pathfinder/__init__.py +158 -0
- v0/relationalai/experimental/pathfinder/api.py +160 -0
- v0/relationalai/experimental/pathfinder/automaton.py +584 -0
- v0/relationalai/experimental/pathfinder/bridge.py +226 -0
- v0/relationalai/experimental/pathfinder/compiler.py +416 -0
- v0/relationalai/experimental/pathfinder/datalog.py +214 -0
- v0/relationalai/experimental/pathfinder/diagnostics.py +56 -0
- v0/relationalai/experimental/pathfinder/filter.py +236 -0
- v0/relationalai/experimental/pathfinder/glushkov.py +439 -0
- v0/relationalai/experimental/pathfinder/options.py +265 -0
- v0/relationalai/experimental/pathfinder/rpq.py +344 -0
- v0/relationalai/experimental/pathfinder/transition.py +200 -0
- v0/relationalai/experimental/pathfinder/utils.py +26 -0
- v0/relationalai/experimental/paths/api.py +143 -0
- v0/relationalai/experimental/paths/benchmarks/grid_graph.py +37 -0
- v0/relationalai/experimental/paths/examples/basic_example.py +40 -0
- v0/relationalai/experimental/paths/examples/minimal_engine_warmup.py +3 -0
- v0/relationalai/experimental/paths/examples/movie_example.py +77 -0
- v0/relationalai/experimental/paths/examples/paths_benchmark.py +115 -0
- v0/relationalai/experimental/paths/examples/paths_example.py +116 -0
- v0/relationalai/experimental/paths/examples/pattern_to_automaton.py +28 -0
- v0/relationalai/experimental/paths/find_paths_via_automaton.py +85 -0
- v0/relationalai/experimental/paths/graph.py +185 -0
- v0/relationalai/experimental/paths/path_algorithms/find_paths.py +280 -0
- v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +26 -0
- v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +111 -0
- v0/relationalai/experimental/paths/path_algorithms/single.py +59 -0
- v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +39 -0
- v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +103 -0
- v0/relationalai/experimental/paths/path_algorithms/usp-old.py +130 -0
- v0/relationalai/experimental/paths/path_algorithms/usp-tuple.py +183 -0
- v0/relationalai/experimental/paths/path_algorithms/usp.py +150 -0
- v0/relationalai/experimental/paths/product_graph.py +93 -0
- v0/relationalai/experimental/paths/rpq/automaton.py +584 -0
- v0/relationalai/experimental/paths/rpq/diagnostics.py +56 -0
- v0/relationalai/experimental/paths/rpq/rpq.py +378 -0
- v0/relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +90 -0
- v0/relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +119 -0
- v0/relationalai/experimental/paths/tests/tests_limit_sp_single.py +104 -0
- v0/relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +113 -0
- v0/relationalai/experimental/paths/tests/tests_limit_walks_single.py +149 -0
- v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +70 -0
- v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +64 -0
- v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +115 -0
- v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +75 -0
- v0/relationalai/experimental/paths/tests/tests_single_paths.py +152 -0
- v0/relationalai/experimental/paths/tests/tests_single_walks.py +208 -0
- v0/relationalai/experimental/paths/tests/tests_single_walks_undirected.py +297 -0
- v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +107 -0
- v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +76 -0
- v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +76 -0
- v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +110 -0
- v0/relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +229 -0
- v0/relationalai/experimental/paths/tests/tests_usp_nsp_single.py +108 -0
- v0/relationalai/experimental/paths/tree_agg.py +168 -0
- v0/relationalai/experimental/paths/utilities/iterators.py +27 -0
- v0/relationalai/experimental/paths/utilities/prefix_sum.py +91 -0
- v0/relationalai/experimental/solvers.py +1087 -0
- v0/relationalai/loaders/csv.py +195 -0
- v0/relationalai/loaders/loader.py +177 -0
- v0/relationalai/loaders/types.py +23 -0
- v0/relationalai/rel_emitter.py +373 -0
- v0/relationalai/rel_utils.py +185 -0
- v0/relationalai/semantics/__init__.py +29 -0
- v0/relationalai/semantics/devtools/benchmark_lqp.py +536 -0
- v0/relationalai/semantics/devtools/compilation_manager.py +294 -0
- v0/relationalai/semantics/devtools/extract_lqp.py +110 -0
- v0/relationalai/semantics/internal/internal.py +3785 -0
- v0/relationalai/semantics/internal/snowflake.py +325 -0
- v0/relationalai/semantics/lqp/builtins.py +16 -0
- v0/relationalai/semantics/lqp/compiler.py +22 -0
- v0/relationalai/semantics/lqp/constructors.py +68 -0
- v0/relationalai/semantics/lqp/executor.py +474 -0
- v0/relationalai/semantics/lqp/intrinsics.py +24 -0
- v0/relationalai/semantics/lqp/ir.py +124 -0
- v0/relationalai/semantics/lqp/model2lqp.py +877 -0
- v0/relationalai/semantics/lqp/passes.py +680 -0
- v0/relationalai/semantics/lqp/primitives.py +252 -0
- v0/relationalai/semantics/lqp/result_helpers.py +202 -0
- v0/relationalai/semantics/lqp/rewrite/__init__.py +18 -0
- v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
- v0/relationalai/semantics/lqp/rewrite/cdc.py +216 -0
- v0/relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
- v0/relationalai/semantics/lqp/rewrite/extract_keys.py +490 -0
- v0/relationalai/semantics/lqp/rewrite/function_annotations.py +114 -0
- v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py +314 -0
- v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +296 -0
- v0/relationalai/semantics/lqp/rewrite/splinter.py +76 -0
- v0/relationalai/semantics/lqp/types.py +101 -0
- v0/relationalai/semantics/lqp/utils.py +160 -0
- v0/relationalai/semantics/lqp/validators.py +57 -0
- v0/relationalai/semantics/metamodel/__init__.py +40 -0
- v0/relationalai/semantics/metamodel/builtins.py +776 -0
- v0/relationalai/semantics/metamodel/compiler.py +133 -0
- v0/relationalai/semantics/metamodel/dependency.py +862 -0
- v0/relationalai/semantics/metamodel/executor.py +61 -0
- v0/relationalai/semantics/metamodel/factory.py +287 -0
- v0/relationalai/semantics/metamodel/helpers.py +361 -0
- v0/relationalai/semantics/metamodel/ir.py +923 -0
- v0/relationalai/semantics/metamodel/rewrite/__init__.py +7 -0
- v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
- v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
- v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
- v0/relationalai/semantics/metamodel/rewrite/flatten.py +554 -0
- v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +165 -0
- v0/relationalai/semantics/metamodel/typer/checker.py +353 -0
- v0/relationalai/semantics/metamodel/typer/typer.py +1395 -0
- v0/relationalai/semantics/metamodel/util.py +505 -0
- v0/relationalai/semantics/metamodel/visitor.py +944 -0
- v0/relationalai/semantics/reasoners/__init__.py +10 -0
- v0/relationalai/semantics/reasoners/graph/__init__.py +37 -0
- v0/relationalai/semantics/reasoners/graph/core.py +9019 -0
- v0/relationalai/semantics/reasoners/optimization/__init__.py +68 -0
- v0/relationalai/semantics/reasoners/optimization/common.py +88 -0
- v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +568 -0
- v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +1163 -0
- v0/relationalai/semantics/rel/builtins.py +40 -0
- v0/relationalai/semantics/rel/compiler.py +989 -0
- v0/relationalai/semantics/rel/executor.py +359 -0
- v0/relationalai/semantics/rel/rel.py +482 -0
- v0/relationalai/semantics/rel/rel_utils.py +276 -0
- v0/relationalai/semantics/snowflake/__init__.py +3 -0
- v0/relationalai/semantics/sql/compiler.py +2503 -0
- v0/relationalai/semantics/sql/executor/duck_db.py +52 -0
- v0/relationalai/semantics/sql/executor/result_helpers.py +64 -0
- v0/relationalai/semantics/sql/executor/snowflake.py +145 -0
- v0/relationalai/semantics/sql/rewrite/denormalize.py +222 -0
- v0/relationalai/semantics/sql/rewrite/double_negation.py +49 -0
- v0/relationalai/semantics/sql/rewrite/recursive_union.py +127 -0
- v0/relationalai/semantics/sql/rewrite/sort_output_query.py +246 -0
- v0/relationalai/semantics/sql/sql.py +504 -0
- v0/relationalai/semantics/std/__init__.py +54 -0
- v0/relationalai/semantics/std/constraints.py +43 -0
- v0/relationalai/semantics/std/datetime.py +363 -0
- v0/relationalai/semantics/std/decimals.py +62 -0
- v0/relationalai/semantics/std/floats.py +7 -0
- v0/relationalai/semantics/std/integers.py +22 -0
- v0/relationalai/semantics/std/math.py +141 -0
- v0/relationalai/semantics/std/pragmas.py +11 -0
- v0/relationalai/semantics/std/re.py +83 -0
- v0/relationalai/semantics/std/std.py +14 -0
- v0/relationalai/semantics/std/strings.py +63 -0
- v0/relationalai/semantics/tests/__init__.py +0 -0
- v0/relationalai/semantics/tests/test_snapshot_abstract.py +143 -0
- v0/relationalai/semantics/tests/test_snapshot_base.py +9 -0
- v0/relationalai/semantics/tests/utils.py +46 -0
- v0/relationalai/std/__init__.py +70 -0
- v0/relationalai/tools/__init__.py +0 -0
- v0/relationalai/tools/cli.py +1940 -0
- v0/relationalai/tools/cli_controls.py +1826 -0
- v0/relationalai/tools/cli_helpers.py +390 -0
- v0/relationalai/tools/debugger.py +183 -0
- v0/relationalai/tools/debugger_client.py +109 -0
- v0/relationalai/tools/debugger_server.py +302 -0
- v0/relationalai/tools/dev.py +685 -0
- v0/relationalai/tools/qb_debugger.py +425 -0
- v0/relationalai/util/clean_up_databases.py +95 -0
- v0/relationalai/util/format.py +123 -0
- v0/relationalai/util/list_databases.py +9 -0
- v0/relationalai/util/otel_configuration.py +25 -0
- v0/relationalai/util/otel_handler.py +484 -0
- v0/relationalai/util/snowflake_handler.py +88 -0
- v0/relationalai/util/span_format_test.py +43 -0
- v0/relationalai/util/span_tracker.py +207 -0
- v0/relationalai/util/spans_file_handler.py +72 -0
- v0/relationalai/util/tracing_handler.py +34 -0
- frontend/debugger/dist/.gitignore +0 -2
- frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png +0 -0
- frontend/debugger/dist/assets/index-Cssla-O7.js +0 -208
- frontend/debugger/dist/assets/index-DlHsYx1V.css +0 -9
- frontend/debugger/dist/index.html +0 -17
- relationalai/clients/__init__.py +0 -18
- relationalai/clients/client.py +0 -946
- relationalai/clients/config.py +0 -673
- relationalai/clients/direct_access_client.py +0 -118
- relationalai/clients/exec_txn_poller.py +0 -153
- relationalai/clients/hash_util.py +0 -31
- relationalai/clients/local.py +0 -594
- relationalai/clients/profile_polling.py +0 -73
- relationalai/clients/resources/__init__.py +0 -8
- relationalai/clients/resources/azure/azure.py +0 -502
- relationalai/clients/resources/snowflake/__init__.py +0 -20
- relationalai/clients/resources/snowflake/cli_resources.py +0 -98
- relationalai/clients/resources/snowflake/direct_access_resources.py +0 -739
- relationalai/clients/resources/snowflake/engine_service.py +0 -381
- relationalai/clients/resources/snowflake/engine_state_handlers.py +0 -315
- relationalai/clients/resources/snowflake/error_handlers.py +0 -240
- relationalai/clients/resources/snowflake/export_procedure.py.jinja +0 -249
- relationalai/clients/resources/snowflake/resources_factory.py +0 -99
- relationalai/clients/resources/snowflake/snowflake.py +0 -3193
- relationalai/clients/resources/snowflake/use_index_poller.py +0 -1019
- relationalai/clients/resources/snowflake/use_index_resources.py +0 -188
- relationalai/clients/resources/snowflake/util.py +0 -387
- relationalai/clients/result_helpers.py +0 -420
- relationalai/clients/types.py +0 -118
- relationalai/clients/util.py +0 -356
- relationalai/debugging.py +0 -389
- relationalai/dsl.py +0 -1749
- relationalai/early_access/builder/__init__.py +0 -30
- relationalai/early_access/builder/builder/__init__.py +0 -35
- relationalai/early_access/builder/snowflake/__init__.py +0 -12
- relationalai/early_access/builder/std/__init__.py +0 -25
- relationalai/early_access/builder/std/decimals/__init__.py +0 -12
- relationalai/early_access/builder/std/integers/__init__.py +0 -12
- relationalai/early_access/builder/std/math/__init__.py +0 -12
- relationalai/early_access/builder/std/strings/__init__.py +0 -14
- relationalai/early_access/devtools/__init__.py +0 -12
- relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
- relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
- relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
- relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
- relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
- relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
- relationalai/early_access/dsl/bindings/common.py +0 -402
- relationalai/early_access/dsl/bindings/csv.py +0 -170
- relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
- relationalai/early_access/dsl/bindings/snowflake.py +0 -64
- relationalai/early_access/dsl/codegen/binder.py +0 -411
- relationalai/early_access/dsl/codegen/common.py +0 -79
- relationalai/early_access/dsl/codegen/helpers.py +0 -23
- relationalai/early_access/dsl/codegen/relations.py +0 -700
- relationalai/early_access/dsl/codegen/weaver.py +0 -417
- relationalai/early_access/dsl/core/builders/__init__.py +0 -47
- relationalai/early_access/dsl/core/builders/logic.py +0 -19
- relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
- relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
- relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
- relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
- relationalai/early_access/dsl/core/context.py +0 -13
- relationalai/early_access/dsl/core/cset.py +0 -132
- relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
- relationalai/early_access/dsl/core/exprs/relational.py +0 -18
- relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
- relationalai/early_access/dsl/core/instances.py +0 -44
- relationalai/early_access/dsl/core/logic/__init__.py +0 -193
- relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
- relationalai/early_access/dsl/core/logic/exists.py +0 -223
- relationalai/early_access/dsl/core/logic/helper.py +0 -163
- relationalai/early_access/dsl/core/namespaces.py +0 -32
- relationalai/early_access/dsl/core/relations.py +0 -276
- relationalai/early_access/dsl/core/rules.py +0 -112
- relationalai/early_access/dsl/core/std/__init__.py +0 -45
- relationalai/early_access/dsl/core/temporal/recall.py +0 -6
- relationalai/early_access/dsl/core/types/__init__.py +0 -270
- relationalai/early_access/dsl/core/types/concepts.py +0 -128
- relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
- relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
- relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
- relationalai/early_access/dsl/core/types/standard.py +0 -92
- relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
- relationalai/early_access/dsl/core/types/variables.py +0 -203
- relationalai/early_access/dsl/ir/compiler.py +0 -318
- relationalai/early_access/dsl/ir/executor.py +0 -260
- relationalai/early_access/dsl/ontologies/constraints.py +0 -88
- relationalai/early_access/dsl/ontologies/export.py +0 -30
- relationalai/early_access/dsl/ontologies/models.py +0 -453
- relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
- relationalai/early_access/dsl/ontologies/readings.py +0 -60
- relationalai/early_access/dsl/ontologies/relationships.py +0 -322
- relationalai/early_access/dsl/ontologies/roles.py +0 -87
- relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
- relationalai/early_access/dsl/orm/constraints.py +0 -438
- relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
- relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
- relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
- relationalai/early_access/dsl/orm/measures/measures.py +0 -299
- relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
- relationalai/early_access/dsl/orm/models.py +0 -256
- relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
- relationalai/early_access/dsl/orm/printer.py +0 -469
- relationalai/early_access/dsl/orm/reasoners.py +0 -480
- relationalai/early_access/dsl/orm/relations.py +0 -19
- relationalai/early_access/dsl/orm/relationships.py +0 -251
- relationalai/early_access/dsl/orm/types.py +0 -42
- relationalai/early_access/dsl/orm/utils.py +0 -79
- relationalai/early_access/dsl/orm/verb.py +0 -204
- relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
- relationalai/early_access/dsl/relations.py +0 -170
- relationalai/early_access/dsl/rulesets.py +0 -69
- relationalai/early_access/dsl/schemas/__init__.py +0 -450
- relationalai/early_access/dsl/schemas/builder.py +0 -48
- relationalai/early_access/dsl/schemas/comp_names.py +0 -51
- relationalai/early_access/dsl/schemas/components.py +0 -203
- relationalai/early_access/dsl/schemas/contexts.py +0 -156
- relationalai/early_access/dsl/schemas/exprs.py +0 -89
- relationalai/early_access/dsl/schemas/fragments.py +0 -464
- relationalai/early_access/dsl/serialization.py +0 -79
- relationalai/early_access/dsl/serialize/exporter.py +0 -163
- relationalai/early_access/dsl/snow/api.py +0 -105
- relationalai/early_access/dsl/snow/common.py +0 -76
- relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
- relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
- relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
- relationalai/early_access/dsl/types/__init__.py +0 -40
- relationalai/early_access/dsl/types/concepts.py +0 -12
- relationalai/early_access/dsl/types/entities.py +0 -135
- relationalai/early_access/dsl/types/values.py +0 -17
- relationalai/early_access/dsl/utils.py +0 -102
- relationalai/early_access/graphs/__init__.py +0 -13
- relationalai/early_access/lqp/__init__.py +0 -12
- relationalai/early_access/lqp/compiler/__init__.py +0 -12
- relationalai/early_access/lqp/constructors/__init__.py +0 -18
- relationalai/early_access/lqp/executor/__init__.py +0 -12
- relationalai/early_access/lqp/ir/__init__.py +0 -12
- relationalai/early_access/lqp/passes/__init__.py +0 -12
- relationalai/early_access/lqp/pragmas/__init__.py +0 -12
- relationalai/early_access/lqp/primitives/__init__.py +0 -12
- relationalai/early_access/lqp/types/__init__.py +0 -12
- relationalai/early_access/lqp/utils/__init__.py +0 -12
- relationalai/early_access/lqp/validators/__init__.py +0 -12
- relationalai/early_access/metamodel/__init__.py +0 -58
- relationalai/early_access/metamodel/builtins/__init__.py +0 -12
- relationalai/early_access/metamodel/compiler/__init__.py +0 -12
- relationalai/early_access/metamodel/dependency/__init__.py +0 -12
- relationalai/early_access/metamodel/factory/__init__.py +0 -17
- relationalai/early_access/metamodel/helpers/__init__.py +0 -12
- relationalai/early_access/metamodel/ir/__init__.py +0 -14
- relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
- relationalai/early_access/metamodel/typer/__init__.py +0 -3
- relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
- relationalai/early_access/metamodel/types/__init__.py +0 -15
- relationalai/early_access/metamodel/util/__init__.py +0 -15
- relationalai/early_access/metamodel/visitor/__init__.py +0 -12
- relationalai/early_access/rel/__init__.py +0 -12
- relationalai/early_access/rel/executor/__init__.py +0 -12
- relationalai/early_access/rel/rel_utils/__init__.py +0 -12
- relationalai/early_access/rel/rewrite/__init__.py +0 -7
- relationalai/early_access/solvers/__init__.py +0 -19
- relationalai/early_access/sql/__init__.py +0 -11
- relationalai/early_access/sql/executor/__init__.py +0 -3
- relationalai/early_access/sql/rewrite/__init__.py +0 -3
- relationalai/early_access/tests/logging/__init__.py +0 -12
- relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
- relationalai/early_access/tests/utils/__init__.py +0 -12
- relationalai/environments/__init__.py +0 -35
- relationalai/environments/base.py +0 -381
- relationalai/environments/colab.py +0 -14
- relationalai/environments/generic.py +0 -71
- relationalai/environments/ipython.py +0 -68
- relationalai/environments/jupyter.py +0 -9
- relationalai/environments/snowbook.py +0 -169
- relationalai/errors.py +0 -2496
- relationalai/experimental/SF.py +0 -38
- relationalai/experimental/inspect.py +0 -47
- relationalai/experimental/pathfinder/__init__.py +0 -158
- relationalai/experimental/pathfinder/api.py +0 -160
- relationalai/experimental/pathfinder/automaton.py +0 -584
- relationalai/experimental/pathfinder/bridge.py +0 -226
- relationalai/experimental/pathfinder/compiler.py +0 -416
- relationalai/experimental/pathfinder/datalog.py +0 -214
- relationalai/experimental/pathfinder/diagnostics.py +0 -56
- relationalai/experimental/pathfinder/filter.py +0 -236
- relationalai/experimental/pathfinder/glushkov.py +0 -439
- relationalai/experimental/pathfinder/options.py +0 -265
- relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +0 -1951
- relationalai/experimental/pathfinder/rpq.py +0 -344
- relationalai/experimental/pathfinder/transition.py +0 -200
- relationalai/experimental/pathfinder/utils.py +0 -26
- relationalai/experimental/paths/README.md +0 -107
- relationalai/experimental/paths/api.py +0 -143
- relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
- relationalai/experimental/paths/code_organization.md +0 -2
- relationalai/experimental/paths/examples/Movies.ipynb +0 -16328
- relationalai/experimental/paths/examples/basic_example.py +0 -40
- relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
- relationalai/experimental/paths/examples/movie_example.py +0 -77
- relationalai/experimental/paths/examples/movies_data/actedin.csv +0 -193
- relationalai/experimental/paths/examples/movies_data/directed.csv +0 -45
- relationalai/experimental/paths/examples/movies_data/follows.csv +0 -7
- relationalai/experimental/paths/examples/movies_data/movies.csv +0 -39
- relationalai/experimental/paths/examples/movies_data/person.csv +0 -134
- relationalai/experimental/paths/examples/movies_data/produced.csv +0 -16
- relationalai/experimental/paths/examples/movies_data/ratings.csv +0 -10
- relationalai/experimental/paths/examples/movies_data/wrote.csv +0 -11
- relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
- relationalai/experimental/paths/examples/paths_example.py +0 -116
- relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
- relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
- relationalai/experimental/paths/graph.py +0 -185
- relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
- relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
- relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
- relationalai/experimental/paths/path_algorithms/single.py +0 -59
- relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
- relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
- relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
- relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
- relationalai/experimental/paths/path_algorithms/usp.py +0 -150
- relationalai/experimental/paths/product_graph.py +0 -93
- relationalai/experimental/paths/rpq/automaton.py +0 -584
- relationalai/experimental/paths/rpq/diagnostics.py +0 -56
- relationalai/experimental/paths/rpq/rpq.py +0 -378
- relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
- relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
- relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
- relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
- relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
- relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
- relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
- relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
- relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
- relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
- relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
- relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
- relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
- relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
- relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
- relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
- relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
- relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
- relationalai/experimental/paths/tree_agg.py +0 -168
- relationalai/experimental/paths/utilities/iterators.py +0 -27
- relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
- relationalai/experimental/solvers.py +0 -1095
- relationalai/loaders/csv.py +0 -195
- relationalai/loaders/loader.py +0 -177
- relationalai/loaders/types.py +0 -23
- relationalai/rel_emitter.py +0 -373
- relationalai/rel_utils.py +0 -185
- relationalai/semantics/designs/query_builder/identify_by.md +0 -106
- relationalai/semantics/devtools/benchmark_lqp.py +0 -535
- relationalai/semantics/devtools/compilation_manager.py +0 -294
- relationalai/semantics/devtools/extract_lqp.py +0 -110
- relationalai/semantics/internal/internal.py +0 -3785
- relationalai/semantics/internal/snowflake.py +0 -329
- relationalai/semantics/lqp/README.md +0 -34
- relationalai/semantics/lqp/algorithms.py +0 -173
- relationalai/semantics/lqp/builtins.py +0 -213
- relationalai/semantics/lqp/compiler.py +0 -22
- relationalai/semantics/lqp/constructors.py +0 -68
- relationalai/semantics/lqp/executor.py +0 -518
- relationalai/semantics/lqp/export_rewriter.py +0 -40
- relationalai/semantics/lqp/intrinsics.py +0 -24
- relationalai/semantics/lqp/ir.py +0 -150
- relationalai/semantics/lqp/model2lqp.py +0 -1056
- relationalai/semantics/lqp/passes.py +0 -38
- relationalai/semantics/lqp/primitives.py +0 -252
- relationalai/semantics/lqp/result_helpers.py +0 -266
- relationalai/semantics/lqp/rewrite/__init__.py +0 -32
- relationalai/semantics/lqp/rewrite/algorithm.py +0 -385
- relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -69
- relationalai/semantics/lqp/rewrite/cdc.py +0 -216
- relationalai/semantics/lqp/rewrite/constants_to_vars.py +0 -70
- relationalai/semantics/lqp/rewrite/deduplicate_vars.py +0 -104
- relationalai/semantics/lqp/rewrite/eliminate_data.py +0 -108
- relationalai/semantics/lqp/rewrite/extract_common.py +0 -340
- relationalai/semantics/lqp/rewrite/extract_keys.py +0 -577
- relationalai/semantics/lqp/rewrite/flatten_script.py +0 -301
- relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
- relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -348
- relationalai/semantics/lqp/rewrite/period_math.py +0 -77
- relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -339
- relationalai/semantics/lqp/rewrite/splinter.py +0 -76
- relationalai/semantics/lqp/rewrite/unify_definitions.py +0 -323
- relationalai/semantics/lqp/types.py +0 -101
- relationalai/semantics/lqp/utils.py +0 -170
- relationalai/semantics/lqp/validators.py +0 -70
- relationalai/semantics/metamodel/compiler.py +0 -134
- relationalai/semantics/metamodel/dependency.py +0 -880
- relationalai/semantics/metamodel/executor.py +0 -78
- relationalai/semantics/metamodel/factory.py +0 -287
- relationalai/semantics/metamodel/helpers.py +0 -368
- relationalai/semantics/metamodel/ir.py +0 -924
- relationalai/semantics/metamodel/rewrite/__init__.py +0 -8
- relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
- relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -220
- relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
- relationalai/semantics/metamodel/rewrite/flatten.py +0 -590
- relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -256
- relationalai/semantics/metamodel/rewrite/handle_aggregations_and_ranks.py +0 -237
- relationalai/semantics/metamodel/typer/checker.py +0 -355
- relationalai/semantics/metamodel/typer/typer.py +0 -1396
- relationalai/semantics/metamodel/util.py +0 -506
- relationalai/semantics/metamodel/visitor.py +0 -945
- relationalai/semantics/reasoners/__init__.py +0 -10
- relationalai/semantics/reasoners/graph/README.md +0 -620
- relationalai/semantics/reasoners/graph/__init__.py +0 -37
- relationalai/semantics/reasoners/graph/core.py +0 -9019
- relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +0 -797
- relationalai/semantics/reasoners/graph/tests/README.md +0 -21
- relationalai/semantics/reasoners/optimization/__init__.py +0 -68
- relationalai/semantics/reasoners/optimization/common.py +0 -88
- relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
- relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1407
- relationalai/semantics/rel/builtins.py +0 -40
- relationalai/semantics/rel/compiler.py +0 -994
- relationalai/semantics/rel/executor.py +0 -363
- relationalai/semantics/rel/rel.py +0 -482
- relationalai/semantics/rel/rel_utils.py +0 -276
- relationalai/semantics/snowflake/__init__.py +0 -3
- relationalai/semantics/sql/compiler.py +0 -2503
- relationalai/semantics/sql/executor/duck_db.py +0 -52
- relationalai/semantics/sql/executor/result_helpers.py +0 -64
- relationalai/semantics/sql/executor/snowflake.py +0 -149
- relationalai/semantics/sql/rewrite/denormalize.py +0 -222
- relationalai/semantics/sql/rewrite/double_negation.py +0 -49
- relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
- relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
- relationalai/semantics/sql/sql.py +0 -504
- relationalai/semantics/std/pragmas.py +0 -11
- relationalai/semantics/std/std.py +0 -14
- relationalai/semantics/tests/lqp/algorithms.py +0 -345
- relationalai/semantics/tests/test_snapshot_abstract.py +0 -144
- relationalai/semantics/tests/test_snapshot_base.py +0 -9
- relationalai/semantics/tests/utils.py +0 -46
- relationalai/std/__init__.py +0 -70
- relationalai/tools/cli.py +0 -2089
- relationalai/tools/cli_controls.py +0 -1975
- relationalai/tools/cli_helpers.py +0 -802
- relationalai/tools/debugger_client.py +0 -109
- relationalai/tools/debugger_server.py +0 -302
- relationalai/tools/dev.py +0 -685
- relationalai/tools/notes +0 -7
- relationalai/tools/qb_debugger.py +0 -425
- relationalai/tools/txn_progress.py +0 -188
- relationalai/util/clean_up_databases.py +0 -95
- relationalai/util/list_databases.py +0 -9
- relationalai/util/otel_configuration.py +0 -26
- relationalai/util/otel_handler.py +0 -484
- relationalai/util/snowflake_handler.py +0 -88
- relationalai/util/span_format_test.py +0 -43
- relationalai/util/span_tracker.py +0 -207
- relationalai/util/spans_file_handler.py +0 -72
- relationalai/util/tracing_handler.py +0 -34
- relationalai-0.13.5.dist-info/METADATA +0 -74
- relationalai-0.13.5.dist-info/RECORD +0 -473
- relationalai-0.13.5.dist-info/WHEEL +0 -4
- relationalai-0.13.5.dist-info/entry_points.txt +0 -3
- relationalai-0.13.5.dist-info/licenses/LICENSE +0 -202
- relationalai_test_util/__init__.py +0 -4
- relationalai_test_util/fixtures.py +0 -233
- relationalai_test_util/snapshot.py +0 -252
- relationalai_test_util/traceback.py +0 -118
- /relationalai/{analysis → semantics/frontend}/__init__.py +0 -0
- /relationalai/{auth/__init__.py → semantics/metamodel/metamodel_compiler.py} +0 -0
- /relationalai/{early_access → shims}/__init__.py +0 -0
- {relationalai/early_access/dsl/adapters → v0/relationalai/analysis}/__init__.py +0 -0
- {relationalai → v0/relationalai}/analysis/mechanistic.py +0 -0
- {relationalai → v0/relationalai}/analysis/whynot.py +0 -0
- {relationalai/early_access/dsl/adapters/orm → v0/relationalai/auth}/__init__.py +0 -0
- {relationalai → v0/relationalai}/auth/jwt_generator.py +0 -0
- {relationalai → v0/relationalai}/auth/oauth_callback_server.py +0 -0
- {relationalai → v0/relationalai}/auth/token_handler.py +0 -0
- {relationalai → v0/relationalai}/auth/util.py +0 -0
- {relationalai/clients/resources/snowflake → v0/relationalai/clients}/cache_store.py +0 -0
- {relationalai → v0/relationalai}/compiler.py +0 -0
- {relationalai → v0/relationalai}/dependencies.py +0 -0
- {relationalai → v0/relationalai}/docutils.py +0 -0
- {relationalai/early_access/dsl/adapters/owl → v0/relationalai/early_access}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/__init__.py +0 -0
- {relationalai/early_access/dsl/bindings → v0/relationalai/early_access/dsl/adapters}/__init__.py +0 -0
- {relationalai/early_access/dsl/bindings/legacy → v0/relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
- {relationalai/early_access/dsl/codegen → v0/relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
- {relationalai/early_access/dsl/core/temporal → v0/relationalai/early_access/dsl/bindings}/__init__.py +0 -0
- {relationalai/early_access/dsl/ir → v0/relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
- {relationalai/early_access/dsl/ontologies → v0/relationalai/early_access/dsl/codegen}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/constants.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/core/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/core/stack.py +0 -0
- {relationalai/early_access/dsl/orm → v0/relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/core/utils.py +0 -0
- {relationalai/early_access/dsl/orm/measures → v0/relationalai/early_access/dsl/ir}/__init__.py +0 -0
- {relationalai/early_access/dsl/physical_metadata → v0/relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
- {relationalai/early_access/dsl/serialize → v0/relationalai/early_access/dsl/orm}/__init__.py +0 -0
- {relationalai/early_access/dsl/snow → v0/relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
- {relationalai/loaders → v0/relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
- {relationalai/semantics/tests → v0/relationalai/early_access/dsl/serialize}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/serialize/model.py +0 -0
- {relationalai/semantics/tests/lqp → v0/relationalai/early_access/dsl/snow}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/tests/__init__.py +0 -0
- {relationalai → v0/relationalai}/environments/ci.py +0 -0
- {relationalai → v0/relationalai}/environments/hex.py +0 -0
- {relationalai → v0/relationalai}/environments/terminal.py +0 -0
- {relationalai → v0/relationalai}/experimental/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/graphs.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/rpq/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/rpq/filter.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/rpq/glushkov.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/rpq/transition.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/utilities/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/utilities/utilities.py +0 -0
- {relationalai/tools → v0/relationalai/loaders}/__init__.py +0 -0
- {relationalai → v0/relationalai}/metagen.py +0 -0
- {relationalai → v0/relationalai}/metamodel.py +0 -0
- {relationalai → v0/relationalai}/rel.py +0 -0
- {relationalai → v0/relationalai}/semantics/devtools/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/internal/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/internal/annotations.py +0 -0
- {relationalai → v0/relationalai}/semantics/lqp/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/lqp/pragmas.py +0 -0
- {relationalai → v0/relationalai}/semantics/metamodel/dataflow.py +0 -0
- {relationalai → v0/relationalai}/semantics/metamodel/typer/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/metamodel/types.py +0 -0
- {relationalai → v0/relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/rel/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/sql/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/sql/executor/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/sql/rewrite/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/tests/logging.py +0 -0
- {relationalai → v0/relationalai}/std/aggregates.py +0 -0
- {relationalai → v0/relationalai}/std/dates.py +0 -0
- {relationalai → v0/relationalai}/std/graphs.py +0 -0
- {relationalai → v0/relationalai}/std/inspect.py +0 -0
- {relationalai → v0/relationalai}/std/math.py +0 -0
- {relationalai → v0/relationalai}/std/re.py +0 -0
- {relationalai → v0/relationalai}/std/strings.py +0 -0
- {relationalai → v0/relationalai}/tools/cleanup_snapshots.py +0 -0
- {relationalai → v0/relationalai}/tools/constants.py +0 -0
- {relationalai → v0/relationalai}/tools/query_utils.py +0 -0
- {relationalai → v0/relationalai}/tools/snapshot_viewer.py +0 -0
- {relationalai → v0/relationalai}/util/__init__.py +0 -0
- {relationalai → v0/relationalai}/util/constants.py +0 -0
- {relationalai → v0/relationalai}/util/graph.py +0 -0
- {relationalai → v0/relationalai}/util/timeout.py +0 -0
|
@@ -0,0 +1,1394 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from dataclasses import dataclass, field, replace as dc_replace
|
|
5
|
+
from typing import Dict, Sequence as seq, Iterable
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from math import pi
|
|
8
|
+
|
|
9
|
+
# PyRel imports
|
|
10
|
+
from ..util.naming import sanitize
|
|
11
|
+
from ..semantics.metamodel import metamodel as mm
|
|
12
|
+
from ..semantics.metamodel.builtins import builtins as b, is_abstract
|
|
13
|
+
from ..semantics.metamodel.metamodel_analyzer import Normalize
|
|
14
|
+
# ensure std libs are loaded
|
|
15
|
+
from ..semantics.metamodel.metamodel_analyzer import VarFinder
|
|
16
|
+
from ..semantics.metamodel.rewriter import Walker
|
|
17
|
+
from ..semantics.std import aggregates, common, math, numbers, re, strings, decimals, datetime, floats
|
|
18
|
+
from ..semantics.backends.lqp import annotations as lqp_annotations
|
|
19
|
+
|
|
20
|
+
# V0 imports
|
|
21
|
+
from v0.relationalai.semantics.metamodel import ir as v0, builtins as v0_builtins, types as v0_types, factory as f
|
|
22
|
+
from v0.relationalai.semantics.metamodel.util import FrozenOrderedSet, frozen, ordered_set, filter_by_type, OrderedSet
|
|
23
|
+
from v0.relationalai.semantics.internal.internal import literal_value_to_type
|
|
24
|
+
from v0.relationalai.semantics.metamodel.typer import typer as v0_typer
|
|
25
|
+
from v0.relationalai.clients.util import IdentityParser
|
|
26
|
+
|
|
27
|
+
from .hoister import Hoister
|
|
28
|
+
from .helpers import is_output_update, is_main_output
|
|
29
|
+
|
|
30
|
+
#------------------------------------------------------
|
|
31
|
+
# Simplified translation API
|
|
32
|
+
#------------------------------------------------------
|
|
33
|
+
def translate(model: mm.Model) -> v0.Model:
|
|
34
|
+
return Translator().translate_model(model)
|
|
35
|
+
|
|
36
|
+
#------------------------------------------------------
|
|
37
|
+
# Implementation
|
|
38
|
+
#------------------------------------------------------
|
|
39
|
+
class Context(Enum):
|
|
40
|
+
# when translating tasks (i.e. runtime behavior)
|
|
41
|
+
TASK = 1
|
|
42
|
+
# when translating the static structure of the model (types, relations, etc.)
|
|
43
|
+
MODEL = 2
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class Translator():
|
|
47
|
+
|
|
48
|
+
stack: list[mm.Node] = field(default_factory=list)
|
|
49
|
+
|
|
50
|
+
# maps from mm.Node id to the v0.Node created for it
|
|
51
|
+
# for Context=TASK
|
|
52
|
+
task_map: Dict[int, v0.Node] = field(default_factory=dict)
|
|
53
|
+
# for Context=MODEL
|
|
54
|
+
model_map: Dict[int, v0.Node] = field(default_factory=dict)
|
|
55
|
+
|
|
56
|
+
# map from a var that is bound to a table, to the list of vars that were used to construct
|
|
57
|
+
# this var. This var is going to be used as a key to an output.
|
|
58
|
+
key_map: Dict[mm.Var, seq[v0.Var]] = field(default_factory=dict)
|
|
59
|
+
|
|
60
|
+
# map from a var that is bound to a data, to the data itself. This is used to translate
|
|
61
|
+
# lookups on this var into v0 Data nodes.
|
|
62
|
+
data_map: Dict[mm.Var, mm.Var] = field(default_factory=dict)
|
|
63
|
+
|
|
64
|
+
# map from a var that is bound to an external table, to the vars of its fields
|
|
65
|
+
column_map: defaultdict[mm.Var, dict[mm.Relation, v0.Value]] = field(default_factory=lambda: defaultdict(dict))
|
|
66
|
+
|
|
67
|
+
# used tables
|
|
68
|
+
used_tables: OrderedSet[mm.Table] = field(default_factory=lambda: ordered_set())
|
|
69
|
+
|
|
70
|
+
# when translating a relation that has multiple readings, we need to translate to multiple
|
|
71
|
+
# relations in v0, and we need to add rules to populate those relations. We also need rules
|
|
72
|
+
# to populate super types from sub types.
|
|
73
|
+
maintenance_rules: list[v0.Logical] = field(default_factory=list)
|
|
74
|
+
|
|
75
|
+
# outputs that are exports
|
|
76
|
+
exports: set[v0.Output] = field(default_factory=set)
|
|
77
|
+
|
|
78
|
+
hoister = Hoister()
|
|
79
|
+
normalize = Normalize()
|
|
80
|
+
|
|
81
|
+
def get(self, ctx: Context, node: mm.Node):
|
|
82
|
+
if ctx == Context.MODEL:
|
|
83
|
+
return self.model_map.get(node.id, None)
|
|
84
|
+
else:
|
|
85
|
+
return self.task_map.get(node.id, None)
|
|
86
|
+
def set(self, ctx: Context, node: mm.Node, value: v0.Node):
|
|
87
|
+
if ctx == Context.MODEL:
|
|
88
|
+
self.model_map[node.id] = value # type: ignore
|
|
89
|
+
else:
|
|
90
|
+
self.task_map[node.id] = value # type: ignore
|
|
91
|
+
|
|
92
|
+
def translate_node(self, node: mm.Node, parent=None, ctx=Context.TASK) -> v0.Node|seq[v0.Node]:
|
|
93
|
+
x = self.get(ctx, node)
|
|
94
|
+
if x is not None:
|
|
95
|
+
return x
|
|
96
|
+
|
|
97
|
+
source_class_name = node.__class__.__name__.lower()
|
|
98
|
+
translator = getattr(self, f"translate_{source_class_name}", None)
|
|
99
|
+
if translator is None:
|
|
100
|
+
raise NotImplementedError(f"No translator for node type: {source_class_name}")
|
|
101
|
+
|
|
102
|
+
if parent:
|
|
103
|
+
self.stack.append(parent)
|
|
104
|
+
result = translator(node, parent, ctx)
|
|
105
|
+
if parent:
|
|
106
|
+
self.stack.pop()
|
|
107
|
+
|
|
108
|
+
self.set(ctx, node, result)
|
|
109
|
+
return result
|
|
110
|
+
|
|
111
|
+
def translate_value(self, value: mm.Value, parent, ctx) -> v0.Value:
|
|
112
|
+
# Value = _Union[Var, Literal, Type, Relation, seq["Value"], None]
|
|
113
|
+
if value is None:
|
|
114
|
+
return None
|
|
115
|
+
elif isinstance(value, mm.ScalarType) or isinstance(value, mm.Relation):
|
|
116
|
+
return self.translate_node(value, parent, Context.MODEL) # type: ignore
|
|
117
|
+
elif isinstance(value, seq):
|
|
118
|
+
return self.translate_seq(value, parent, ctx) # type: ignore
|
|
119
|
+
return self.translate_node(value, parent, ctx) # type: ignore
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def translate_seq(self, nodes: seq[mm.Node], parent, ctx) -> tuple[v0.Node,...]:
|
|
123
|
+
res = []
|
|
124
|
+
for n in nodes:
|
|
125
|
+
x = self.translate_node(n, parent, ctx)
|
|
126
|
+
# flat map would be great here
|
|
127
|
+
if isinstance(x, list) or isinstance(x, tuple):
|
|
128
|
+
res.extend(x)
|
|
129
|
+
elif x is not None:
|
|
130
|
+
res.append(x)
|
|
131
|
+
return tuple(res)
|
|
132
|
+
|
|
133
|
+
def translate_frozen(self, nodes: seq[mm.Node], parent, ctx) -> FrozenOrderedSet[v0.Node]:
|
|
134
|
+
return frozen(*self.translate_seq(nodes, parent, ctx))
|
|
135
|
+
|
|
136
|
+
#------------------------------------------------------
|
|
137
|
+
# Helper
|
|
138
|
+
#------------------------------------------------------
|
|
139
|
+
|
|
140
|
+
# NOTE: This has to match what is done in the v0 snowflake.Table class as that is what CDC
|
|
141
|
+
# produces. If there's a quote in the table name, then we take it verbatim, otherwise we lowercase it.
|
|
142
|
+
def translate_table_name(self, table: mm.Table) -> str:
|
|
143
|
+
name = IdentityParser(table.name).identifier
|
|
144
|
+
name = name.lower() if '"' not in table.name else table.name.replace('"', '_')
|
|
145
|
+
return sanitize(name)
|
|
146
|
+
|
|
147
|
+
#-----------------------------------------------------------------------------
|
|
148
|
+
# Capabilities, Reasoners
|
|
149
|
+
#-----------------------------------------------------------------------------
|
|
150
|
+
|
|
151
|
+
def translate_capability(self, c: mm.Capability, parent: mm.Reasoner, ctx) -> v0.Capability:
|
|
152
|
+
return v0.Capability(name=c.name)
|
|
153
|
+
|
|
154
|
+
def translate_reasoner(self, r: mm.Reasoner|None, parent, ctx) -> v0.Engine|None:
|
|
155
|
+
if r is None:
|
|
156
|
+
return None
|
|
157
|
+
return v0.Engine(
|
|
158
|
+
name=f"{r.id}", # no name field in v0, so use id
|
|
159
|
+
platform=r.type,
|
|
160
|
+
info=r.info,
|
|
161
|
+
capabilities=self.translate_frozen(r.capabilities, r, ctx), # type: ignore
|
|
162
|
+
relations=self.translate_frozen(r.relations, r, ctx), # type: ignore
|
|
163
|
+
annotations=self.translate_frozen(r.annotations, r, ctx) # type: ignore
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# -----------------------------------------------------------------------------
|
|
167
|
+
# Relation
|
|
168
|
+
# -----------------------------------------------------------------------------
|
|
169
|
+
|
|
170
|
+
def translate_field(self, f: mm.Field, parent, ctx) -> v0.Field:
|
|
171
|
+
return v0.Field(
|
|
172
|
+
name=f.name,
|
|
173
|
+
type=self.translate_node(f.type, f, Context.MODEL), # type: ignore
|
|
174
|
+
input=f.input,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
def translate_reading(self, r: mm.Reading, parent: mm.Relation, ctx) -> v0.Relation:
|
|
178
|
+
# Readings in v0 are represented as separate Relation nodes with different field orders
|
|
179
|
+
fields = []
|
|
180
|
+
for i in r.field_order:
|
|
181
|
+
fields.append(self.translate_field(parent.fields[i], r, ctx))
|
|
182
|
+
|
|
183
|
+
# this is not totally correct, we are translating the parent's overloads here, but
|
|
184
|
+
# the order of fields would be different. However, it's unlikely we will have multiple
|
|
185
|
+
# readings AND overloads in the same relation, so this is acceptable for now.
|
|
186
|
+
return v0.Relation(
|
|
187
|
+
name=f"{parent.name}_{parent.readings.index(r)}",
|
|
188
|
+
fields=tuple(fields),
|
|
189
|
+
requires=frozen(),
|
|
190
|
+
annotations=frozen(),
|
|
191
|
+
overloads=self.translate_frozen(parent.overloads, parent, ctx), # type: ignore
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
def translate_overload(self, o: mm.Overload, parent: mm.Relation, ctx) -> v0.Relation:
|
|
195
|
+
# Overloads in v0 are represented as separate Relation nodes with different types
|
|
196
|
+
fields = []
|
|
197
|
+
for field, typ in zip(parent.fields, o.types):
|
|
198
|
+
fields.append(
|
|
199
|
+
v0.Field(name=field.name, type=self.translate_node(typ, field, ctx), input=field.input) # type: ignore
|
|
200
|
+
)
|
|
201
|
+
return v0.Relation(
|
|
202
|
+
name=parent.name,
|
|
203
|
+
fields=tuple(fields),
|
|
204
|
+
requires=frozen(),
|
|
205
|
+
annotations=frozen(),
|
|
206
|
+
overloads=frozen()
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# map builtin relations by name
|
|
210
|
+
BUILTIN_RELATION_MAP = {}
|
|
211
|
+
RENAMES = {
|
|
212
|
+
"degrees": "rad2deg",
|
|
213
|
+
"radians": "deg2rad",
|
|
214
|
+
"len": "num_chars",
|
|
215
|
+
"power": "pow",
|
|
216
|
+
"^": "pow",
|
|
217
|
+
"like": "like_match",
|
|
218
|
+
"regex_escape": "escape_regex_metachars",
|
|
219
|
+
}
|
|
220
|
+
for lib in ["core", "aggregates", "common", "datetime", "floats", "math", "numbers", "strings", "re", "lqp"]:
|
|
221
|
+
for x in b._libraries[lib].data.values():
|
|
222
|
+
v0_name = RENAMES.get(x.name, x.name)
|
|
223
|
+
if v0_name in v0_builtins.builtin_relations_by_name:
|
|
224
|
+
BUILTIN_RELATION_MAP[x] = v0_builtins.builtin_relations_by_name[v0_name]
|
|
225
|
+
|
|
226
|
+
def translate_relation(self, r: mm.Relation, parent, ctx):
|
|
227
|
+
if r in self.BUILTIN_RELATION_MAP:
|
|
228
|
+
return self.BUILTIN_RELATION_MAP[r]
|
|
229
|
+
|
|
230
|
+
if r is b.numbers.parse_number:
|
|
231
|
+
if isinstance(parent, mm.Lookup):
|
|
232
|
+
assert(isinstance(parent.args[1], mm.Var))
|
|
233
|
+
out_type = parent.args[1].type
|
|
234
|
+
assert(isinstance(out_type, mm.NumberType))
|
|
235
|
+
if out_type.scale == 0:
|
|
236
|
+
return v0_builtins.parse_int128 if out_type.precision > 19 else v0_builtins.parse_int64
|
|
237
|
+
else:
|
|
238
|
+
return v0_builtins.parse_decimal
|
|
239
|
+
|
|
240
|
+
# relations can be accessed by any context; if it exists in the other context, use it
|
|
241
|
+
other_ctx = Context.MODEL if ctx == Context.TASK else Context.TASK
|
|
242
|
+
x = self.get(other_ctx, r)
|
|
243
|
+
if x is not None:
|
|
244
|
+
return x # type: ignore
|
|
245
|
+
|
|
246
|
+
if len(r.readings) > 1:
|
|
247
|
+
# if there are multiple readings, create a relation per reading
|
|
248
|
+
relations = self.translate_seq(r.readings, r, ctx) # type: ignore
|
|
249
|
+
|
|
250
|
+
# also create a rule to populate the other readings from the main relation
|
|
251
|
+
main_relation = relations[0]
|
|
252
|
+
assert isinstance(main_relation, v0.Relation)
|
|
253
|
+
main_relation_args = tuple(v0.Var(type=field.type, name=field.name) for field in main_relation.fields)
|
|
254
|
+
for reading in r.readings[1:]:
|
|
255
|
+
relation = relations[r.readings.index(reading)]
|
|
256
|
+
assert isinstance(relation, v0.Relation)
|
|
257
|
+
# lookup from main_relation and derive into this relation
|
|
258
|
+
self.maintenance_rules.append(v0.Logical(
|
|
259
|
+
engine=None,
|
|
260
|
+
hoisted=(),
|
|
261
|
+
body=(
|
|
262
|
+
v0.Lookup(
|
|
263
|
+
engine=None,
|
|
264
|
+
relation=main_relation,
|
|
265
|
+
args=main_relation_args,
|
|
266
|
+
annotations=frozen(),
|
|
267
|
+
),
|
|
268
|
+
v0.Update(
|
|
269
|
+
engine=None,
|
|
270
|
+
relation=relation,
|
|
271
|
+
args=tuple([main_relation_args[idx] for idx in reading.field_order]),
|
|
272
|
+
effect=v0.Effect.derive,
|
|
273
|
+
annotations=frozen(),
|
|
274
|
+
)
|
|
275
|
+
),
|
|
276
|
+
annotations=frozen(),
|
|
277
|
+
))
|
|
278
|
+
return relations
|
|
279
|
+
else:
|
|
280
|
+
# if there are no readings or a single reading, create a single relation
|
|
281
|
+
|
|
282
|
+
# if this is a placeholder relation, fill overloads with all non-placeholder relations
|
|
283
|
+
# with the same name
|
|
284
|
+
overloads = ordered_set()
|
|
285
|
+
if all(field.type == b.core.Any for field in r.fields):
|
|
286
|
+
for rr in self.relations_by_name[r.name]:
|
|
287
|
+
if any(field.type != b.core.Any for field in rr.fields):
|
|
288
|
+
x = self.translate_relation(rr, r, ctx)
|
|
289
|
+
if isinstance(x, v0.Relation):
|
|
290
|
+
overloads.add(x)
|
|
291
|
+
else:
|
|
292
|
+
overloads.update(x) # type: ignore
|
|
293
|
+
overloads.update(self.translate_frozen(r.overloads, r, ctx)) # type: ignore
|
|
294
|
+
annotations = self.translate_seq(r.annotations, r, ctx) # type: ignore
|
|
295
|
+
name = r.name
|
|
296
|
+
fields = self.translate_seq(r.fields, r, ctx) # type: ignore
|
|
297
|
+
# We need to turn column relations into what the CDC pass would otherwise produce
|
|
298
|
+
# by making the relation name be the table name and adding a symbol field at the front
|
|
299
|
+
# representing the column name
|
|
300
|
+
if r.fields and isinstance(r.fields[0].type, mm.Table) and r in r.fields[0].type.columns:
|
|
301
|
+
name = self.translate_table_name(r.fields[0].type)
|
|
302
|
+
fields = (v0.Field("symbol", v0_types.Symbol, False), *fields) # type: ignore
|
|
303
|
+
annotations = annotations + (v0_builtins.external_annotation,)
|
|
304
|
+
|
|
305
|
+
return v0.Relation(
|
|
306
|
+
name=name,
|
|
307
|
+
fields=frozen(*fields), # type: ignore
|
|
308
|
+
requires=self.translate_frozen(r.requires, r, ctx), # type: ignore
|
|
309
|
+
annotations=frozen(*annotations), # type: ignore
|
|
310
|
+
overloads=overloads.frozen(), # type: ignore
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
def translate_unresolvedrelation(self, r: mm.UnresolvedRelation, parent, ctx):
|
|
314
|
+
# treat unresolved relations the same as normal relations for now
|
|
315
|
+
return self.translate_relation(r, parent, ctx)
|
|
316
|
+
|
|
317
|
+
#------------------------------------------------------
|
|
318
|
+
# Annotation
|
|
319
|
+
#------------------------------------------------------
|
|
320
|
+
|
|
321
|
+
def translate_annotation(self, a: mm.Annotation, parent, ctx) -> v0.Annotation:
|
|
322
|
+
if a.relation.name in v0_builtins.builtin_annotations_by_name:
|
|
323
|
+
return getattr(v0_builtins, a.relation.name + "_annotation") # type: ignore
|
|
324
|
+
|
|
325
|
+
return v0.Annotation(
|
|
326
|
+
relation=self.translate_node(a.relation, a, Context.MODEL), # type: ignore
|
|
327
|
+
args=tuple(self.translate_value(arg, a, ctx) for arg in a.args)
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
#-----------------------------------------------------------------------------
|
|
331
|
+
# Types
|
|
332
|
+
#-----------------------------------------------------------------------------
|
|
333
|
+
|
|
334
|
+
BUILTIN_TYPE_MAP = {
|
|
335
|
+
# Abstract types (should be removed once our typer is done because they should not
|
|
336
|
+
# show up in the typed metamodel.)
|
|
337
|
+
b.core.Any: v0_types.Any,
|
|
338
|
+
# b.core.AnyEntity: v0_types.AnyEntity,
|
|
339
|
+
b.core.Number: v0_types.Number, # v0 typer can figure the rest out
|
|
340
|
+
# Concrete types
|
|
341
|
+
b.core.Boolean: v0_types.Bool,
|
|
342
|
+
b.core.String: v0_types.String,
|
|
343
|
+
b.core.Date: v0_types.Date,
|
|
344
|
+
b.core.DateTime: v0_types.DateTime,
|
|
345
|
+
b.core.Float: v0_types.Float,
|
|
346
|
+
b.core.Hash: v0_types.Hash,
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
def translate_scalartype(self, t: mm.ScalarType, parent: mm.Node, ctx) -> v0.ScalarType|v0.Relation|None:
|
|
350
|
+
if t in self.BUILTIN_TYPE_MAP:
|
|
351
|
+
return self.BUILTIN_TYPE_MAP[t]
|
|
352
|
+
|
|
353
|
+
if ctx == Context.TASK:
|
|
354
|
+
# in task context, this is a lookup or update on a concept population relation
|
|
355
|
+
# TODO - removing this filter for now
|
|
356
|
+
actual_type = self.translate_node(t, t, Context.MODEL)
|
|
357
|
+
assert isinstance(actual_type, v0.ScalarType)
|
|
358
|
+
fields = [v0.Field(name="entity", type=actual_type, input=False)] # type: ignore
|
|
359
|
+
annotations = [v0_builtins.concept_relation_annotation]
|
|
360
|
+
name = t.name
|
|
361
|
+
if isinstance(t, mm.Table):
|
|
362
|
+
annotations.append(v0_builtins.external_annotation)
|
|
363
|
+
name = self.translate_table_name(t)
|
|
364
|
+
fields.insert(0, v0.Field(name="symbol", type=v0_types.Symbol, input=False)) # type: ignore
|
|
365
|
+
|
|
366
|
+
type_relation = v0.Relation(
|
|
367
|
+
name=name,
|
|
368
|
+
fields=tuple(fields), # type: ignore
|
|
369
|
+
requires=frozen(),
|
|
370
|
+
annotations=frozen(*annotations), # type: ignore
|
|
371
|
+
overloads=frozen()
|
|
372
|
+
)
|
|
373
|
+
for super_type in t.super_types:
|
|
374
|
+
super_rel = self.translate_node(super_type, t, Context.TASK)
|
|
375
|
+
if not super_rel:
|
|
376
|
+
continue
|
|
377
|
+
assert isinstance(super_rel, v0.Relation)
|
|
378
|
+
v = v0.Var(type=actual_type, name=type_relation.name.lower())
|
|
379
|
+
self.maintenance_rules.append(v0.Logical(
|
|
380
|
+
engine=None,
|
|
381
|
+
hoisted=(),
|
|
382
|
+
body=(
|
|
383
|
+
v0.Lookup(
|
|
384
|
+
engine=None,
|
|
385
|
+
relation=type_relation,
|
|
386
|
+
args=(v,),
|
|
387
|
+
annotations=frozen(),
|
|
388
|
+
),
|
|
389
|
+
v0.Update(
|
|
390
|
+
engine=None,
|
|
391
|
+
relation=super_rel,
|
|
392
|
+
args=(v,),
|
|
393
|
+
effect=v0.Effect.derive,
|
|
394
|
+
annotations=frozen(),
|
|
395
|
+
)
|
|
396
|
+
),
|
|
397
|
+
annotations=frozen(),
|
|
398
|
+
))
|
|
399
|
+
return type_relation
|
|
400
|
+
|
|
401
|
+
extends=[]
|
|
402
|
+
if isinstance(t, mm.Table):
|
|
403
|
+
extends.append(v0_types.RowId)
|
|
404
|
+
|
|
405
|
+
for st in t.super_types:
|
|
406
|
+
# for now make all value types extending number be Int64, we will fix this with a new typer
|
|
407
|
+
if st == b.core.Number:
|
|
408
|
+
translated_st = v0_types.Number
|
|
409
|
+
else:
|
|
410
|
+
translated_st = self.translate_node(st, t, ctx)
|
|
411
|
+
extends.append(translated_st)
|
|
412
|
+
|
|
413
|
+
return v0.ScalarType(
|
|
414
|
+
name=t.name,
|
|
415
|
+
super_types=frozen(*extends), # type: ignore
|
|
416
|
+
# super_types=self.translate_frozen(t.super_types, t, ctx), # type: ignore
|
|
417
|
+
annotations=self.translate_frozen(t.annotations, t, ctx) # type: ignore
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
def translate_numbertype(self, t: mm.NumberType, parent, ctx):
|
|
421
|
+
if t.scale == 0:
|
|
422
|
+
return v0_types.Int128 if t.precision > 19 else v0_types.Int64
|
|
423
|
+
return v0.DecimalType(
|
|
424
|
+
name=t.name,
|
|
425
|
+
precision=t.precision,
|
|
426
|
+
scale=t.scale,
|
|
427
|
+
super_types=frozen(),
|
|
428
|
+
annotations=self.translate_frozen(t.annotations, t, ctx) # type: ignore
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
def translate_uniontype(self, t: mm.UnionType, parent, ctx) -> v0.UnionType:
|
|
432
|
+
return v0.UnionType(
|
|
433
|
+
types=self.translate_frozen(t.types, t, ctx), # type: ignore
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
def translate_listtype(self, t: mm.ListType, parent, ctx) -> v0.ListType:
|
|
437
|
+
return v0.ListType(
|
|
438
|
+
element_type=self.translate_node(t.element_type, t, ctx), # type: ignore
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
def translate_tupletype(self, t: mm.TupleType, parent, ctx) -> v0.TupleType:
|
|
442
|
+
return v0.TupleType(
|
|
443
|
+
types=self.translate_seq(t.element_types, t, ctx), # type: ignore
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
#------------------------------------------------------
|
|
448
|
+
# Table
|
|
449
|
+
#------------------------------------------------------
|
|
450
|
+
|
|
451
|
+
# TODO - this depends on what is using it, it may become an Output
|
|
452
|
+
# class Table(ScalarType):
|
|
453
|
+
# columns: seq[Relation] = tuple_field()
|
|
454
|
+
# uri: str = ""
|
|
455
|
+
|
|
456
|
+
def translate_table(self, t: mm.Table, parent, ctx):
|
|
457
|
+
return self.translate_scalartype(t, parent, ctx)
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
# -----------------------------------------------------------------------------
|
|
461
|
+
# Values
|
|
462
|
+
# -----------------------------------------------------------------------------
|
|
463
|
+
|
|
464
|
+
# Primitive = _Union[str, int, float, bool, _dt.datetime, None]
|
|
465
|
+
|
|
466
|
+
def translate_var(self, v: mm.Var, parent, ctx) -> v0.Var:
|
|
467
|
+
if isinstance(parent, mm.Lookup):
|
|
468
|
+
root_type = parent.relation.fields[0].type
|
|
469
|
+
root_arg = parent.args[0]
|
|
470
|
+
if isinstance(root_arg, mm.Var) \
|
|
471
|
+
and isinstance(root_type, mm.Table) \
|
|
472
|
+
and (existing := self.column_map[root_arg].get(parent.relation)):
|
|
473
|
+
return existing # type: ignore
|
|
474
|
+
|
|
475
|
+
return v0.Var(
|
|
476
|
+
type=self.translate_node(v.type, v, Context.MODEL), # type: ignore
|
|
477
|
+
name=v.name
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
def translate_literal(self, l: mm.Literal, parent, ctx) -> v0.Literal:
|
|
481
|
+
typ = None
|
|
482
|
+
if l.type is None or is_abstract(l.type):
|
|
483
|
+
# force int64 for literals, it can be widened later if needed
|
|
484
|
+
if type(l.value) == int:
|
|
485
|
+
typ = v0_types.Int64
|
|
486
|
+
else:
|
|
487
|
+
# using v0's map of literal to type
|
|
488
|
+
typ = literal_value_to_type(l.value)
|
|
489
|
+
else:
|
|
490
|
+
typ = self.translate_node(l.type, l, Context.MODEL)
|
|
491
|
+
if type is None:
|
|
492
|
+
pass
|
|
493
|
+
return v0.Literal(
|
|
494
|
+
type=typ, # type: ignore
|
|
495
|
+
value=l.value
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
# Value = _Union[Var, Literal, Type, Relation, seq["Value"], None]
|
|
499
|
+
|
|
500
|
+
# # -----------------------------------------------------------------------------
|
|
501
|
+
# # Tasks (process algebra)
|
|
502
|
+
# # -----------------------------------------------------------------------------
|
|
503
|
+
|
|
504
|
+
# @dataclass(frozen=True, kw_only=True)
|
|
505
|
+
# class Task(Node):
|
|
506
|
+
# reasoner: Optional[Reasoner] = None
|
|
507
|
+
|
|
508
|
+
# -----------------------------
|
|
509
|
+
# Control Flow
|
|
510
|
+
# -----------------------------
|
|
511
|
+
|
|
512
|
+
def _merge_outputs(self, children: seq[v0.Node], outputs:list[v0.Output]):
|
|
513
|
+
# We need to always rewrite the outputs, even if there's only one, because
|
|
514
|
+
# we may need to mark it as an export and handle the NO_KEYS case.
|
|
515
|
+
# if len(outputs) < 2:
|
|
516
|
+
# return children
|
|
517
|
+
|
|
518
|
+
children = list(children)
|
|
519
|
+
|
|
520
|
+
# merge all outputs, accumulating keys and aliases
|
|
521
|
+
keys = ordered_set()
|
|
522
|
+
aliases = ordered_set()
|
|
523
|
+
for output in outputs:
|
|
524
|
+
assert isinstance(output, v0.Output)
|
|
525
|
+
children.remove(output)
|
|
526
|
+
if output.keys is not None:
|
|
527
|
+
keys.update(output.keys)
|
|
528
|
+
aliases.update(output.aliases)
|
|
529
|
+
|
|
530
|
+
# add a single, merged output
|
|
531
|
+
is_export = any(output in self.exports for output in outputs)
|
|
532
|
+
annos = (v0_builtins.export_annotation,) if is_export else ()
|
|
533
|
+
if is_export and not keys:
|
|
534
|
+
key_var = v0.Var(type=v0_types.Hash, name="export_key")
|
|
535
|
+
vals = [alias[1] for alias in aliases]
|
|
536
|
+
children.append(v0.Construct(
|
|
537
|
+
engine=None,
|
|
538
|
+
values=(v0.Literal(type=v0_types.String, value="NO_KEYS"), *vals),
|
|
539
|
+
id_var=key_var,
|
|
540
|
+
))
|
|
541
|
+
keys.add(key_var)
|
|
542
|
+
|
|
543
|
+
children.append(
|
|
544
|
+
v0.Output(
|
|
545
|
+
engine=None,
|
|
546
|
+
aliases=frozen(*aliases),
|
|
547
|
+
keys=frozen(*keys),
|
|
548
|
+
annotations=frozen(*annos)
|
|
549
|
+
)
|
|
550
|
+
)
|
|
551
|
+
return tuple(children)
|
|
552
|
+
|
|
553
|
+
def get_outputs(self, children: seq[v0.Node]) -> list[v0.Output]:
|
|
554
|
+
return list(filter(lambda o: isinstance(o, v0.Output), children)) # type: ignore
|
|
555
|
+
|
|
556
|
+
def translate_logical(self, l: mm.Logical, parent, ctx):
|
|
557
|
+
# first process children
|
|
558
|
+
children = self.translate_seq(l.body, l, ctx)
|
|
559
|
+
|
|
560
|
+
# inline logicals if possible
|
|
561
|
+
new_children = []
|
|
562
|
+
for c in children:
|
|
563
|
+
if isinstance(c, v0.Logical) and not c.hoisted and len(c.body) == 1 and not isinstance(c.body[0], (v0.Aggregate, v0.Rank)):
|
|
564
|
+
new_children.extend(c.body)
|
|
565
|
+
else:
|
|
566
|
+
new_children.append(c)
|
|
567
|
+
# children = children if len(children) == len(new_children) else tuple(new_children)
|
|
568
|
+
children = tuple(new_children)
|
|
569
|
+
|
|
570
|
+
# compute variables to hoist, wrapping in Default if the logical is optional
|
|
571
|
+
if l.optional:
|
|
572
|
+
hoisted = tuple([v0.Default(self.translate_node(v, l, ctx), None) for v in self.hoister.hoisted(l)]) # type: ignore
|
|
573
|
+
else:
|
|
574
|
+
hoisted = tuple([self.translate_node(v, l, ctx) for v in self.hoister.hoisted(l)]) # type: ignore
|
|
575
|
+
|
|
576
|
+
# Nots can never hoist variables upwards
|
|
577
|
+
if isinstance(parent, mm.Not):
|
|
578
|
+
hoisted = ()
|
|
579
|
+
|
|
580
|
+
# if there are no outputs, just return the logical
|
|
581
|
+
outputs = self.get_outputs(children)
|
|
582
|
+
if not outputs:
|
|
583
|
+
return v0.Logical(
|
|
584
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
585
|
+
hoisted=hoisted, # type: ignore
|
|
586
|
+
body=children, # type: ignore
|
|
587
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
# if there's a main output here, we need to merge all outputs as a single one
|
|
592
|
+
has_main_output = any(is_main_output(c) for c in l.body)
|
|
593
|
+
if has_main_output:
|
|
594
|
+
return v0.Logical(
|
|
595
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
596
|
+
hoisted=hoisted, # type: ignore
|
|
597
|
+
body=self._merge_outputs(children, outputs), # type: ignore
|
|
598
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
599
|
+
)
|
|
600
|
+
else:
|
|
601
|
+
# this logical has an output but it's not the main one; so we return the outputs
|
|
602
|
+
# side-by-side with the logical. This assumes that the parent is a logical that
|
|
603
|
+
# will splat these tasks and we will eventually get into a logical with a main
|
|
604
|
+
# output that will merge them all.
|
|
605
|
+
|
|
606
|
+
# remove outputs from children
|
|
607
|
+
children = tuple([c for c in children if not isinstance(c, v0.Output)])
|
|
608
|
+
if not children:
|
|
609
|
+
return outputs
|
|
610
|
+
|
|
611
|
+
# if this is an optional logical but we're not hoisting anything and not updating,
|
|
612
|
+
# then it's possible we're filtering an outer variable, but only for this column. If
|
|
613
|
+
# so, we need to alias the output and hoist it.
|
|
614
|
+
# this is important because the LQP stack blows up if there's a logical with no effect
|
|
615
|
+
if l.optional and not hoisted and not any(isinstance(c, v0.Update) for c in children):
|
|
616
|
+
# if there are no lookups, then this really is a no-op, just return outputs
|
|
617
|
+
# LQP blows up with e.g. a match-only logical
|
|
618
|
+
if not any(isinstance(c, v0.Lookup) for c in children):
|
|
619
|
+
return outputs
|
|
620
|
+
# otherwise, make sure we filter the outer variable through aliasing
|
|
621
|
+
new_children = [*children]
|
|
622
|
+
new_hoists = []
|
|
623
|
+
new_outputs = []
|
|
624
|
+
# add an eq to a new var for the output, hoist the new var, change the output to use the new var
|
|
625
|
+
for output in outputs:
|
|
626
|
+
# shim outputs always only have one alias
|
|
627
|
+
(name, orig_var) = output.aliases.data[0]
|
|
628
|
+
# if the original var is not a Var or Literal, or it's already in the keys, skip (we can't filter keys)
|
|
629
|
+
if not isinstance(orig_var, (v0.Var, v0.Literal)) or (output.keys and orig_var in output.keys): #type: ignore
|
|
630
|
+
new_outputs.append(output)
|
|
631
|
+
continue
|
|
632
|
+
new_var = v0.Var(
|
|
633
|
+
type=orig_var.type,
|
|
634
|
+
name=f"{orig_var.name if isinstance(orig_var, v0.Var) else 'literal'}_hoisted"
|
|
635
|
+
)
|
|
636
|
+
new_output = v0.Output(
|
|
637
|
+
engine=None,
|
|
638
|
+
aliases=frozen((name, new_var)),
|
|
639
|
+
keys=output.keys,
|
|
640
|
+
annotations=output.annotations
|
|
641
|
+
)
|
|
642
|
+
eq = v0.Lookup(
|
|
643
|
+
engine=None,
|
|
644
|
+
relation=v0_builtins.eq,
|
|
645
|
+
args=(new_var, orig_var),
|
|
646
|
+
annotations=frozen()
|
|
647
|
+
)
|
|
648
|
+
new_children.append(eq)
|
|
649
|
+
new_hoists.append(v0.Default(new_var, None))
|
|
650
|
+
new_outputs.append(new_output)
|
|
651
|
+
outputs = new_outputs
|
|
652
|
+
hoisted = tuple(new_hoists)
|
|
653
|
+
children = tuple(new_children)
|
|
654
|
+
# return outputs
|
|
655
|
+
|
|
656
|
+
# return outputs + a logical with the other children
|
|
657
|
+
outputs.append(
|
|
658
|
+
v0.Logical(
|
|
659
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
660
|
+
hoisted=hoisted, # type: ignore
|
|
661
|
+
body=children, # type: ignore
|
|
662
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
663
|
+
))
|
|
664
|
+
return outputs
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
def translate_sequence(self, s: mm.Sequence, parent, ctx) -> v0.Sequence:
|
|
670
|
+
return v0.Sequence(
|
|
671
|
+
engine=self.translate_reasoner(s.reasoner, s, Context.MODEL),
|
|
672
|
+
hoisted=self.translate_seq(self.hoister.hoisted(s), s, ctx), # type: ignore
|
|
673
|
+
tasks=self.translate_seq(s.tasks, s, ctx), # type: ignore
|
|
674
|
+
annotations=self.translate_frozen(s.annotations, s, ctx) # type: ignore
|
|
675
|
+
)
|
|
676
|
+
|
|
677
|
+
def translate_union(self, u: mm.Union, parent, ctx) -> v0.Union:
|
|
678
|
+
return v0.Union(
|
|
679
|
+
engine=self.translate_reasoner(u.reasoner, u, Context.MODEL),
|
|
680
|
+
hoisted=self.translate_seq(self.hoister.hoisted(u), u, ctx), # type: ignore
|
|
681
|
+
tasks=self.translate_seq(u.tasks, u, ctx), # type: ignore
|
|
682
|
+
annotations=self.translate_frozen(u.annotations, u, ctx) # type: ignore
|
|
683
|
+
)
|
|
684
|
+
|
|
685
|
+
def translate_match(self, m: mm.Match, parent, ctx) -> v0.Match:
|
|
686
|
+
return v0.Match(
|
|
687
|
+
engine=self.translate_reasoner(m.reasoner, m, Context.MODEL),
|
|
688
|
+
hoisted=self.translate_seq(self.hoister.hoisted(m), m, ctx), # type: ignore
|
|
689
|
+
tasks=self.translate_seq(m.tasks, m, ctx), # type: ignore
|
|
690
|
+
annotations=self.translate_frozen(m.annotations, m, ctx) # type: ignore
|
|
691
|
+
)
|
|
692
|
+
|
|
693
|
+
def translate_until(self, u: mm.Until, parent, ctx) -> v0.Until:
|
|
694
|
+
return v0.Until(
|
|
695
|
+
engine=self.translate_reasoner(u.reasoner, u, Context.MODEL),
|
|
696
|
+
hoisted=self.translate_seq(self.hoister.hoisted(u), u, ctx), # type: ignore
|
|
697
|
+
check=self.translate_node(u.check, u, ctx), # type: ignore
|
|
698
|
+
body=self.translate_node(u.body, u, ctx), # type: ignore
|
|
699
|
+
annotations=self.translate_frozen(u.annotations, u, ctx) # type: ignore
|
|
700
|
+
)
|
|
701
|
+
|
|
702
|
+
def translate_wait(self, w: mm.Wait, parent, ctx) -> v0.Wait:
|
|
703
|
+
return v0.Wait(
|
|
704
|
+
engine=self.translate_reasoner(w.reasoner, w, Context.MODEL),
|
|
705
|
+
hoisted=self.translate_seq(self.hoister.hoisted(w), w, ctx), # type: ignore
|
|
706
|
+
check=self.translate_node(w.check, w, ctx), # type: ignore
|
|
707
|
+
annotations=self.translate_frozen(w.annotations, w, ctx) # type: ignore
|
|
708
|
+
)
|
|
709
|
+
|
|
710
|
+
def translate_loop(self, l: mm.Loop, parent, ctx) -> v0.Loop:
|
|
711
|
+
# TODO - loop is incompatible because over has multiple vars, so this is a best
|
|
712
|
+
# attempt (does not matter much as this is not used in practice)
|
|
713
|
+
return v0.Loop(
|
|
714
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
715
|
+
hoisted=self.translate_seq(self.hoister.hoisted(l), l, ctx), # type: ignore
|
|
716
|
+
iter=self.translate_node(l.over[0], l, ctx), # type: ignore
|
|
717
|
+
body=self.translate_node(l.body, l, ctx), # type: ignore
|
|
718
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
719
|
+
)
|
|
720
|
+
|
|
721
|
+
def translate_break(self, b: mm.Break, parent, ctx) -> v0.Break:
|
|
722
|
+
return v0.Break(
|
|
723
|
+
engine=self.translate_reasoner(b.reasoner, b, Context.MODEL),
|
|
724
|
+
check=self.translate_node(b.check, b, ctx), # type: ignore
|
|
725
|
+
annotations=self.translate_frozen(b.annotations, b, ctx) # type: ignore
|
|
726
|
+
)
|
|
727
|
+
|
|
728
|
+
# -----------------------------
|
|
729
|
+
# Constraints
|
|
730
|
+
# -----------------------------
|
|
731
|
+
|
|
732
|
+
def translate_require(self, r: mm.Require, parent, ctx) -> v0.Require|None:
|
|
733
|
+
# check if this is a unique_fields constraint
|
|
734
|
+
assert isinstance(r.domain, mm.Logical)
|
|
735
|
+
assert isinstance(r.check, mm.Logical)
|
|
736
|
+
if not r.domain.body and all(isinstance(c, mm.Lookup) and c.relation is b.constraints.unique_fields for c in r.check.body):
|
|
737
|
+
return
|
|
738
|
+
v0_reqs = []
|
|
739
|
+
# v0 expects a check with both the domain and the relation in it followed by the unique
|
|
740
|
+
# constraint, so we construct a logical with all of that in it
|
|
741
|
+
for c in r.check.body:
|
|
742
|
+
assert isinstance(c, mm.Lookup)
|
|
743
|
+
fields = c.args[0] # tuple of fields
|
|
744
|
+
assert isinstance(fields, tuple) and all(isinstance(f, mm.Field) for f in fields)
|
|
745
|
+
first_field = fields[0]
|
|
746
|
+
if isinstance(first_field.type, mm.Table):
|
|
747
|
+
# skip union types for now
|
|
748
|
+
continue
|
|
749
|
+
assert isinstance(first_field, mm.Field)
|
|
750
|
+
relation = first_field._relation
|
|
751
|
+
domain = self.translate_node(mm.Logical(()), r, ctx)
|
|
752
|
+
all_vars = [mm.Var(type=field.type, name=field.name + "_var") for field in relation.fields]
|
|
753
|
+
check_tasks = [
|
|
754
|
+
mm.Lookup(relation, tuple(all_vars)),
|
|
755
|
+
mm.Lookup(b.constraints.unique, (tuple(all_vars[0:len(fields)]),))
|
|
756
|
+
]
|
|
757
|
+
check_logical = self.translate_node(mm.Logical(tuple(check_tasks)), r, Context.TASK)
|
|
758
|
+
check = v0.Check(
|
|
759
|
+
check=check_logical, # type: ignore
|
|
760
|
+
error=None,
|
|
761
|
+
annotations=self.translate_frozen(r.annotations, r, ctx) # type: ignore
|
|
762
|
+
)
|
|
763
|
+
v0_reqs.append(v0.Require(
|
|
764
|
+
engine=self.translate_reasoner(r.reasoner, r, Context.MODEL),
|
|
765
|
+
domain=domain, # type: ignore
|
|
766
|
+
checks=(check,), # type: ignore
|
|
767
|
+
annotations=self.translate_frozen(r.annotations, r, ctx) # type: ignore
|
|
768
|
+
))
|
|
769
|
+
return v0_reqs # type: ignore
|
|
770
|
+
|
|
771
|
+
# check = v0.Check(
|
|
772
|
+
# check=self.translate_node(r.check, r, ctx), # type: ignore
|
|
773
|
+
# error=self.translate_node(r.error, r, ctx) if r.error else None, # type: ignore
|
|
774
|
+
# annotations=self.translate_frozen(r.annotations, r, ctx) # type: ignore
|
|
775
|
+
# )
|
|
776
|
+
# return v0.Require(
|
|
777
|
+
# engine=self.translate_reasoner(r.reasoner, r, Context.MODEL),
|
|
778
|
+
# domain=self.translate_node(r.domain, r, ctx), # type: ignore
|
|
779
|
+
# checks=(check,), # type: ignore
|
|
780
|
+
# annotations=self.translate_frozen(r.annotations, r, ctx) # type: ignore
|
|
781
|
+
# )
|
|
782
|
+
return None
|
|
783
|
+
|
|
784
|
+
# -----------------------------
|
|
785
|
+
# Quantifiers
|
|
786
|
+
# -----------------------------
|
|
787
|
+
|
|
788
|
+
def translate_not(self, n: mm.Not, parent, ctx) -> v0.Not:
|
|
789
|
+
return v0.Not(
|
|
790
|
+
engine=self.translate_reasoner(n.reasoner, n, Context.MODEL),
|
|
791
|
+
task=self.translate_node(n.task, n, ctx), # type: ignore
|
|
792
|
+
annotations=self.translate_frozen(n.annotations, n, ctx) # type: ignore
|
|
793
|
+
)
|
|
794
|
+
|
|
795
|
+
def translate_exists(self, e: mm.Exists, parent, ctx) -> v0.Exists:
|
|
796
|
+
return v0.Exists(
|
|
797
|
+
engine=self.translate_reasoner(e.reasoner, e, Context.MODEL),
|
|
798
|
+
vars=self.translate_seq(e.vars, e, ctx), # type: ignore
|
|
799
|
+
task=self.translate_node(e.task, e, ctx), # type: ignore
|
|
800
|
+
annotations=self.translate_frozen(e.annotations, e, ctx) # type: ignore
|
|
801
|
+
)
|
|
802
|
+
|
|
803
|
+
# -----------------------------
|
|
804
|
+
# Relation Ops
|
|
805
|
+
# -----------------------------
|
|
806
|
+
|
|
807
|
+
def translate_effect(self, e: mm.Effect, parent, ctx) -> v0.Effect:
|
|
808
|
+
if e == mm.Effect.derive:
|
|
809
|
+
return v0.Effect.derive
|
|
810
|
+
elif e == mm.Effect.insert:
|
|
811
|
+
return v0.Effect.insert
|
|
812
|
+
elif e == mm.Effect.delete:
|
|
813
|
+
return v0.Effect.delete
|
|
814
|
+
|
|
815
|
+
def translate_lookup(self, l: mm.Lookup, parent, ctx):
|
|
816
|
+
# Data Node lookups
|
|
817
|
+
if isinstance(l.relation, mm.Data):
|
|
818
|
+
vars = [self.translate_value(l.args[0], l, ctx)]
|
|
819
|
+
for col in l.relation.columns:
|
|
820
|
+
v = v0.Var(
|
|
821
|
+
type=self.translate_node(col.fields[-1].type, col, Context.MODEL), # type: ignore
|
|
822
|
+
name=f"{col.name}"
|
|
823
|
+
)
|
|
824
|
+
vars.append(v)
|
|
825
|
+
assert isinstance(l.args[0], mm.Var)
|
|
826
|
+
self.column_map[l.args[0]][col] = v
|
|
827
|
+
return v0.Data(
|
|
828
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
829
|
+
data=l.relation.data,
|
|
830
|
+
vars=frozen(*vars) # type: ignore
|
|
831
|
+
)
|
|
832
|
+
elif l.args and l.args[0] in self.column_map and l.relation in self.column_map[l.args[0]]: # type: ignore
|
|
833
|
+
assert isinstance(l.args[0], mm.Var)
|
|
834
|
+
var = self.translate_value(l.args[1], l, ctx)
|
|
835
|
+
col_var = self.column_map[l.args[0]][l.relation] # ensure entry exists
|
|
836
|
+
if var != col_var:
|
|
837
|
+
return v0.Lookup(
|
|
838
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
839
|
+
relation=v0_builtins.eq,
|
|
840
|
+
args=(var, col_var), # type: ignore
|
|
841
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
842
|
+
)
|
|
843
|
+
# if this is a data column, we just ignore it as the data node already binds the variables
|
|
844
|
+
elif isinstance(l.args[0].type, mm.Data):
|
|
845
|
+
return None
|
|
846
|
+
# Otherwise we keep the lookup because that's what the LQP stack expect (the lookup gets repeated for
|
|
847
|
+
# each column)
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
relation, args = self._resolve_reading(l, ctx)
|
|
851
|
+
if relation is None:
|
|
852
|
+
return None
|
|
853
|
+
|
|
854
|
+
# External Table Column lookups
|
|
855
|
+
# we have to prepend the column symbol to the args
|
|
856
|
+
root_type = l.relation.fields[0].type
|
|
857
|
+
if isinstance(root_type, mm.Table):
|
|
858
|
+
self.used_tables.add(root_type)
|
|
859
|
+
is_table = l.relation == root_type
|
|
860
|
+
if is_table or l.relation in root_type.columns:
|
|
861
|
+
sym = "METADATA$KEY" if is_table else l.relation.name
|
|
862
|
+
args = (v0.Literal(type=v0_types.Symbol, value=sym), *args)
|
|
863
|
+
|
|
864
|
+
# Specific rewrites
|
|
865
|
+
rewrite = self.rewrite_lookup(l, parent, ctx)
|
|
866
|
+
if rewrite is None:
|
|
867
|
+
# General translation
|
|
868
|
+
rewrite = v0.Lookup(
|
|
869
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
870
|
+
relation=relation, # type: ignore
|
|
871
|
+
args=args,
|
|
872
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
873
|
+
)
|
|
874
|
+
|
|
875
|
+
return rewrite
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
def translate_update(self, u: mm.Update, parent, ctx) -> v0.Update|v0.Output|None:
|
|
879
|
+
if isinstance(u.relation, mm.Table):
|
|
880
|
+
# ignore updates to tables for now
|
|
881
|
+
return None
|
|
882
|
+
|
|
883
|
+
if is_output_update(u):
|
|
884
|
+
# this is an output, the last arg is the value for the output column, the other
|
|
885
|
+
# args are part of the key
|
|
886
|
+
|
|
887
|
+
# get the list of key vars created during construction
|
|
888
|
+
keys = list(self.key_map[u.args[0]]) # type: ignore
|
|
889
|
+
# if there are no keys in the key map, this is a constructor of output without
|
|
890
|
+
# keys; we still need to remove the output from the args, so count is 1
|
|
891
|
+
arg_count = len(keys) if keys else 1
|
|
892
|
+
# append any other args used for the key
|
|
893
|
+
for arg in u.args[arg_count:-1]:
|
|
894
|
+
x = self.translate_value(arg, u, ctx)
|
|
895
|
+
keys.append(x) # type: ignore
|
|
896
|
+
if any(anno.relation is b.core["output_value_is_key"] for anno in u.annotations):
|
|
897
|
+
# if the output_value_is_key annotation is present, add the output value to the keys
|
|
898
|
+
keys.append(self.translate_value(u.args[-1], u, ctx)) # type: ignore
|
|
899
|
+
|
|
900
|
+
# there will be a single alias here, the output column
|
|
901
|
+
aliases = ordered_set((u.relation.name, self.translate_value(u.args[-1], u, ctx))).frozen()
|
|
902
|
+
|
|
903
|
+
out = v0.Output(
|
|
904
|
+
engine=self.translate_reasoner(u.reasoner, u, Context.MODEL),
|
|
905
|
+
keys=frozen(*keys), # type: ignore
|
|
906
|
+
aliases=aliases,
|
|
907
|
+
annotations=self.translate_frozen(u.annotations, u, ctx) # type: ignore
|
|
908
|
+
)
|
|
909
|
+
table = u.relation.fields[0].type
|
|
910
|
+
if isinstance(table, mm.Table) and not table.uri.startswith("dataframe://"):
|
|
911
|
+
self.exports.add(out)
|
|
912
|
+
return out
|
|
913
|
+
else:
|
|
914
|
+
relation, args = self._resolve_reading(u, ctx)
|
|
915
|
+
|
|
916
|
+
return v0.Update(
|
|
917
|
+
engine=self.translate_reasoner(u.reasoner, u, Context.MODEL),
|
|
918
|
+
relation=relation, # type: ignore
|
|
919
|
+
args=args,
|
|
920
|
+
effect=self.translate_effect(u.effect, u, ctx),
|
|
921
|
+
annotations=self.translate_frozen(u.annotations, u, ctx) # type: ignore
|
|
922
|
+
)
|
|
923
|
+
|
|
924
|
+
def _resolve_reading(self, task: mm.Lookup|mm.Update, ctx):
|
|
925
|
+
relation = self.translate_node(task.relation, task, ctx)
|
|
926
|
+
args = tuple(self.translate_value(arg, task, ctx) for arg in task.args)
|
|
927
|
+
if isinstance(relation, seq):
|
|
928
|
+
# Updates should always write to the root so that the reading maintenance rules
|
|
929
|
+
# can populate the other readings
|
|
930
|
+
if task.reading_hint is not None and isinstance(task, mm.Lookup):
|
|
931
|
+
relation = relation[task.relation.readings.index(task.reading_hint)]
|
|
932
|
+
args = tuple([args[i] for i in task.reading_hint.field_order])
|
|
933
|
+
else:
|
|
934
|
+
relation = relation[0]
|
|
935
|
+
|
|
936
|
+
return relation, args
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
def translate_aggregate(self, a: mm.Aggregate, parent, ctx) -> v0.Aggregate:
|
|
940
|
+
|
|
941
|
+
# hoist the return variables (those that are not inputs to the aggregation)
|
|
942
|
+
return_args = []
|
|
943
|
+
for field, arg in zip(a.aggregation.fields, a.args):
|
|
944
|
+
if not field.input:
|
|
945
|
+
return_args.append(arg)
|
|
946
|
+
hoisted=self.translate_seq(return_args, a, ctx)
|
|
947
|
+
|
|
948
|
+
# body must contain the aggregate body plus the aggregate itself
|
|
949
|
+
body = self.translate_node(a.body, a, ctx)
|
|
950
|
+
body = list(body.body if isinstance(body, v0.Logical) else [body])
|
|
951
|
+
|
|
952
|
+
# construct the aggregate node
|
|
953
|
+
engine = self.translate_reasoner(a.reasoner, a, Context.MODEL)
|
|
954
|
+
aggregation = self.translate_node(a.aggregation, a, ctx)
|
|
955
|
+
projection = self.translate_seq(a.projection, a, ctx)
|
|
956
|
+
group = self.translate_seq(a.group, a, ctx)
|
|
957
|
+
args = tuple(self.translate_value(arg, a, ctx) for arg in a.args)
|
|
958
|
+
annotations = self.translate_frozen(a.annotations, a, ctx)
|
|
959
|
+
|
|
960
|
+
v0_agg = None
|
|
961
|
+
if a.aggregation == b.aggregates.rank:
|
|
962
|
+
assert isinstance(args[0], tuple)
|
|
963
|
+
assert isinstance(args[1], tuple)
|
|
964
|
+
v0_agg = v0.Rank(engine, projection, group, args[0], tuple(l.value for l in args[1]), args[-1], 0, annotations,) # type: ignore
|
|
965
|
+
elif a.aggregation == b.aggregates.limit:
|
|
966
|
+
assert isinstance(args[0], v0.Literal)
|
|
967
|
+
assert isinstance(args[1], tuple)
|
|
968
|
+
assert isinstance(args[2], tuple)
|
|
969
|
+
result = v0.Var(type=v0_types.Int64, name="limit_result")
|
|
970
|
+
v0_agg = v0.Rank(engine, projection, group, args[1], tuple(l.value for l in args[2]), result, args[0].value, annotations,) # type: ignore
|
|
971
|
+
else:
|
|
972
|
+
v0_agg = v0.Aggregate(engine, aggregation, projection, group, args, annotations) # type: ignore
|
|
973
|
+
|
|
974
|
+
body.append(v0_agg)
|
|
975
|
+
return v0.Logical(
|
|
976
|
+
engine=None,
|
|
977
|
+
hoisted=hoisted, # type: ignore
|
|
978
|
+
body=tuple(body) # type: ignore
|
|
979
|
+
)
|
|
980
|
+
|
|
981
|
+
def translate_construct(self, c: mm.Construct, parent, ctx) -> v0.Construct|None:
|
|
982
|
+
if isinstance(c.id_var.type, mm.Table):
|
|
983
|
+
# we are constructing the key for an output. If there are no values, there is no
|
|
984
|
+
# key in v0, so we can just ignore this
|
|
985
|
+
if not c.values:
|
|
986
|
+
self.key_map[c.id_var] = []
|
|
987
|
+
return None
|
|
988
|
+
# now create a new v0 var to represent the hashed key, record that this key is
|
|
989
|
+
# to be used by updates, and generate the constructor
|
|
990
|
+
v = v0.Var(type=v0_types.Hash, name=c.id_var.name)
|
|
991
|
+
self.key_map[c.id_var] = [v]
|
|
992
|
+
values = [v0_types.Hash]
|
|
993
|
+
values.extend(self.translate_seq(c.values, c, ctx)) # type: ignore
|
|
994
|
+
return v0.Construct(
|
|
995
|
+
engine=self.translate_reasoner(c.reasoner, c, Context.MODEL),
|
|
996
|
+
values=tuple(values), # type: ignore
|
|
997
|
+
id_var=v,
|
|
998
|
+
annotations=self.translate_frozen(c.annotations, c, ctx) # type: ignore
|
|
999
|
+
)
|
|
1000
|
+
return v0.Construct(
|
|
1001
|
+
engine=self.translate_reasoner(c.reasoner, c, Context.MODEL),
|
|
1002
|
+
values=self.translate_seq(c.values, c, ctx), # type: ignore
|
|
1003
|
+
id_var=self.translate_node(c.id_var, c, ctx), # type: ignore
|
|
1004
|
+
annotations=self.translate_frozen(c.annotations, c, ctx) # type: ignore
|
|
1005
|
+
)
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
def translate_data(self, d: mm.Data, parent, ctx):
|
|
1009
|
+
if isinstance(parent, mm.Field) or isinstance(parent, mm.Var):
|
|
1010
|
+
return v0_types.Int128
|
|
1011
|
+
|
|
1012
|
+
# -----------------------------------------------------------------------------
|
|
1013
|
+
# Model
|
|
1014
|
+
# -----------------------------------------------------------------------------
|
|
1015
|
+
|
|
1016
|
+
def translate_model(self, source_model: mm.Model, parent=None, ctx=None) -> v0.Model:
|
|
1017
|
+
try:
|
|
1018
|
+
# first analyze the model to compute variables that need to be hoisted
|
|
1019
|
+
self.hoister.analyze(source_model)
|
|
1020
|
+
|
|
1021
|
+
self.relations_by_name = defaultdict(list)
|
|
1022
|
+
for r in source_model.relations:
|
|
1023
|
+
self.relations_by_name[r.name].append(r)
|
|
1024
|
+
|
|
1025
|
+
# translate root first as it may create relations from types (e.g. concept populations)
|
|
1026
|
+
root = self.translate_node(source_model.root, source_model, Context.TASK)
|
|
1027
|
+
|
|
1028
|
+
# translate all declared relations
|
|
1029
|
+
relations:OrderedSet[v0.Relation] = ordered_set(*self.translate_seq(source_model.relations, source_model, Context.MODEL)) # type: ignore
|
|
1030
|
+
# add relations created during task translation
|
|
1031
|
+
relations.update(filter_by_type(self.task_map.values(), v0.Relation)) # type: ignore
|
|
1032
|
+
# v0 needs all overloads also added to the model
|
|
1033
|
+
for r in list(relations):
|
|
1034
|
+
relations.update(r.overloads) # type: ignore
|
|
1035
|
+
|
|
1036
|
+
# if there are reading maintenance rules, add them as well
|
|
1037
|
+
if self.maintenance_rules:
|
|
1038
|
+
root = v0.Logical(
|
|
1039
|
+
engine=None,
|
|
1040
|
+
hoisted=(),
|
|
1041
|
+
body=(
|
|
1042
|
+
root, # type: ignore
|
|
1043
|
+
*self.maintenance_rules
|
|
1044
|
+
),
|
|
1045
|
+
annotations=frozen()
|
|
1046
|
+
)
|
|
1047
|
+
engines=self.translate_frozen(source_model.reasoners, source_model, Context.MODEL) # type: ignore
|
|
1048
|
+
types=self.translate_frozen(source_model.types, source_model, Context.MODEL) # type: ignore
|
|
1049
|
+
|
|
1050
|
+
return v0.Model(
|
|
1051
|
+
engines=engines, # type: ignore
|
|
1052
|
+
relations=relations.frozen(), # type: ignore
|
|
1053
|
+
types=types, # type: ignore
|
|
1054
|
+
root=root # type: ignore
|
|
1055
|
+
)
|
|
1056
|
+
finally:
|
|
1057
|
+
self.hoister.clear()
|
|
1058
|
+
|
|
1059
|
+
# -----------------------------------------------------------------------------
|
|
1060
|
+
# Translate query
|
|
1061
|
+
# -----------------------------------------------------------------------------
|
|
1062
|
+
|
|
1063
|
+
def translate_query(self, source_query: mm.Task) -> v0.Logical:
|
|
1064
|
+
try:
|
|
1065
|
+
# first analyze the model to compute variables that need to be hoisted
|
|
1066
|
+
self.hoister.analyze_task(source_query)
|
|
1067
|
+
|
|
1068
|
+
# translate the query logical
|
|
1069
|
+
return self.translate_node(source_query, source_query, Context.TASK) # type: ignore
|
|
1070
|
+
finally:
|
|
1071
|
+
self.hoister.clear()
|
|
1072
|
+
|
|
1073
|
+
# -----------------------------------------------------------------------------
|
|
1074
|
+
# Library-specific rewrites
|
|
1075
|
+
# -----------------------------------------------------------------------------
|
|
1076
|
+
|
|
1077
|
+
def adjust_index(self, l: mm.Lookup, indices: list[int], ctx, args=None, no_outputs=False):
|
|
1078
|
+
""" Rewrite the lookup such that the args at `indices` are adjusted to convert from
|
|
1079
|
+
0-based indexing (as in the mm) to 1-based indexing (as in v0's backend).
|
|
1080
|
+
|
|
1081
|
+
If the field at the given index is input, we increment the arg by 1 before passing
|
|
1082
|
+
it to the lookup. If the field is output, we create a tmp var to hold the result
|
|
1083
|
+
of the lookup, and then create a subsequent task to decrement the tmp var by 1.
|
|
1084
|
+
|
|
1085
|
+
`args` can be used to provide a different set of args than l.args, in case they need
|
|
1086
|
+
reordering (e.g. strings.split).
|
|
1087
|
+
"""
|
|
1088
|
+
if args is None:
|
|
1089
|
+
args = l.args
|
|
1090
|
+
# vars to hold the result from the v0 lookup
|
|
1091
|
+
tmps = {}
|
|
1092
|
+
for i in indices:
|
|
1093
|
+
index_type = l.relation.fields[i].type
|
|
1094
|
+
tmps[i] = mm.Var(type=index_type, name=f"tmp")
|
|
1095
|
+
# insert tmp at index
|
|
1096
|
+
replaced_args = []
|
|
1097
|
+
for i, arg in enumerate(args):
|
|
1098
|
+
if i in indices:
|
|
1099
|
+
replaced_args.append(tmps[i])
|
|
1100
|
+
else:
|
|
1101
|
+
replaced_args.append(arg)
|
|
1102
|
+
# translate the lookup
|
|
1103
|
+
lookup = v0.Lookup(
|
|
1104
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
1105
|
+
relation=self.translate_node(l.relation), # type: ignore
|
|
1106
|
+
args=tuple(self.translate_value(arg, l, ctx) for arg in replaced_args),
|
|
1107
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
1108
|
+
)
|
|
1109
|
+
# subtract 1 from the index to convert from 1-based to 0-based
|
|
1110
|
+
tasks = []
|
|
1111
|
+
for index in indices:
|
|
1112
|
+
arg = args[index]
|
|
1113
|
+
if isinstance(arg, mm.Literal):
|
|
1114
|
+
if l.relation.fields[index].input:
|
|
1115
|
+
new = mm.Literal(arg.type, arg.value + 1) # type: ignore
|
|
1116
|
+
else:
|
|
1117
|
+
new = mm.Literal(arg.type, arg.value + 1) # type: ignore
|
|
1118
|
+
tasks.append(v0.Lookup(
|
|
1119
|
+
engine=None,
|
|
1120
|
+
relation=v0_builtins.eq, # type: ignore
|
|
1121
|
+
args=(
|
|
1122
|
+
self.translate_value(tmps[index], lookup, ctx),
|
|
1123
|
+
self.translate_value(new, lookup, ctx),
|
|
1124
|
+
)
|
|
1125
|
+
))
|
|
1126
|
+
elif l.relation.fields[index].input:
|
|
1127
|
+
tasks.append(v0.Lookup(
|
|
1128
|
+
engine=None,
|
|
1129
|
+
relation=v0_builtins.plus, # type: ignore
|
|
1130
|
+
args=(
|
|
1131
|
+
self.translate_value(args[index], lookup, ctx),
|
|
1132
|
+
v0.Literal(v0_types.Int128, 1),
|
|
1133
|
+
self.translate_value(tmps[index], lookup, ctx),
|
|
1134
|
+
),
|
|
1135
|
+
)
|
|
1136
|
+
)
|
|
1137
|
+
else:
|
|
1138
|
+
tasks.append(v0.Lookup(
|
|
1139
|
+
engine=None,
|
|
1140
|
+
relation=v0_builtins.minus, # type: ignore
|
|
1141
|
+
args=(
|
|
1142
|
+
self.translate_value(tmps[index], lookup, ctx),
|
|
1143
|
+
v0.Literal(v0_types.Int128, 1),
|
|
1144
|
+
self.translate_value(args[index], lookup, ctx),
|
|
1145
|
+
),
|
|
1146
|
+
)
|
|
1147
|
+
)
|
|
1148
|
+
# do casts
|
|
1149
|
+
tasks.extend(self.cast(lookup, ctx, no_outputs=no_outputs))
|
|
1150
|
+
|
|
1151
|
+
return tasks
|
|
1152
|
+
|
|
1153
|
+
def decrement(self, l: mm.Lookup, index: int, ctx):
|
|
1154
|
+
""" Rewrite the lookup such that the arg at `index` is decremented by 1 before the
|
|
1155
|
+
lookup. """
|
|
1156
|
+
x = l.args[index]
|
|
1157
|
+
if isinstance(x, mm.Literal):
|
|
1158
|
+
# if the arg is a literal, just decrement the literal directly
|
|
1159
|
+
new_literal = mm.Literal(type=x.type, value=x.value - 1) # type: ignore
|
|
1160
|
+
return v0.Lookup(
|
|
1161
|
+
engine=None,
|
|
1162
|
+
relation=self.translate_node(l.relation), # type: ignore
|
|
1163
|
+
args=tuple(self.translate_value(arg, l, ctx) if i != index else self.translate_value(new_literal, l, ctx) for i, arg in enumerate(l.args)),
|
|
1164
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
1165
|
+
)
|
|
1166
|
+
|
|
1167
|
+
# arg is not a literal, so we need to create a tmp var to store the decremented value
|
|
1168
|
+
tmp = self.translate_value(mm.Var(type=b.core.Number, name="tmp"), l, ctx)
|
|
1169
|
+
# lookup(..., tmp, ...)
|
|
1170
|
+
new = v0.Lookup(
|
|
1171
|
+
engine=None,
|
|
1172
|
+
relation=self.translate_node(l.relation), # type: ignore
|
|
1173
|
+
args=tuple(self.translate_value(arg, l, ctx) if i != index else tmp for i, arg in enumerate(l.args)),
|
|
1174
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
1175
|
+
)
|
|
1176
|
+
casted = self.cast(new, ctx)
|
|
1177
|
+
return (
|
|
1178
|
+
# tmp = l.args[index] - 1
|
|
1179
|
+
v0.Lookup(
|
|
1180
|
+
engine=None,
|
|
1181
|
+
relation=v0_builtins.minus, # type: ignore
|
|
1182
|
+
args=(
|
|
1183
|
+
self.translate_value(l.args[index], l, ctx),
|
|
1184
|
+
v0.Literal(v0_types.Int128, 1),
|
|
1185
|
+
tmp,
|
|
1186
|
+
),
|
|
1187
|
+
),
|
|
1188
|
+
*casted
|
|
1189
|
+
)
|
|
1190
|
+
|
|
1191
|
+
def cast(self, l: v0.Lookup, ctx, no_outputs=False):
|
|
1192
|
+
# note that everything here is in v0
|
|
1193
|
+
inputs = []
|
|
1194
|
+
outputs = []
|
|
1195
|
+
args = []
|
|
1196
|
+
fields = l.relation.fields
|
|
1197
|
+
# if there are overloads, we need to cast based on the most compatible overload
|
|
1198
|
+
if l.relation.overloads:
|
|
1199
|
+
inf = float("inf")
|
|
1200
|
+
min_cost = inf
|
|
1201
|
+
for overload in l.relation.overloads:
|
|
1202
|
+
total = 0
|
|
1203
|
+
for arg, field in zip(l.args, overload.fields):
|
|
1204
|
+
if v0_typer.to_type(arg) != field.type:
|
|
1205
|
+
total += 1
|
|
1206
|
+
if total < min_cost:
|
|
1207
|
+
min_cost = total
|
|
1208
|
+
fields = overload.fields
|
|
1209
|
+
|
|
1210
|
+
for arg, field in zip(l.args, fields):
|
|
1211
|
+
target_type = field.type
|
|
1212
|
+
if target_type is None or not isinstance(arg, (v0.Var, v0.Literal)) or arg.type == target_type:
|
|
1213
|
+
args.append(arg)
|
|
1214
|
+
continue
|
|
1215
|
+
if field.input:
|
|
1216
|
+
cast_var = v0.Var(type=target_type, name="cast_var")
|
|
1217
|
+
args.append(cast_var)
|
|
1218
|
+
inputs.append(v0.Lookup(
|
|
1219
|
+
engine=None,
|
|
1220
|
+
relation=v0_builtins.cast, # type: ignore
|
|
1221
|
+
args=(target_type, arg, cast_var),
|
|
1222
|
+
))
|
|
1223
|
+
elif not no_outputs:
|
|
1224
|
+
cast_var = v0.Var(type=target_type, name="cast_var")
|
|
1225
|
+
args.append(cast_var)
|
|
1226
|
+
outputs.append(v0.Lookup(
|
|
1227
|
+
engine=None,
|
|
1228
|
+
relation=v0_builtins.cast, # type: ignore
|
|
1229
|
+
args=(arg.type, cast_var, arg),
|
|
1230
|
+
))
|
|
1231
|
+
else:
|
|
1232
|
+
# This is ridiculous, but there are cases where we need to force the type
|
|
1233
|
+
# of the var, but not through an actual cast operation. E.g. due to the way
|
|
1234
|
+
# the LQP stack handles dates.
|
|
1235
|
+
object.__setattr__(arg, 'type', target_type)
|
|
1236
|
+
args.append(arg)
|
|
1237
|
+
|
|
1238
|
+
lookup = v0.Lookup(
|
|
1239
|
+
engine=l.engine,
|
|
1240
|
+
relation=l.relation,
|
|
1241
|
+
args=tuple(args),
|
|
1242
|
+
annotations=l.annotations
|
|
1243
|
+
)
|
|
1244
|
+
if no_outputs:
|
|
1245
|
+
outputs = []
|
|
1246
|
+
return [*inputs, lookup, *outputs]
|
|
1247
|
+
|
|
1248
|
+
def rewrite_lookup(self, l: mm.Lookup, parent, ctx):
|
|
1249
|
+
""" Special cases for v1 builtins that either have some different shape in v0 or
|
|
1250
|
+
do not exist as a primitive in the engine, so we want to compose the result so that
|
|
1251
|
+
LQP works. Return None if no rewrite is needed.
|
|
1252
|
+
|
|
1253
|
+
Note that this type of adjustment will need to be made by emitters anyways, so we
|
|
1254
|
+
will want to have a good API for them. But in that case, they should do
|
|
1255
|
+
transformations still in the mm, whereas this is doing it during translation to v0.
|
|
1256
|
+
"""
|
|
1257
|
+
|
|
1258
|
+
# -----------------------------------------------------------------------------
|
|
1259
|
+
# Common
|
|
1260
|
+
# -----------------------------------------------------------------------------
|
|
1261
|
+
if l.relation == b.common.range:
|
|
1262
|
+
# python/PyRel range has inclusive start but exclusive stop, whereas LQP/Rel has
|
|
1263
|
+
# inclusive stop, so we have to decrement the stop index by 1
|
|
1264
|
+
# tmp, lookup = self.decrement(l, 1, ctx)
|
|
1265
|
+
# return [tmp] + self.cast(lookup, [v0_types.Int64, v0_types.Int64, v0_types.Int64, v0_types.Int64], ctx)
|
|
1266
|
+
return self.decrement(l, 1, ctx)
|
|
1267
|
+
|
|
1268
|
+
elif l.relation == b.core.cast:
|
|
1269
|
+
return v0.Lookup(
|
|
1270
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.TASK),
|
|
1271
|
+
relation=v0_builtins.builtin_relations_by_name["cast"], # type: ignore
|
|
1272
|
+
args=(
|
|
1273
|
+
self.translate_value(l.args[0], l, Context.MODEL),
|
|
1274
|
+
self.translate_value(l.args[1], l, Context.TASK),
|
|
1275
|
+
self.translate_value(l.args[2], l, Context.TASK)
|
|
1276
|
+
),
|
|
1277
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
1278
|
+
)
|
|
1279
|
+
|
|
1280
|
+
# -----------------------------------------------------------------------------
|
|
1281
|
+
# Strings
|
|
1282
|
+
# -----------------------------------------------------------------------------
|
|
1283
|
+
|
|
1284
|
+
elif l.relation == b.strings.len:
|
|
1285
|
+
lookup = v0.Lookup(
|
|
1286
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
1287
|
+
relation=v0_builtins.builtin_relations_by_name["num_chars"], # type: ignore
|
|
1288
|
+
args=(
|
|
1289
|
+
self.translate_value(l.args[0], l, ctx),
|
|
1290
|
+
self.translate_value(l.args[1], l, ctx),
|
|
1291
|
+
),
|
|
1292
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
1293
|
+
)
|
|
1294
|
+
return self.cast(lookup, ctx)
|
|
1295
|
+
|
|
1296
|
+
elif l.relation == b.strings.split:
|
|
1297
|
+
# swap first two args because that's how rel and v0 expect them
|
|
1298
|
+
args = l.args[1], l.args[0], l.args[2], l.args[3]
|
|
1299
|
+
return self.adjust_index(l, [2], ctx, args=args)
|
|
1300
|
+
|
|
1301
|
+
elif l.relation == b.strings.substring:
|
|
1302
|
+
return self.adjust_index(l, [1], ctx)
|
|
1303
|
+
|
|
1304
|
+
# -----------------------------------------------------------------------------
|
|
1305
|
+
# RE
|
|
1306
|
+
# -----------------------------------------------------------------------------
|
|
1307
|
+
elif l.relation == b.re.regex_match_all:
|
|
1308
|
+
return self.adjust_index(l, [2], ctx)
|
|
1309
|
+
|
|
1310
|
+
# -----------------------------------------------------------------------------
|
|
1311
|
+
# Math
|
|
1312
|
+
# -----------------------------------------------------------------------------
|
|
1313
|
+
elif l.relation == b.math.degrees:
|
|
1314
|
+
# degrees(radians, x) = /(radians, (pi/180.0), x)
|
|
1315
|
+
return v0.Lookup(
|
|
1316
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
1317
|
+
relation=v0_builtins.builtin_relations_by_name["/"], # type: ignore
|
|
1318
|
+
args=(
|
|
1319
|
+
self.translate_value(l.args[0], l, ctx),
|
|
1320
|
+
v0.Literal(v0_types.Float, pi / 180.0),
|
|
1321
|
+
self.translate_value(l.args[1], l, ctx)
|
|
1322
|
+
),
|
|
1323
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
1324
|
+
)
|
|
1325
|
+
elif l.relation == b.math.radians:
|
|
1326
|
+
# radians(degrees, x) = /(degrees, (180.0/pi), x)
|
|
1327
|
+
return v0.Lookup(
|
|
1328
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
1329
|
+
relation=v0_builtins.builtin_relations_by_name["/"], # type: ignore
|
|
1330
|
+
args=(
|
|
1331
|
+
self.translate_value(l.args[0], l, ctx),
|
|
1332
|
+
v0.Literal(v0_types.Float, 180.0 / pi),
|
|
1333
|
+
self.translate_value(l.args[1], l, ctx)
|
|
1334
|
+
),
|
|
1335
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
1336
|
+
)
|
|
1337
|
+
|
|
1338
|
+
# -----------------------------------------------------------------------------
|
|
1339
|
+
# Datetime
|
|
1340
|
+
# -----------------------------------------------------------------------------
|
|
1341
|
+
#
|
|
1342
|
+
# elif l.relation == b.datetime.date_range:
|
|
1343
|
+
# return self.rewrite_date_range(l, parent, ctx)
|
|
1344
|
+
# elif l.relation == b.datetime.datetime_range:
|
|
1345
|
+
# pass
|
|
1346
|
+
|
|
1347
|
+
elif l.relation == b.datetime.date_add:
|
|
1348
|
+
return v0.Lookup(
|
|
1349
|
+
engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
|
|
1350
|
+
relation=self.translate_relation(l.relation, l, ctx), # type: ignore
|
|
1351
|
+
args=self.translate_seq(l.args, l, ctx), # type: ignore
|
|
1352
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
1353
|
+
)
|
|
1354
|
+
|
|
1355
|
+
if b.datetime[l.relation.name] is l.relation:
|
|
1356
|
+
return self.adjust_index(l, [], ctx, no_outputs=True)
|
|
1357
|
+
|
|
1358
|
+
v0_rel = self.translate_node(l.relation, l, ctx)
|
|
1359
|
+
if isinstance(v0_rel, v0.Relation) and any(f.type == v0_types.Int64 for f in v0_rel.fields):
|
|
1360
|
+
return self.adjust_index(l, [], ctx)
|
|
1361
|
+
|
|
1362
|
+
return None
|
|
1363
|
+
|
|
1364
|
+
|
|
1365
|
+
# TODO - Currently implemented in the std.datetime itself.
|
|
1366
|
+
# def rewrite_date_range(self, l: mm.Lookup, parent, ctx: Context):
|
|
1367
|
+
# start, end, freq, date = l.args
|
|
1368
|
+
# result = []
|
|
1369
|
+
|
|
1370
|
+
# range_end = num_days = mm.Var(type=b.core.Number, name="num_days")
|
|
1371
|
+
# result.append(mm.Lookup(b.datetime.dates_period_days, (start, end, num_days)))
|
|
1372
|
+
|
|
1373
|
+
# assert isinstance(freq, mm.Literal) and isinstance(freq.value, str)
|
|
1374
|
+
# if freq.value in ["W", "M", "Y"]:
|
|
1375
|
+
# range_end = mm.Var(type=b.core.Number, name="range_end")
|
|
1376
|
+
# x = mm.Var(type=b.core.Number, name="x")
|
|
1377
|
+
# result.append(mm.Lookup(b.core.mul, (num_days, mm.Literal(b.core.Float, _days[freq.value]), x)))
|
|
1378
|
+
# result.append(mm.Lookup(b.math.ceil, (x, range_end)))
|
|
1379
|
+
|
|
1380
|
+
# # date_range is inclusive. add 1 since std.range is exclusive
|
|
1381
|
+
# tmp = mm.Var(type=b.core.Number, name="tmp")
|
|
1382
|
+
# result.append(mm.Lookup(b.core["+"], (range_end, mm.Literal(b.core.Number, 1), tmp)))
|
|
1383
|
+
# ix = mm.Var(type=b.core.Number, name="ix")
|
|
1384
|
+
# result.append(mm.Lookup(b.common.range, (mm.Literal(b.core.Number, 0), tmp, mm.Literal(b.core.Number, 1), ix)))
|
|
1385
|
+
|
|
1386
|
+
# tmp2 = mm.Var(type=b.core.Number, name="tmp2")
|
|
1387
|
+
# result.append(mm.Lookup(_periods[freq.value], (ix, tmp2)))
|
|
1388
|
+
# result.append(mm.Lookup(b.datetime.date_add, (start, tmp2, date)))
|
|
1389
|
+
|
|
1390
|
+
# result.append(mm.Lookup(b.core[">="], (end, date)))
|
|
1391
|
+
|
|
1392
|
+
# return self.translate_node(mm.Logical(
|
|
1393
|
+
# body=tuple(result)
|
|
1394
|
+
# ))
|