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