relationalai 0.13.5__py3-none-any.whl → 1.0.0a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- relationalai/__init__.py +1 -256
- relationalai/config/__init__.py +56 -0
- relationalai/config/config.py +289 -0
- relationalai/config/config_fields.py +86 -0
- relationalai/config/connections/__init__.py +46 -0
- relationalai/config/connections/base.py +23 -0
- relationalai/config/connections/duckdb.py +29 -0
- relationalai/config/connections/snowflake.py +243 -0
- relationalai/config/external/__init__.py +17 -0
- relationalai/config/external/dbt_converter.py +101 -0
- relationalai/config/external/dbt_models.py +93 -0
- relationalai/config/external/snowflake_converter.py +41 -0
- relationalai/config/external/snowflake_models.py +85 -0
- relationalai/config/external/utils.py +19 -0
- relationalai/config/shims.py +1 -0
- relationalai/semantics/__init__.py +146 -22
- relationalai/semantics/backends/lqp/annotations.py +11 -0
- relationalai/semantics/backends/sql/sql_compiler.py +327 -0
- relationalai/semantics/frontend/base.py +1716 -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 -772
- 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 +1186 -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 +101 -46
- relationalai/shims/executor.py +161 -0
- relationalai/shims/helpers.py +126 -0
- relationalai/shims/hoister.py +221 -0
- relationalai/shims/mm2v0.py +1324 -0
- relationalai/tools/cli/__init__.py +6 -0
- relationalai/tools/cli/cli.py +90 -0
- relationalai/tools/cli/components/__init__.py +5 -0
- relationalai/tools/cli/components/progress_reader.py +1524 -0
- relationalai/tools/cli/components/utils.py +58 -0
- relationalai/tools/cli/config_template.py +45 -0
- relationalai/tools/cli/dev.py +19 -0
- relationalai/tools/debugger.py +289 -183
- relationalai/tools/typer_debugger.py +93 -0
- relationalai/util/dataclasses.py +43 -0
- relationalai/util/docutils.py +40 -0
- relationalai/util/error.py +199 -0
- relationalai/util/format.py +48 -109
- relationalai/util/naming.py +145 -0
- relationalai/util/python.py +35 -0
- relationalai/util/runtime.py +156 -0
- relationalai/util/schema.py +197 -0
- relationalai/util/source.py +185 -0
- relationalai/util/structures.py +163 -0
- relationalai/util/tracing.py +261 -0
- relationalai-1.0.0a1.dist-info/METADATA +44 -0
- relationalai-1.0.0a1.dist-info/RECORD +489 -0
- relationalai-1.0.0a1.dist-info/WHEEL +5 -0
- relationalai-1.0.0a1.dist-info/entry_points.txt +3 -0
- relationalai-1.0.0a1.dist-info/top_level.txt +2 -0
- v0/relationalai/__init__.py +216 -0
- v0/relationalai/clients/__init__.py +5 -0
- v0/relationalai/clients/azure.py +477 -0
- v0/relationalai/clients/client.py +912 -0
- v0/relationalai/clients/config.py +673 -0
- v0/relationalai/clients/direct_access_client.py +118 -0
- v0/relationalai/clients/hash_util.py +31 -0
- v0/relationalai/clients/local.py +571 -0
- v0/relationalai/clients/profile_polling.py +73 -0
- v0/relationalai/clients/result_helpers.py +420 -0
- v0/relationalai/clients/snowflake.py +3869 -0
- v0/relationalai/clients/types.py +113 -0
- v0/relationalai/clients/use_index_poller.py +980 -0
- v0/relationalai/clients/util.py +356 -0
- v0/relationalai/debugging.py +389 -0
- v0/relationalai/dsl.py +1749 -0
- v0/relationalai/early_access/builder/__init__.py +30 -0
- v0/relationalai/early_access/builder/builder/__init__.py +35 -0
- v0/relationalai/early_access/builder/snowflake/__init__.py +12 -0
- v0/relationalai/early_access/builder/std/__init__.py +25 -0
- v0/relationalai/early_access/builder/std/decimals/__init__.py +12 -0
- v0/relationalai/early_access/builder/std/integers/__init__.py +12 -0
- v0/relationalai/early_access/builder/std/math/__init__.py +12 -0
- v0/relationalai/early_access/builder/std/strings/__init__.py +14 -0
- v0/relationalai/early_access/devtools/__init__.py +12 -0
- v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
- v0/relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
- v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
- v0/relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
- v0/relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
- v0/relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
- v0/relationalai/early_access/dsl/bindings/common.py +402 -0
- v0/relationalai/early_access/dsl/bindings/csv.py +170 -0
- v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
- v0/relationalai/early_access/dsl/bindings/snowflake.py +64 -0
- v0/relationalai/early_access/dsl/codegen/binder.py +411 -0
- v0/relationalai/early_access/dsl/codegen/common.py +79 -0
- v0/relationalai/early_access/dsl/codegen/helpers.py +23 -0
- v0/relationalai/early_access/dsl/codegen/relations.py +700 -0
- v0/relationalai/early_access/dsl/codegen/weaver.py +417 -0
- v0/relationalai/early_access/dsl/core/builders/__init__.py +47 -0
- v0/relationalai/early_access/dsl/core/builders/logic.py +19 -0
- v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
- v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
- v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
- v0/relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
- v0/relationalai/early_access/dsl/core/context.py +13 -0
- v0/relationalai/early_access/dsl/core/cset.py +132 -0
- v0/relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
- v0/relationalai/early_access/dsl/core/exprs/relational.py +18 -0
- v0/relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
- v0/relationalai/early_access/dsl/core/instances.py +44 -0
- v0/relationalai/early_access/dsl/core/logic/__init__.py +193 -0
- v0/relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
- v0/relationalai/early_access/dsl/core/logic/exists.py +223 -0
- v0/relationalai/early_access/dsl/core/logic/helper.py +163 -0
- v0/relationalai/early_access/dsl/core/namespaces.py +32 -0
- v0/relationalai/early_access/dsl/core/relations.py +276 -0
- v0/relationalai/early_access/dsl/core/rules.py +112 -0
- v0/relationalai/early_access/dsl/core/std/__init__.py +45 -0
- v0/relationalai/early_access/dsl/core/temporal/recall.py +6 -0
- v0/relationalai/early_access/dsl/core/types/__init__.py +270 -0
- v0/relationalai/early_access/dsl/core/types/concepts.py +128 -0
- v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
- v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
- v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
- v0/relationalai/early_access/dsl/core/types/standard.py +92 -0
- v0/relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
- v0/relationalai/early_access/dsl/core/types/variables.py +203 -0
- v0/relationalai/early_access/dsl/ir/compiler.py +318 -0
- v0/relationalai/early_access/dsl/ir/executor.py +260 -0
- v0/relationalai/early_access/dsl/ontologies/constraints.py +88 -0
- v0/relationalai/early_access/dsl/ontologies/export.py +30 -0
- v0/relationalai/early_access/dsl/ontologies/models.py +453 -0
- v0/relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
- v0/relationalai/early_access/dsl/ontologies/readings.py +60 -0
- v0/relationalai/early_access/dsl/ontologies/relationships.py +322 -0
- v0/relationalai/early_access/dsl/ontologies/roles.py +87 -0
- v0/relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
- v0/relationalai/early_access/dsl/orm/constraints.py +438 -0
- v0/relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
- v0/relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
- v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
- v0/relationalai/early_access/dsl/orm/measures/measures.py +299 -0
- v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
- v0/relationalai/early_access/dsl/orm/models.py +256 -0
- v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
- v0/relationalai/early_access/dsl/orm/printer.py +469 -0
- v0/relationalai/early_access/dsl/orm/reasoners.py +480 -0
- v0/relationalai/early_access/dsl/orm/relations.py +19 -0
- v0/relationalai/early_access/dsl/orm/relationships.py +251 -0
- v0/relationalai/early_access/dsl/orm/types.py +42 -0
- v0/relationalai/early_access/dsl/orm/utils.py +79 -0
- v0/relationalai/early_access/dsl/orm/verb.py +204 -0
- v0/relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
- v0/relationalai/early_access/dsl/relations.py +170 -0
- v0/relationalai/early_access/dsl/rulesets.py +69 -0
- v0/relationalai/early_access/dsl/schemas/__init__.py +450 -0
- v0/relationalai/early_access/dsl/schemas/builder.py +48 -0
- v0/relationalai/early_access/dsl/schemas/comp_names.py +51 -0
- v0/relationalai/early_access/dsl/schemas/components.py +203 -0
- v0/relationalai/early_access/dsl/schemas/contexts.py +156 -0
- v0/relationalai/early_access/dsl/schemas/exprs.py +89 -0
- v0/relationalai/early_access/dsl/schemas/fragments.py +464 -0
- v0/relationalai/early_access/dsl/serialization.py +79 -0
- v0/relationalai/early_access/dsl/serialize/exporter.py +163 -0
- v0/relationalai/early_access/dsl/snow/api.py +104 -0
- v0/relationalai/early_access/dsl/snow/common.py +76 -0
- v0/relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
- v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
- v0/relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
- v0/relationalai/early_access/dsl/types/__init__.py +40 -0
- v0/relationalai/early_access/dsl/types/concepts.py +12 -0
- v0/relationalai/early_access/dsl/types/entities.py +135 -0
- v0/relationalai/early_access/dsl/types/values.py +17 -0
- v0/relationalai/early_access/dsl/utils.py +102 -0
- v0/relationalai/early_access/graphs/__init__.py +13 -0
- v0/relationalai/early_access/lqp/__init__.py +12 -0
- v0/relationalai/early_access/lqp/compiler/__init__.py +12 -0
- v0/relationalai/early_access/lqp/constructors/__init__.py +18 -0
- v0/relationalai/early_access/lqp/executor/__init__.py +12 -0
- v0/relationalai/early_access/lqp/ir/__init__.py +12 -0
- v0/relationalai/early_access/lqp/passes/__init__.py +12 -0
- v0/relationalai/early_access/lqp/pragmas/__init__.py +12 -0
- v0/relationalai/early_access/lqp/primitives/__init__.py +12 -0
- v0/relationalai/early_access/lqp/types/__init__.py +12 -0
- v0/relationalai/early_access/lqp/utils/__init__.py +12 -0
- v0/relationalai/early_access/lqp/validators/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/__init__.py +58 -0
- v0/relationalai/early_access/metamodel/builtins/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/compiler/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/dependency/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/factory/__init__.py +17 -0
- v0/relationalai/early_access/metamodel/helpers/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/ir/__init__.py +14 -0
- v0/relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
- v0/relationalai/early_access/metamodel/typer/__init__.py +3 -0
- v0/relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
- v0/relationalai/early_access/metamodel/types/__init__.py +15 -0
- v0/relationalai/early_access/metamodel/util/__init__.py +15 -0
- v0/relationalai/early_access/metamodel/visitor/__init__.py +12 -0
- v0/relationalai/early_access/rel/__init__.py +12 -0
- v0/relationalai/early_access/rel/executor/__init__.py +12 -0
- v0/relationalai/early_access/rel/rel_utils/__init__.py +12 -0
- v0/relationalai/early_access/rel/rewrite/__init__.py +7 -0
- v0/relationalai/early_access/solvers/__init__.py +19 -0
- v0/relationalai/early_access/sql/__init__.py +11 -0
- v0/relationalai/early_access/sql/executor/__init__.py +3 -0
- v0/relationalai/early_access/sql/rewrite/__init__.py +3 -0
- v0/relationalai/early_access/tests/logging/__init__.py +12 -0
- v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
- v0/relationalai/early_access/tests/utils/__init__.py +12 -0
- v0/relationalai/environments/__init__.py +35 -0
- v0/relationalai/environments/base.py +381 -0
- v0/relationalai/environments/colab.py +14 -0
- v0/relationalai/environments/generic.py +71 -0
- v0/relationalai/environments/ipython.py +68 -0
- v0/relationalai/environments/jupyter.py +9 -0
- v0/relationalai/environments/snowbook.py +169 -0
- v0/relationalai/errors.py +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/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/ir.py +124 -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/__init__.py +18 -0
- v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
- v0/relationalai/semantics/lqp/rewrite/cdc.py +216 -0
- v0/relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
- v0/relationalai/semantics/lqp/rewrite/extract_keys.py +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/ir.py +923 -0
- v0/relationalai/semantics/metamodel/rewrite/__init__.py +7 -0
- v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
- v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
- v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
- v0/relationalai/semantics/metamodel/rewrite/flatten.py +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/metamodel/util.py +505 -0
- v0/relationalai/semantics/metamodel/visitor.py +944 -0
- v0/relationalai/semantics/reasoners/__init__.py +10 -0
- v0/relationalai/semantics/reasoners/graph/__init__.py +37 -0
- v0/relationalai/semantics/reasoners/graph/core.py +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/__init__.py +0 -18
- relationalai/clients/client.py +0 -946
- relationalai/clients/config.py +0 -673
- relationalai/clients/direct_access_client.py +0 -118
- relationalai/clients/exec_txn_poller.py +0 -153
- relationalai/clients/hash_util.py +0 -31
- relationalai/clients/local.py +0 -594
- relationalai/clients/profile_polling.py +0 -73
- relationalai/clients/resources/__init__.py +0 -8
- relationalai/clients/resources/azure/azure.py +0 -502
- relationalai/clients/resources/snowflake/__init__.py +0 -20
- relationalai/clients/resources/snowflake/cli_resources.py +0 -98
- relationalai/clients/resources/snowflake/direct_access_resources.py +0 -739
- relationalai/clients/resources/snowflake/engine_service.py +0 -381
- relationalai/clients/resources/snowflake/engine_state_handlers.py +0 -315
- relationalai/clients/resources/snowflake/error_handlers.py +0 -240
- relationalai/clients/resources/snowflake/export_procedure.py.jinja +0 -249
- relationalai/clients/resources/snowflake/resources_factory.py +0 -99
- relationalai/clients/resources/snowflake/snowflake.py +0 -3193
- relationalai/clients/resources/snowflake/use_index_poller.py +0 -1019
- relationalai/clients/resources/snowflake/use_index_resources.py +0 -188
- relationalai/clients/resources/snowflake/util.py +0 -387
- relationalai/clients/result_helpers.py +0 -420
- relationalai/clients/types.py +0 -118
- relationalai/clients/util.py +0 -356
- relationalai/debugging.py +0 -389
- relationalai/dsl.py +0 -1749
- relationalai/early_access/builder/__init__.py +0 -30
- relationalai/early_access/builder/builder/__init__.py +0 -35
- relationalai/early_access/builder/snowflake/__init__.py +0 -12
- relationalai/early_access/builder/std/__init__.py +0 -25
- relationalai/early_access/builder/std/decimals/__init__.py +0 -12
- relationalai/early_access/builder/std/integers/__init__.py +0 -12
- relationalai/early_access/builder/std/math/__init__.py +0 -12
- relationalai/early_access/builder/std/strings/__init__.py +0 -14
- relationalai/early_access/devtools/__init__.py +0 -12
- relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
- relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
- relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
- relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
- relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
- relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
- relationalai/early_access/dsl/bindings/common.py +0 -402
- relationalai/early_access/dsl/bindings/csv.py +0 -170
- relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
- relationalai/early_access/dsl/bindings/snowflake.py +0 -64
- relationalai/early_access/dsl/codegen/binder.py +0 -411
- relationalai/early_access/dsl/codegen/common.py +0 -79
- relationalai/early_access/dsl/codegen/helpers.py +0 -23
- relationalai/early_access/dsl/codegen/relations.py +0 -700
- relationalai/early_access/dsl/codegen/weaver.py +0 -417
- relationalai/early_access/dsl/core/builders/__init__.py +0 -47
- relationalai/early_access/dsl/core/builders/logic.py +0 -19
- relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
- relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
- relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
- relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
- relationalai/early_access/dsl/core/context.py +0 -13
- relationalai/early_access/dsl/core/cset.py +0 -132
- relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
- relationalai/early_access/dsl/core/exprs/relational.py +0 -18
- relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
- relationalai/early_access/dsl/core/instances.py +0 -44
- relationalai/early_access/dsl/core/logic/__init__.py +0 -193
- relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
- relationalai/early_access/dsl/core/logic/exists.py +0 -223
- relationalai/early_access/dsl/core/logic/helper.py +0 -163
- relationalai/early_access/dsl/core/namespaces.py +0 -32
- relationalai/early_access/dsl/core/relations.py +0 -276
- relationalai/early_access/dsl/core/rules.py +0 -112
- relationalai/early_access/dsl/core/std/__init__.py +0 -45
- relationalai/early_access/dsl/core/temporal/recall.py +0 -6
- relationalai/early_access/dsl/core/types/__init__.py +0 -270
- relationalai/early_access/dsl/core/types/concepts.py +0 -128
- relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
- relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
- relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
- relationalai/early_access/dsl/core/types/standard.py +0 -92
- relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
- relationalai/early_access/dsl/core/types/variables.py +0 -203
- relationalai/early_access/dsl/ir/compiler.py +0 -318
- relationalai/early_access/dsl/ir/executor.py +0 -260
- relationalai/early_access/dsl/ontologies/constraints.py +0 -88
- relationalai/early_access/dsl/ontologies/export.py +0 -30
- relationalai/early_access/dsl/ontologies/models.py +0 -453
- relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
- relationalai/early_access/dsl/ontologies/readings.py +0 -60
- relationalai/early_access/dsl/ontologies/relationships.py +0 -322
- relationalai/early_access/dsl/ontologies/roles.py +0 -87
- relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
- relationalai/early_access/dsl/orm/constraints.py +0 -438
- relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
- relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
- relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
- relationalai/early_access/dsl/orm/measures/measures.py +0 -299
- relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
- relationalai/early_access/dsl/orm/models.py +0 -256
- relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
- relationalai/early_access/dsl/orm/printer.py +0 -469
- relationalai/early_access/dsl/orm/reasoners.py +0 -480
- relationalai/early_access/dsl/orm/relations.py +0 -19
- relationalai/early_access/dsl/orm/relationships.py +0 -251
- relationalai/early_access/dsl/orm/types.py +0 -42
- relationalai/early_access/dsl/orm/utils.py +0 -79
- relationalai/early_access/dsl/orm/verb.py +0 -204
- relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
- relationalai/early_access/dsl/relations.py +0 -170
- relationalai/early_access/dsl/rulesets.py +0 -69
- relationalai/early_access/dsl/schemas/__init__.py +0 -450
- relationalai/early_access/dsl/schemas/builder.py +0 -48
- relationalai/early_access/dsl/schemas/comp_names.py +0 -51
- relationalai/early_access/dsl/schemas/components.py +0 -203
- relationalai/early_access/dsl/schemas/contexts.py +0 -156
- relationalai/early_access/dsl/schemas/exprs.py +0 -89
- relationalai/early_access/dsl/schemas/fragments.py +0 -464
- relationalai/early_access/dsl/serialization.py +0 -79
- relationalai/early_access/dsl/serialize/exporter.py +0 -163
- relationalai/early_access/dsl/snow/api.py +0 -105
- relationalai/early_access/dsl/snow/common.py +0 -76
- relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
- relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
- relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
- relationalai/early_access/dsl/types/__init__.py +0 -40
- relationalai/early_access/dsl/types/concepts.py +0 -12
- relationalai/early_access/dsl/types/entities.py +0 -135
- relationalai/early_access/dsl/types/values.py +0 -17
- relationalai/early_access/dsl/utils.py +0 -102
- relationalai/early_access/graphs/__init__.py +0 -13
- relationalai/early_access/lqp/__init__.py +0 -12
- relationalai/early_access/lqp/compiler/__init__.py +0 -12
- relationalai/early_access/lqp/constructors/__init__.py +0 -18
- relationalai/early_access/lqp/executor/__init__.py +0 -12
- relationalai/early_access/lqp/ir/__init__.py +0 -12
- relationalai/early_access/lqp/passes/__init__.py +0 -12
- relationalai/early_access/lqp/pragmas/__init__.py +0 -12
- relationalai/early_access/lqp/primitives/__init__.py +0 -12
- relationalai/early_access/lqp/types/__init__.py +0 -12
- relationalai/early_access/lqp/utils/__init__.py +0 -12
- relationalai/early_access/lqp/validators/__init__.py +0 -12
- relationalai/early_access/metamodel/__init__.py +0 -58
- relationalai/early_access/metamodel/builtins/__init__.py +0 -12
- relationalai/early_access/metamodel/compiler/__init__.py +0 -12
- relationalai/early_access/metamodel/dependency/__init__.py +0 -12
- relationalai/early_access/metamodel/factory/__init__.py +0 -17
- relationalai/early_access/metamodel/helpers/__init__.py +0 -12
- relationalai/early_access/metamodel/ir/__init__.py +0 -14
- relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
- relationalai/early_access/metamodel/typer/__init__.py +0 -3
- relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
- relationalai/early_access/metamodel/types/__init__.py +0 -15
- relationalai/early_access/metamodel/util/__init__.py +0 -15
- relationalai/early_access/metamodel/visitor/__init__.py +0 -12
- relationalai/early_access/rel/__init__.py +0 -12
- relationalai/early_access/rel/executor/__init__.py +0 -12
- relationalai/early_access/rel/rel_utils/__init__.py +0 -12
- relationalai/early_access/rel/rewrite/__init__.py +0 -7
- relationalai/early_access/solvers/__init__.py +0 -19
- relationalai/early_access/sql/__init__.py +0 -11
- relationalai/early_access/sql/executor/__init__.py +0 -3
- relationalai/early_access/sql/rewrite/__init__.py +0 -3
- relationalai/early_access/tests/logging/__init__.py +0 -12
- relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
- relationalai/early_access/tests/utils/__init__.py +0 -12
- relationalai/environments/__init__.py +0 -35
- relationalai/environments/base.py +0 -381
- relationalai/environments/colab.py +0 -14
- relationalai/environments/generic.py +0 -71
- relationalai/environments/ipython.py +0 -68
- relationalai/environments/jupyter.py +0 -9
- relationalai/environments/snowbook.py +0 -169
- relationalai/errors.py +0 -2496
- relationalai/experimental/SF.py +0 -38
- relationalai/experimental/inspect.py +0 -47
- relationalai/experimental/pathfinder/__init__.py +0 -158
- relationalai/experimental/pathfinder/api.py +0 -160
- relationalai/experimental/pathfinder/automaton.py +0 -584
- relationalai/experimental/pathfinder/bridge.py +0 -226
- relationalai/experimental/pathfinder/compiler.py +0 -416
- relationalai/experimental/pathfinder/datalog.py +0 -214
- relationalai/experimental/pathfinder/diagnostics.py +0 -56
- relationalai/experimental/pathfinder/filter.py +0 -236
- relationalai/experimental/pathfinder/glushkov.py +0 -439
- relationalai/experimental/pathfinder/options.py +0 -265
- relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +0 -1951
- relationalai/experimental/pathfinder/rpq.py +0 -344
- relationalai/experimental/pathfinder/transition.py +0 -200
- relationalai/experimental/pathfinder/utils.py +0 -26
- relationalai/experimental/paths/README.md +0 -107
- relationalai/experimental/paths/api.py +0 -143
- relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
- relationalai/experimental/paths/code_organization.md +0 -2
- relationalai/experimental/paths/examples/Movies.ipynb +0 -16328
- relationalai/experimental/paths/examples/basic_example.py +0 -40
- relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
- relationalai/experimental/paths/examples/movie_example.py +0 -77
- relationalai/experimental/paths/examples/movies_data/actedin.csv +0 -193
- relationalai/experimental/paths/examples/movies_data/directed.csv +0 -45
- relationalai/experimental/paths/examples/movies_data/follows.csv +0 -7
- relationalai/experimental/paths/examples/movies_data/movies.csv +0 -39
- relationalai/experimental/paths/examples/movies_data/person.csv +0 -134
- relationalai/experimental/paths/examples/movies_data/produced.csv +0 -16
- relationalai/experimental/paths/examples/movies_data/ratings.csv +0 -10
- relationalai/experimental/paths/examples/movies_data/wrote.csv +0 -11
- relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
- relationalai/experimental/paths/examples/paths_example.py +0 -116
- relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
- relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
- relationalai/experimental/paths/graph.py +0 -185
- relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
- relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
- relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
- relationalai/experimental/paths/path_algorithms/single.py +0 -59
- relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
- relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
- relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
- relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
- relationalai/experimental/paths/path_algorithms/usp.py +0 -150
- relationalai/experimental/paths/product_graph.py +0 -93
- relationalai/experimental/paths/rpq/automaton.py +0 -584
- relationalai/experimental/paths/rpq/diagnostics.py +0 -56
- relationalai/experimental/paths/rpq/rpq.py +0 -378
- relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
- relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
- relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
- relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
- relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
- relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
- relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
- relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
- relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
- relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
- relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
- relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
- relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
- relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
- relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
- relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
- relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
- relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
- relationalai/experimental/paths/tree_agg.py +0 -168
- relationalai/experimental/paths/utilities/iterators.py +0 -27
- relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
- relationalai/experimental/solvers.py +0 -1095
- relationalai/loaders/csv.py +0 -195
- relationalai/loaders/loader.py +0 -177
- relationalai/loaders/types.py +0 -23
- relationalai/rel_emitter.py +0 -373
- relationalai/rel_utils.py +0 -185
- relationalai/semantics/designs/query_builder/identify_by.md +0 -106
- relationalai/semantics/devtools/benchmark_lqp.py +0 -535
- relationalai/semantics/devtools/compilation_manager.py +0 -294
- relationalai/semantics/devtools/extract_lqp.py +0 -110
- relationalai/semantics/internal/internal.py +0 -3785
- relationalai/semantics/internal/snowflake.py +0 -329
- relationalai/semantics/lqp/README.md +0 -34
- relationalai/semantics/lqp/algorithms.py +0 -173
- relationalai/semantics/lqp/builtins.py +0 -213
- relationalai/semantics/lqp/compiler.py +0 -22
- relationalai/semantics/lqp/constructors.py +0 -68
- relationalai/semantics/lqp/executor.py +0 -518
- relationalai/semantics/lqp/export_rewriter.py +0 -40
- relationalai/semantics/lqp/intrinsics.py +0 -24
- relationalai/semantics/lqp/ir.py +0 -150
- relationalai/semantics/lqp/model2lqp.py +0 -1056
- relationalai/semantics/lqp/passes.py +0 -38
- relationalai/semantics/lqp/primitives.py +0 -252
- relationalai/semantics/lqp/result_helpers.py +0 -266
- relationalai/semantics/lqp/rewrite/__init__.py +0 -32
- relationalai/semantics/lqp/rewrite/algorithm.py +0 -385
- relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -69
- relationalai/semantics/lqp/rewrite/cdc.py +0 -216
- relationalai/semantics/lqp/rewrite/constants_to_vars.py +0 -70
- relationalai/semantics/lqp/rewrite/deduplicate_vars.py +0 -104
- relationalai/semantics/lqp/rewrite/eliminate_data.py +0 -108
- relationalai/semantics/lqp/rewrite/extract_common.py +0 -340
- relationalai/semantics/lqp/rewrite/extract_keys.py +0 -577
- relationalai/semantics/lqp/rewrite/flatten_script.py +0 -301
- relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
- relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -348
- relationalai/semantics/lqp/rewrite/period_math.py +0 -77
- relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -339
- relationalai/semantics/lqp/rewrite/splinter.py +0 -76
- relationalai/semantics/lqp/rewrite/unify_definitions.py +0 -323
- relationalai/semantics/lqp/types.py +0 -101
- relationalai/semantics/lqp/utils.py +0 -170
- relationalai/semantics/lqp/validators.py +0 -70
- relationalai/semantics/metamodel/compiler.py +0 -134
- relationalai/semantics/metamodel/dependency.py +0 -880
- relationalai/semantics/metamodel/executor.py +0 -78
- relationalai/semantics/metamodel/factory.py +0 -287
- relationalai/semantics/metamodel/helpers.py +0 -368
- relationalai/semantics/metamodel/ir.py +0 -924
- relationalai/semantics/metamodel/rewrite/__init__.py +0 -8
- relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
- relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -220
- relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
- relationalai/semantics/metamodel/rewrite/flatten.py +0 -590
- relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -256
- relationalai/semantics/metamodel/rewrite/handle_aggregations_and_ranks.py +0 -237
- relationalai/semantics/metamodel/typer/checker.py +0 -355
- relationalai/semantics/metamodel/typer/typer.py +0 -1396
- relationalai/semantics/metamodel/util.py +0 -506
- relationalai/semantics/metamodel/visitor.py +0 -945
- relationalai/semantics/reasoners/__init__.py +0 -10
- relationalai/semantics/reasoners/graph/README.md +0 -620
- relationalai/semantics/reasoners/graph/__init__.py +0 -37
- relationalai/semantics/reasoners/graph/core.py +0 -9019
- relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +0 -797
- relationalai/semantics/reasoners/graph/tests/README.md +0 -21
- relationalai/semantics/reasoners/optimization/__init__.py +0 -68
- relationalai/semantics/reasoners/optimization/common.py +0 -88
- relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
- relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1407
- relationalai/semantics/rel/builtins.py +0 -40
- relationalai/semantics/rel/compiler.py +0 -994
- relationalai/semantics/rel/executor.py +0 -363
- relationalai/semantics/rel/rel.py +0 -482
- relationalai/semantics/rel/rel_utils.py +0 -276
- relationalai/semantics/snowflake/__init__.py +0 -3
- relationalai/semantics/sql/compiler.py +0 -2503
- relationalai/semantics/sql/executor/duck_db.py +0 -52
- relationalai/semantics/sql/executor/result_helpers.py +0 -64
- relationalai/semantics/sql/executor/snowflake.py +0 -149
- relationalai/semantics/sql/rewrite/denormalize.py +0 -222
- relationalai/semantics/sql/rewrite/double_negation.py +0 -49
- relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
- relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
- relationalai/semantics/sql/sql.py +0 -504
- relationalai/semantics/std/pragmas.py +0 -11
- relationalai/semantics/std/std.py +0 -14
- relationalai/semantics/tests/lqp/algorithms.py +0 -345
- relationalai/semantics/tests/test_snapshot_abstract.py +0 -144
- relationalai/semantics/tests/test_snapshot_base.py +0 -9
- relationalai/semantics/tests/utils.py +0 -46
- relationalai/std/__init__.py +0 -70
- relationalai/tools/cli.py +0 -2089
- relationalai/tools/cli_controls.py +0 -1975
- relationalai/tools/cli_helpers.py +0 -802
- relationalai/tools/debugger_client.py +0 -109
- relationalai/tools/debugger_server.py +0 -302
- relationalai/tools/dev.py +0 -685
- relationalai/tools/notes +0 -7
- relationalai/tools/qb_debugger.py +0 -425
- relationalai/tools/txn_progress.py +0 -188
- relationalai/util/clean_up_databases.py +0 -95
- relationalai/util/list_databases.py +0 -9
- relationalai/util/otel_configuration.py +0 -26
- relationalai/util/otel_handler.py +0 -484
- relationalai/util/snowflake_handler.py +0 -88
- relationalai/util/span_format_test.py +0 -43
- relationalai/util/span_tracker.py +0 -207
- relationalai/util/spans_file_handler.py +0 -72
- relationalai/util/tracing_handler.py +0 -34
- relationalai-0.13.5.dist-info/METADATA +0 -74
- relationalai-0.13.5.dist-info/RECORD +0 -473
- relationalai-0.13.5.dist-info/WHEEL +0 -4
- relationalai-0.13.5.dist-info/entry_points.txt +0 -3
- relationalai-0.13.5.dist-info/licenses/LICENSE +0 -202
- relationalai_test_util/__init__.py +0 -4
- relationalai_test_util/fixtures.py +0 -233
- relationalai_test_util/snapshot.py +0 -252
- relationalai_test_util/traceback.py +0 -118
- /relationalai/{analysis → semantics/frontend}/__init__.py +0 -0
- /relationalai/{auth/__init__.py → semantics/metamodel/metamodel_compiler.py} +0 -0
- /relationalai/{early_access → shims}/__init__.py +0 -0
- {relationalai/early_access/dsl/adapters → v0/relationalai/analysis}/__init__.py +0 -0
- {relationalai → v0/relationalai}/analysis/mechanistic.py +0 -0
- {relationalai → v0/relationalai}/analysis/whynot.py +0 -0
- {relationalai/early_access/dsl/adapters/orm → v0/relationalai/auth}/__init__.py +0 -0
- {relationalai → v0/relationalai}/auth/jwt_generator.py +0 -0
- {relationalai → v0/relationalai}/auth/oauth_callback_server.py +0 -0
- {relationalai → v0/relationalai}/auth/token_handler.py +0 -0
- {relationalai → v0/relationalai}/auth/util.py +0 -0
- {relationalai/clients/resources/snowflake → v0/relationalai/clients}/cache_store.py +0 -0
- {relationalai → v0/relationalai}/compiler.py +0 -0
- {relationalai → v0/relationalai}/dependencies.py +0 -0
- {relationalai → v0/relationalai}/docutils.py +0 -0
- {relationalai/early_access/dsl/adapters/owl → v0/relationalai/early_access}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/__init__.py +0 -0
- {relationalai/early_access/dsl/bindings → v0/relationalai/early_access/dsl/adapters}/__init__.py +0 -0
- {relationalai/early_access/dsl/bindings/legacy → v0/relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
- {relationalai/early_access/dsl/codegen → v0/relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
- {relationalai/early_access/dsl/core/temporal → v0/relationalai/early_access/dsl/bindings}/__init__.py +0 -0
- {relationalai/early_access/dsl/ir → v0/relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
- {relationalai/early_access/dsl/ontologies → v0/relationalai/early_access/dsl/codegen}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/constants.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/core/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/core/stack.py +0 -0
- {relationalai/early_access/dsl/orm → v0/relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/core/utils.py +0 -0
- {relationalai/early_access/dsl/orm/measures → v0/relationalai/early_access/dsl/ir}/__init__.py +0 -0
- {relationalai/early_access/dsl/physical_metadata → v0/relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
- {relationalai/early_access/dsl/serialize → v0/relationalai/early_access/dsl/orm}/__init__.py +0 -0
- {relationalai/early_access/dsl/snow → v0/relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
- {relationalai/loaders → v0/relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
- {relationalai/semantics/tests → v0/relationalai/early_access/dsl/serialize}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
- {relationalai → v0/relationalai}/early_access/dsl/serialize/model.py +0 -0
- {relationalai/semantics/tests/lqp → v0/relationalai/early_access/dsl/snow}/__init__.py +0 -0
- {relationalai → v0/relationalai}/early_access/tests/__init__.py +0 -0
- {relationalai → v0/relationalai}/environments/ci.py +0 -0
- {relationalai → v0/relationalai}/environments/hex.py +0 -0
- {relationalai → v0/relationalai}/environments/terminal.py +0 -0
- {relationalai → v0/relationalai}/experimental/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/graphs.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/rpq/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/rpq/filter.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/rpq/glushkov.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/rpq/transition.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/utilities/__init__.py +0 -0
- {relationalai → v0/relationalai}/experimental/paths/utilities/utilities.py +0 -0
- {relationalai/tools → v0/relationalai/loaders}/__init__.py +0 -0
- {relationalai → v0/relationalai}/metagen.py +0 -0
- {relationalai → v0/relationalai}/metamodel.py +0 -0
- {relationalai → v0/relationalai}/rel.py +0 -0
- {relationalai → v0/relationalai}/semantics/devtools/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/internal/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/internal/annotations.py +0 -0
- {relationalai → v0/relationalai}/semantics/lqp/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/lqp/pragmas.py +0 -0
- {relationalai → v0/relationalai}/semantics/metamodel/dataflow.py +0 -0
- {relationalai → v0/relationalai}/semantics/metamodel/typer/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/metamodel/types.py +0 -0
- {relationalai → v0/relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/rel/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/sql/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/sql/executor/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/sql/rewrite/__init__.py +0 -0
- {relationalai → v0/relationalai}/semantics/tests/logging.py +0 -0
- {relationalai → v0/relationalai}/std/aggregates.py +0 -0
- {relationalai → v0/relationalai}/std/dates.py +0 -0
- {relationalai → v0/relationalai}/std/graphs.py +0 -0
- {relationalai → v0/relationalai}/std/inspect.py +0 -0
- {relationalai → v0/relationalai}/std/math.py +0 -0
- {relationalai → v0/relationalai}/std/re.py +0 -0
- {relationalai → v0/relationalai}/std/strings.py +0 -0
- {relationalai → v0/relationalai}/tools/cleanup_snapshots.py +0 -0
- {relationalai → v0/relationalai}/tools/constants.py +0 -0
- {relationalai → v0/relationalai}/tools/query_utils.py +0 -0
- {relationalai → v0/relationalai}/tools/snapshot_viewer.py +0 -0
- {relationalai → v0/relationalai}/util/__init__.py +0 -0
- {relationalai → v0/relationalai}/util/constants.py +0 -0
- {relationalai → v0/relationalai}/util/graph.py +0 -0
- {relationalai → v0/relationalai}/util/timeout.py +0 -0
|
@@ -0,0 +1,839 @@
|
|
|
1
|
+
from v0.relationalai.semantics.metamodel import ir, builtins, helpers, types
|
|
2
|
+
from v0.relationalai.semantics.metamodel.visitor import collect_by_type
|
|
3
|
+
from v0.relationalai.semantics.metamodel.util import FrozenOrderedSet
|
|
4
|
+
from v0.relationalai.semantics.lqp import ir as lqp, utils, types as lqp_types, builtins as lqp_builtins
|
|
5
|
+
from v0.relationalai.semantics.lqp.primitives import lqp_avg_op, lqp_operator, build_primitive
|
|
6
|
+
from v0.relationalai.semantics.lqp.pragmas import pragma_to_lqp_name
|
|
7
|
+
from v0.relationalai.semantics.lqp.types import meta_type_to_lqp
|
|
8
|
+
from v0.relationalai.semantics.lqp.constructors import (
|
|
9
|
+
mk_abstraction, mk_and, mk_exists, mk_or, mk_pragma, mk_primitive,
|
|
10
|
+
mk_specialized_value, mk_type, mk_value, mk_attribute
|
|
11
|
+
)
|
|
12
|
+
from v0.relationalai.semantics.lqp.utils import TranslationCtx, gen_unique_var
|
|
13
|
+
from v0.relationalai.semantics.lqp.validators import assert_valid_input
|
|
14
|
+
from v0.relationalai.semantics.lqp.rewrite.functional_dependencies import (
|
|
15
|
+
normalized_fd, contains_only_declarable_constraints
|
|
16
|
+
)
|
|
17
|
+
from decimal import Decimal as PyDecimal
|
|
18
|
+
from datetime import datetime, date, timezone
|
|
19
|
+
from typing import Tuple, cast, Union, Optional
|
|
20
|
+
from warnings import warn
|
|
21
|
+
import re
|
|
22
|
+
import uuid
|
|
23
|
+
|
|
24
|
+
# Main access point for translating metamodel to lqp. Converts the model IR to an LQP epoch.
|
|
25
|
+
def to_lqp(model: ir.Model, fragment_name: bytes, ctx: TranslationCtx) -> tuple[Optional[tuple], lqp.Epoch]:
|
|
26
|
+
assert_valid_input(model)
|
|
27
|
+
decls: list[lqp.Declaration] = []
|
|
28
|
+
reads: list[lqp.Read] = []
|
|
29
|
+
|
|
30
|
+
# LQP only accepts logical tasks
|
|
31
|
+
# These are asserted at init time
|
|
32
|
+
root = cast(ir.Logical, model.root)
|
|
33
|
+
for subtask in root.body:
|
|
34
|
+
assert isinstance(subtask, ir.Logical)
|
|
35
|
+
new_decls = _translate_to_decls(ctx, subtask)
|
|
36
|
+
decls.extend(new_decls)
|
|
37
|
+
|
|
38
|
+
# Add pyrel error attributes to reads.
|
|
39
|
+
for err_id in _extract_pyrel_error_ids(ctx, model):
|
|
40
|
+
ctx.output_ids.append(err_id)
|
|
41
|
+
|
|
42
|
+
reads.extend(_get_output_reads(ctx.output_ids))
|
|
43
|
+
|
|
44
|
+
export_info = None
|
|
45
|
+
if len(ctx.export_ids) > 0:
|
|
46
|
+
export_filename, col_types, export_reads = _get_export_reads(ctx.export_ids)
|
|
47
|
+
reads.extend(export_reads)
|
|
48
|
+
export_info = (export_filename, col_types)
|
|
49
|
+
|
|
50
|
+
debug_info = lqp.DebugInfo(id_to_orig_name=ctx.rel_id_to_orig_name, meta=None)
|
|
51
|
+
fragment_id = lqp.FragmentId(id=fragment_name, meta=None)
|
|
52
|
+
fragment = lqp.Fragment(id=fragment_id, declarations=decls, meta=None, debug_info=debug_info)
|
|
53
|
+
define_op = lqp.Define(fragment=fragment, meta=None)
|
|
54
|
+
|
|
55
|
+
txn = lqp.Epoch(
|
|
56
|
+
reads=reads,
|
|
57
|
+
writes=[lqp.Write(write_type=define_op, meta=None)],
|
|
58
|
+
meta=None
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
return (export_info, txn)
|
|
62
|
+
|
|
63
|
+
def _effect_bindings(effect: Union[ir.Output, ir.Update]) -> list[ir.Value]:
|
|
64
|
+
if isinstance(effect, ir.Output):
|
|
65
|
+
# Unions may not return anything. The generated IR contains a None value when this
|
|
66
|
+
# happens. We ignore it here.
|
|
67
|
+
return [v for v in helpers.output_values(effect.aliases) if v]
|
|
68
|
+
else:
|
|
69
|
+
return list(effect.args)
|
|
70
|
+
|
|
71
|
+
def _get_output_reads(output_ids: list[tuple[lqp.RelationId, str]]) -> list[lqp.Read]:
|
|
72
|
+
reads = []
|
|
73
|
+
for (rel_id, name) in output_ids:
|
|
74
|
+
assert isinstance(rel_id, lqp.RelationId)
|
|
75
|
+
output = lqp.Output(name=name, relation_id=rel_id, meta=None)
|
|
76
|
+
reads.append(lqp.Read(read_type=output, meta=None))
|
|
77
|
+
return reads
|
|
78
|
+
|
|
79
|
+
def _get_export_reads(export_ids: list[tuple[lqp.RelationId, int, lqp.Type]]) -> tuple[str, list, list[lqp.Read]]:
|
|
80
|
+
reads = []
|
|
81
|
+
csv_columns = []
|
|
82
|
+
col_info = []
|
|
83
|
+
for (col_id, col_num, col_type) in sorted(export_ids, key=lambda x: x[1]):
|
|
84
|
+
col_name = f"col{col_num:03}"
|
|
85
|
+
csv_columns.append(lqp.ExportCSVColumn(column_name=col_name, column_data=col_id, meta=None))
|
|
86
|
+
col_info.append((col_name, col_type))
|
|
87
|
+
|
|
88
|
+
# Generate a random name for the internal export path
|
|
89
|
+
export_filename = "export_" + str(uuid.uuid4()).replace("-", "_")
|
|
90
|
+
|
|
91
|
+
# Note that the engine will append the transaction id to the export path for access
|
|
92
|
+
# control reasons. So the actual final path will be
|
|
93
|
+
# `.../export/{export_filename}/data_{txn_id}`
|
|
94
|
+
export_path = f"snowflake://APP_STATE.RAI_INTERNAL_STAGE/export/{export_filename}/data"
|
|
95
|
+
export_csv_config = lqp.ExportCSVConfig(
|
|
96
|
+
path=export_path,
|
|
97
|
+
data_columns=csv_columns,
|
|
98
|
+
compression="gzip",
|
|
99
|
+
partition_size=200,
|
|
100
|
+
syntax_escapechar='"', # To follow Snowflake's expected format
|
|
101
|
+
meta=None,
|
|
102
|
+
)
|
|
103
|
+
reads.append(lqp.Read(read_type=lqp.Export(config=export_csv_config, meta=None), meta=None))
|
|
104
|
+
return (export_filename, col_info, reads)
|
|
105
|
+
|
|
106
|
+
def _translate_to_decls(ctx: TranslationCtx, rule: ir.Logical) -> list[lqp.Declaration]:
|
|
107
|
+
if contains_only_declarable_constraints(rule):
|
|
108
|
+
return _translate_to_constraint_decls(ctx, rule)
|
|
109
|
+
else:
|
|
110
|
+
return _translate_to_standard_decl(ctx, rule)
|
|
111
|
+
|
|
112
|
+
def _translate_to_constraint_decls(ctx: TranslationCtx, rule: ir.Logical) -> list[lqp.Declaration]:
|
|
113
|
+
constraint_decls: list[lqp.Declaration] = []
|
|
114
|
+
for task in rule.body:
|
|
115
|
+
assert isinstance(task, ir.Require)
|
|
116
|
+
fd = normalized_fd(task)
|
|
117
|
+
assert fd is not None
|
|
118
|
+
|
|
119
|
+
# check for unresolved types
|
|
120
|
+
if any(types.is_any(var.type) for var in fd.keys + fd.values):
|
|
121
|
+
warn(f"Ignoring FD with unresolved type: {fd}")
|
|
122
|
+
continue
|
|
123
|
+
|
|
124
|
+
lqp_typed_keys = [_translate_term(ctx, key) for key in fd.keys]
|
|
125
|
+
lqp_typed_values = [_translate_term(ctx, value) for value in fd.values]
|
|
126
|
+
lqp_typed_vars:list[Tuple[lqp.Var, lqp.Type]] = lqp_typed_keys + lqp_typed_values # type: ignore
|
|
127
|
+
lqp_guard_atoms = [_translate_to_atom(ctx, atom) for atom in fd.guard]
|
|
128
|
+
lqp_guard = mk_abstraction(lqp_typed_vars, mk_and(lqp_guard_atoms))
|
|
129
|
+
lqp_keys:list[lqp.Var] = [var for (var, _) in lqp_typed_keys] # type: ignore
|
|
130
|
+
lqp_values:list[lqp.Var] = [var for (var, _) in lqp_typed_values] # type: ignore
|
|
131
|
+
|
|
132
|
+
fd_decl = lqp.FunctionalDependency(
|
|
133
|
+
guard=lqp_guard,
|
|
134
|
+
keys=lqp_keys,
|
|
135
|
+
values=lqp_values,
|
|
136
|
+
meta=None
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
constraint_decls.append(fd_decl)
|
|
140
|
+
|
|
141
|
+
return constraint_decls
|
|
142
|
+
|
|
143
|
+
def _translate_to_standard_decl(ctx: TranslationCtx, rule: ir.Logical) -> list[lqp.Declaration]:
|
|
144
|
+
effects = collect_by_type((ir.Output, ir.Update), rule)
|
|
145
|
+
aggregates = collect_by_type(ir.Aggregate, rule)
|
|
146
|
+
ranks = collect_by_type(ir.Rank, rule)
|
|
147
|
+
|
|
148
|
+
# TODO: should this ever actually come in as input?
|
|
149
|
+
if len(effects) == 0:
|
|
150
|
+
return []
|
|
151
|
+
|
|
152
|
+
assert len(ranks) == 0 or len(aggregates) == 0, "rules cannot have both aggregates and ranks"
|
|
153
|
+
|
|
154
|
+
conjuncts = []
|
|
155
|
+
for task in rule.body:
|
|
156
|
+
if isinstance(task, (ir.Output, ir.Update)):
|
|
157
|
+
continue
|
|
158
|
+
conjuncts.append(_translate_to_formula(ctx, task))
|
|
159
|
+
|
|
160
|
+
# Aggregates reduce over the body
|
|
161
|
+
if aggregates or ranks:
|
|
162
|
+
aggr_body = mk_and(conjuncts)
|
|
163
|
+
conjuncts = []
|
|
164
|
+
for aggr in aggregates:
|
|
165
|
+
conjuncts.append(_translate_aggregate(ctx, aggr, aggr_body))
|
|
166
|
+
for rank in ranks:
|
|
167
|
+
conjuncts.append(_translate_rank(ctx, rank, aggr_body))
|
|
168
|
+
|
|
169
|
+
return [_translate_effect(ctx, effect, mk_and(conjuncts)) for effect in effects]
|
|
170
|
+
|
|
171
|
+
def _translate_annotations(annotations: FrozenOrderedSet[ir.Annotation]) -> list[lqp.Attribute]:
|
|
172
|
+
attributes = []
|
|
173
|
+
for annotation in annotations:
|
|
174
|
+
|
|
175
|
+
if annotation.relation.name in lqp_builtins.annotations_to_emit:
|
|
176
|
+
if any(not isinstance(a, ir.Literal) for a in annotation.args):
|
|
177
|
+
warn("LQP currently ignores annotation parameters with non-literal values")
|
|
178
|
+
continue
|
|
179
|
+
|
|
180
|
+
# Convert literal arguments to LQP values
|
|
181
|
+
args = []
|
|
182
|
+
for a in annotation.args:
|
|
183
|
+
assert isinstance(a, ir.Literal)
|
|
184
|
+
args.append(mk_value(a.value))
|
|
185
|
+
attributes.append(mk_attribute(annotation.relation.name, args))
|
|
186
|
+
return attributes
|
|
187
|
+
|
|
188
|
+
# Translates an effect (export, output, or update) into the corresponding def. Note that
|
|
189
|
+
# this method only generates the def and not the LQP read operation, which is added later by
|
|
190
|
+
# `_get_output_reads` and `_get_export_reads`.
|
|
191
|
+
def _translate_effect(ctx: TranslationCtx, effect: Union[ir.Output, ir.Update], body: lqp.Formula) -> lqp.Declaration:
|
|
192
|
+
bindings = _effect_bindings(effect)
|
|
193
|
+
|
|
194
|
+
def _is_export(e):
|
|
195
|
+
return isinstance(e, ir.Output) and builtins.export_annotation in e.annotations
|
|
196
|
+
|
|
197
|
+
if isinstance(effect, ir.Output):
|
|
198
|
+
projection, eqs, suffix = _translate_output_bindings(ctx, bindings)
|
|
199
|
+
meta_id = effect.id
|
|
200
|
+
|
|
201
|
+
if _is_export(effect):
|
|
202
|
+
def_name = "export_relation" + suffix
|
|
203
|
+
else:
|
|
204
|
+
def_name = "output" + suffix
|
|
205
|
+
|
|
206
|
+
def_name = ctx.output_names.get_name_by_id(meta_id, def_name)
|
|
207
|
+
rel_id = get_output_id(ctx, def_name, meta_id)
|
|
208
|
+
else:
|
|
209
|
+
projection, eqs = _translate_bindings(ctx, bindings)
|
|
210
|
+
def_name = effect.relation.name
|
|
211
|
+
rel_id = get_relation_id(ctx, effect.relation, projection)
|
|
212
|
+
|
|
213
|
+
eqs.append(body)
|
|
214
|
+
new_body = mk_and(eqs)
|
|
215
|
+
|
|
216
|
+
# Context bookkeeping for exports and outputs
|
|
217
|
+
if _is_export(effect):
|
|
218
|
+
# The row id is the first n-1 elements, and the actual data is the last element. Its
|
|
219
|
+
# type is stored in the first element of the tuple.
|
|
220
|
+
col_type = projection[-1][1]
|
|
221
|
+
_col_num_match = re.search(r"export_relation_col([0-9]+)", def_name)
|
|
222
|
+
assert _col_num_match, f"Could not find column number in suffix: {def_name}"
|
|
223
|
+
col_num = int(_col_num_match.group(1))
|
|
224
|
+
ctx.export_ids.append((rel_id, col_num, col_type))
|
|
225
|
+
elif isinstance(effect, ir.Output):
|
|
226
|
+
ctx.output_ids.append((rel_id, def_name))
|
|
227
|
+
|
|
228
|
+
# First we collect annotations on the effect itself, e.g. from something like
|
|
229
|
+
# `select(...).annotate(...)`.
|
|
230
|
+
annotations = effect.annotations
|
|
231
|
+
if isinstance(effect, ir.Update):
|
|
232
|
+
# Then we translate annotations on the relation itself, e.g.
|
|
233
|
+
# ```
|
|
234
|
+
# Bar.foo = model.Relationship(...)
|
|
235
|
+
# Bar.foo.annotate(...)
|
|
236
|
+
# ```
|
|
237
|
+
annotations = annotations | effect.relation.annotations
|
|
238
|
+
|
|
239
|
+
return lqp.Def(
|
|
240
|
+
name = rel_id,
|
|
241
|
+
body = mk_abstraction(projection, new_body),
|
|
242
|
+
attrs = _translate_annotations(annotations),
|
|
243
|
+
meta = None,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
def _translate_output_bindings(ctx: TranslationCtx, bindings: list[ir.Value]) -> Tuple[list[Tuple[lqp.Var, lqp.Type]], list[lqp.Formula], str]:
|
|
247
|
+
symbol_literals = []
|
|
248
|
+
non_symbols = []
|
|
249
|
+
for binding in bindings:
|
|
250
|
+
if isinstance(binding, ir.Literal) and binding.type == types.Symbol:
|
|
251
|
+
symbol_literals.append(binding.value)
|
|
252
|
+
else:
|
|
253
|
+
non_symbols.append(binding)
|
|
254
|
+
projection, eqs = _translate_bindings(ctx, non_symbols)
|
|
255
|
+
if len(symbol_literals) > 0:
|
|
256
|
+
name_suffix = "_"
|
|
257
|
+
name_suffix += "_".join(symbol_literals)
|
|
258
|
+
else:
|
|
259
|
+
name_suffix = ""
|
|
260
|
+
|
|
261
|
+
return projection, eqs, name_suffix
|
|
262
|
+
|
|
263
|
+
def _translate_rank(ctx: TranslationCtx, rank: ir.Rank, body: lqp.Formula) -> lqp.Formula:
|
|
264
|
+
# Ascending rank is constructed using rel_primitive_sort. If a limit is added to an
|
|
265
|
+
# ascending rank we can use rel_primitive_top for an efficient evaluation.
|
|
266
|
+
#
|
|
267
|
+
# Descending rank is constructed as an ascending sort, then the ascending rank is
|
|
268
|
+
# subtracted from a count of the elements (plus 1 so that we still start at 1).
|
|
269
|
+
# Adding a limit to a descending rank is done by adding a filter of rank <= limit.
|
|
270
|
+
|
|
271
|
+
# Limits are the sort plus a filter on rank <= limit.
|
|
272
|
+
if all(o for o in rank.arg_is_ascending):
|
|
273
|
+
ascending = True
|
|
274
|
+
elif all(not o for o in rank.arg_is_ascending):
|
|
275
|
+
ascending = False
|
|
276
|
+
else:
|
|
277
|
+
raise Exception("Mixed orderings in rank are not supported yet.")
|
|
278
|
+
|
|
279
|
+
# Filter out the group-by variables, since they are introduced outside the rank.
|
|
280
|
+
input_args, input_eqs = _translate_bindings(ctx, list(rank.args))
|
|
281
|
+
introduced_meta_projs = [arg for arg in rank.projection if arg not in rank.group and arg not in rank.args]
|
|
282
|
+
projected_args, projected_eqs = _translate_bindings(ctx, list(introduced_meta_projs))
|
|
283
|
+
|
|
284
|
+
# rank expects an Int128 result, but the primitive will return an Int64 result.
|
|
285
|
+
# we need to set up an intermediary variable to hold the Int64 result, and a cast
|
|
286
|
+
# to convert it to Int128.
|
|
287
|
+
result_var, _ = _translate_term(ctx, rank.result)
|
|
288
|
+
# The primitive will return an Int64 result, so we need a var to hold the intermediary.
|
|
289
|
+
result_64_var = gen_unique_var(ctx, "v_rank")
|
|
290
|
+
result_64_type = mk_type(lqp.TypeName.INT)
|
|
291
|
+
|
|
292
|
+
cast = lqp.Cast(input=result_64_var, result=result_var, meta=None)
|
|
293
|
+
|
|
294
|
+
body = mk_and([body] + input_eqs + projected_eqs)
|
|
295
|
+
abstr_args = input_args + projected_args
|
|
296
|
+
|
|
297
|
+
if ascending:
|
|
298
|
+
ranker = _translate_ascending_rank(ctx, rank.limit, result_64_var, body, abstr_args)
|
|
299
|
+
else:
|
|
300
|
+
ranker = _translate_descending_rank(ctx, rank.limit, result_64_var, body, abstr_args)
|
|
301
|
+
|
|
302
|
+
return mk_exists([(result_64_var, result_64_type)], mk_and([ranker, cast]))
|
|
303
|
+
|
|
304
|
+
def _translate_descending_rank(ctx: TranslationCtx, limit: int, result: lqp.Var, body: lqp.Formula, abstr_args) -> lqp.Formula:
|
|
305
|
+
result_var = result
|
|
306
|
+
result_type = mk_type(lqp.TypeName.INT)
|
|
307
|
+
|
|
308
|
+
# Rename abstracted args in the body to new variable names
|
|
309
|
+
var_map = {var.name: gen_unique_var(ctx, 't_' + var.name) for (var, _) in abstr_args}
|
|
310
|
+
body = utils.rename_vars_formula(body, var_map)
|
|
311
|
+
new_abstr_args = [(var_map[var.name], typ) for (var, typ) in abstr_args]
|
|
312
|
+
|
|
313
|
+
# Construct a conjunction of the ranking, a counter for the body, a subtraction
|
|
314
|
+
# of the rank from the count and an addition of 1. Wrap this in an abstraction.
|
|
315
|
+
count_res = gen_unique_var(ctx, "count_res")
|
|
316
|
+
|
|
317
|
+
# Add one to the count to account for the rank starting at 1.
|
|
318
|
+
one, one_eq = constant_to_var(ctx, to_lqp_value(1, types.Int64), "one")
|
|
319
|
+
one_bigger = gen_unique_var(ctx, "one_bigger")
|
|
320
|
+
addition = mk_primitive("rel_primitive_add_monotype", [count_res, one, one_bigger])
|
|
321
|
+
|
|
322
|
+
# Subtract the rank from the count + 1
|
|
323
|
+
asc_rank = gen_unique_var(ctx, "asc_rank")
|
|
324
|
+
subtraction = mk_primitive("rel_primitive_subtract_monotype", [one_bigger, result_var, asc_rank])
|
|
325
|
+
|
|
326
|
+
# Construct the ranking
|
|
327
|
+
desc_ranking_terms = [asc_rank] + [v[0] for v in abstr_args]
|
|
328
|
+
ranking = lqp.FFI(
|
|
329
|
+
meta=None,
|
|
330
|
+
name="rel_primitive_sort",
|
|
331
|
+
args=[mk_abstraction(new_abstr_args, body)],
|
|
332
|
+
terms=desc_ranking_terms,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
# Count the number of rows in the body
|
|
336
|
+
count_type = meta_type_to_lqp(types.Int64)
|
|
337
|
+
count_var, count_eq = constant_to_var(ctx, to_lqp_value(1, types.Int64), "counter")
|
|
338
|
+
desc_body = mk_and([body, count_eq])
|
|
339
|
+
aggr_abstr_args = new_abstr_args + [(count_var, count_type)]
|
|
340
|
+
count_aggr = lqp.Reduce(
|
|
341
|
+
op=lqp_operator(
|
|
342
|
+
ctx,
|
|
343
|
+
"count",
|
|
344
|
+
"count",
|
|
345
|
+
mk_type(lqp.TypeName.INT)
|
|
346
|
+
),
|
|
347
|
+
body=mk_abstraction(aggr_abstr_args, desc_body),
|
|
348
|
+
terms=[count_res],
|
|
349
|
+
meta=None
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
# Bring it all together and do the maths.
|
|
353
|
+
ranking = mk_exists(
|
|
354
|
+
vars=[
|
|
355
|
+
(asc_rank, result_type),
|
|
356
|
+
(count_res, result_type),
|
|
357
|
+
(one, result_type),
|
|
358
|
+
(one_bigger, result_type)
|
|
359
|
+
],
|
|
360
|
+
value=mk_and([ranking, count_aggr, one_eq, addition, subtraction])
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
# If there is a limit, we need to add a filter to the ranking.
|
|
364
|
+
# Wrap with a rank <= limit
|
|
365
|
+
if limit != 0:
|
|
366
|
+
limit_term, _ = _translate_term(ctx, ir.Literal(types.Int64, limit))
|
|
367
|
+
limiter = mk_primitive("rel_primitive_lt_eq_monotype", [result_var, limit_term])
|
|
368
|
+
ranking = mk_and([ranking, limiter])
|
|
369
|
+
|
|
370
|
+
return ranking
|
|
371
|
+
|
|
372
|
+
def _translate_ascending_rank(ctx: TranslationCtx, limit: int, result_var: lqp.Var, body: lqp.Formula, abstr_args) -> lqp.Formula:
|
|
373
|
+
terms = [result_var] + [v[0] for v in abstr_args]
|
|
374
|
+
|
|
375
|
+
# Rename abstracted args in the body to new variable names
|
|
376
|
+
var_map = {var.name: gen_unique_var(ctx, 't_' + var.name) for (var, _) in abstr_args}
|
|
377
|
+
body = utils.rename_vars_formula(body, var_map)
|
|
378
|
+
new_abstr_args = [(var_map[var.name], typ) for (var, typ) in abstr_args]
|
|
379
|
+
sort_abstr = mk_abstraction(new_abstr_args, body)
|
|
380
|
+
|
|
381
|
+
if limit == 0:
|
|
382
|
+
return lqp.FFI(
|
|
383
|
+
meta=None,
|
|
384
|
+
name="rel_primitive_sort",
|
|
385
|
+
args=[sort_abstr],
|
|
386
|
+
terms=terms,
|
|
387
|
+
)
|
|
388
|
+
else:
|
|
389
|
+
limit_type = meta_type_to_lqp(types.Int64)
|
|
390
|
+
limit_var, limit_eq = constant_to_var(ctx, to_lqp_value(limit, types.Int64), "limit")
|
|
391
|
+
limit_abstr = mk_abstraction([(limit_var, limit_type)], limit_eq)
|
|
392
|
+
return lqp.FFI(
|
|
393
|
+
meta=None,
|
|
394
|
+
name="rel_primitive_top",
|
|
395
|
+
args=[sort_abstr, limit_abstr],
|
|
396
|
+
terms=terms,
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
def _translate_aggregate(ctx: TranslationCtx, aggr: ir.Aggregate, body: lqp.Formula) -> Union[lqp.Reduce, lqp.Formula]:
|
|
400
|
+
# TODO: handle this properly
|
|
401
|
+
aggr_name = aggr.aggregation.name
|
|
402
|
+
supported_aggrs = ("sum", "count", "avg", "min", "max", "rel_primitive_solverlib_ho_appl")
|
|
403
|
+
assert aggr_name in supported_aggrs, f"only support {supported_aggrs} for now, not {aggr.aggregation.name}"
|
|
404
|
+
|
|
405
|
+
meta_output_terms = []
|
|
406
|
+
meta_input_terms = []
|
|
407
|
+
|
|
408
|
+
for (field, arg) in zip(aggr.aggregation.fields, aggr.args):
|
|
409
|
+
if field.input:
|
|
410
|
+
meta_input_terms.append(arg)
|
|
411
|
+
else:
|
|
412
|
+
meta_output_terms.append(arg)
|
|
413
|
+
|
|
414
|
+
output_terms = [_translate_term(ctx, term) for term in meta_output_terms]
|
|
415
|
+
output_vars = [term[0] for term in output_terms]
|
|
416
|
+
|
|
417
|
+
body_conjs = [body]
|
|
418
|
+
input_args, input_eqs = _translate_bindings(ctx, meta_input_terms)
|
|
419
|
+
|
|
420
|
+
# TODO: Can this safely be applied to all aggregates?
|
|
421
|
+
if aggr_name in ("sum", "min", "max"):
|
|
422
|
+
assert len(output_terms) == 1, f"{aggr_name} expects a single output variable"
|
|
423
|
+
assert len(meta_input_terms) == 1, f"{aggr_name} expects a single input variable"
|
|
424
|
+
assert isinstance(meta_output_terms[0], ir.Var)
|
|
425
|
+
assert input_args[0][1] == output_terms[0][1], f"{aggr_name}({input_args[0][1].type_name}) had output type of {output_terms[0][1].type_name}"
|
|
426
|
+
|
|
427
|
+
# Filter out the group-by variables, since they are introduced outside the aggregation.
|
|
428
|
+
# Input terms are added later below.
|
|
429
|
+
introduced_meta_projs = [arg for arg in aggr.projection if arg not in aggr.group and arg not in meta_input_terms]
|
|
430
|
+
projected_args, projected_eqs = _translate_bindings(ctx, list(introduced_meta_projs))
|
|
431
|
+
body_conjs.extend(input_eqs)
|
|
432
|
+
body_conjs.extend(projected_eqs)
|
|
433
|
+
abstr_args: list[Tuple[lqp.Var, lqp.Type]] = projected_args + input_args
|
|
434
|
+
|
|
435
|
+
if aggr_name == "count":
|
|
436
|
+
assert len(output_terms) == 1, "Count and avg expect a single output variable"
|
|
437
|
+
assert isinstance(meta_output_terms[0], ir.Var)
|
|
438
|
+
# Count sums up "1" for each row. We use the expected output type for the type
|
|
439
|
+
# of the count variable.
|
|
440
|
+
typ = meta_type_to_lqp(meta_output_terms[0].type)
|
|
441
|
+
one_var, eq = constant_to_var(ctx, to_lqp_value(1, meta_output_terms[0].type), "one")
|
|
442
|
+
body_conjs.append(eq)
|
|
443
|
+
abstr_args.append((one_var, typ))
|
|
444
|
+
body = mk_and(body_conjs)
|
|
445
|
+
|
|
446
|
+
# Average needs to wrap the reduce in Exists(Conjunction(Reduce, div))
|
|
447
|
+
if aggr_name == "avg":
|
|
448
|
+
assert len(output_vars) == 1, "avg should only have one output variable"
|
|
449
|
+
output_var = output_vars[0]
|
|
450
|
+
|
|
451
|
+
# Count sums up "1" for each row. We make the reasonably safe assumption that there
|
|
452
|
+
# are less than 2^31 rows in the body.
|
|
453
|
+
count_type = meta_type_to_lqp(types.Int64)
|
|
454
|
+
one_var, eq = constant_to_var(ctx, to_lqp_value(1, types.Int64), "one")
|
|
455
|
+
body_conjs.append(eq)
|
|
456
|
+
abstr_args.append((one_var, count_type))
|
|
457
|
+
body = mk_and(body_conjs)
|
|
458
|
+
|
|
459
|
+
# The average will produce two output variables: sum and count.
|
|
460
|
+
sum_result = gen_unique_var(ctx, "sum")
|
|
461
|
+
count_result = gen_unique_var(ctx, "count")
|
|
462
|
+
|
|
463
|
+
# Second to last is the variable we're summing over.
|
|
464
|
+
(sum_var, sum_type) = abstr_args[-2]
|
|
465
|
+
|
|
466
|
+
result = lqp.Reduce(
|
|
467
|
+
op=lqp_avg_op(ctx, aggr.aggregation.name, sum_var.name, sum_type),
|
|
468
|
+
body=mk_abstraction(abstr_args, body),
|
|
469
|
+
terms=[sum_result, count_result],
|
|
470
|
+
meta=None,
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
if sum_type == count_type:
|
|
474
|
+
div = mk_primitive("rel_primitive_divide_monotype", [sum_result, count_result, output_var])
|
|
475
|
+
conjunction = mk_and([result, div])
|
|
476
|
+
|
|
477
|
+
# Finally, we need to wrap everything in an `exists` to project away the sum and
|
|
478
|
+
# count variables and only keep the result of the division.
|
|
479
|
+
result_terms = [(sum_result, sum_type), (count_result, count_type)]
|
|
480
|
+
else:
|
|
481
|
+
# If the sum type and count type don't match, we need to cast the count
|
|
482
|
+
count_casted = gen_unique_var(ctx, "count_casted")
|
|
483
|
+
count_cast = lqp.Cast(input=count_result, result=count_casted, meta=None)
|
|
484
|
+
|
|
485
|
+
div = mk_primitive("rel_primitive_divide_monotype", [sum_result, count_casted, output_var])
|
|
486
|
+
conjunction = mk_and([result, count_cast, div])
|
|
487
|
+
|
|
488
|
+
# Finally, we need to wrap everything in an `exists` to project away the sum and
|
|
489
|
+
# count variables and only keep the result of the division.
|
|
490
|
+
result_terms = [(sum_result, sum_type), (count_result, count_type), (count_casted, sum_type)]
|
|
491
|
+
|
|
492
|
+
return mk_exists(result_terms, conjunction)
|
|
493
|
+
|
|
494
|
+
# `input_args` hold the types of the input arguments, but they may have been modified
|
|
495
|
+
# if we're dealing with a count, so we use `abstr_args` to find the type.
|
|
496
|
+
(aggr_arg, aggr_arg_type) = abstr_args[-1]
|
|
497
|
+
|
|
498
|
+
# Group-bys do not need to be handled at all, since they are introduced outside already
|
|
499
|
+
reduce = lqp.Reduce(
|
|
500
|
+
op=lqp_operator(ctx, aggr.aggregation.name, aggr_arg.name, aggr_arg_type),
|
|
501
|
+
body=mk_abstraction(abstr_args, body),
|
|
502
|
+
terms=output_vars,
|
|
503
|
+
meta=None
|
|
504
|
+
)
|
|
505
|
+
return reduce
|
|
506
|
+
|
|
507
|
+
def _translate_to_formula(ctx: TranslationCtx, task: ir.Task) -> lqp.Formula:
|
|
508
|
+
if isinstance(task, ir.Logical):
|
|
509
|
+
conjuncts = [_translate_to_formula(ctx, child) for child in task.body]
|
|
510
|
+
return mk_and(conjuncts)
|
|
511
|
+
elif isinstance(task, ir.Lookup):
|
|
512
|
+
return _translate_to_atom(ctx, task)
|
|
513
|
+
elif isinstance(task, ir.Not):
|
|
514
|
+
return lqp.Not(arg=_translate_to_formula(ctx, task.task), meta=None)
|
|
515
|
+
elif isinstance(task, ir.Exists):
|
|
516
|
+
lqp_vars, conjuncts = _translate_bindings(ctx, list(task.vars))
|
|
517
|
+
conjuncts.append(_translate_to_formula(ctx, task.task))
|
|
518
|
+
return mk_exists(lqp_vars, mk_and(conjuncts))
|
|
519
|
+
elif isinstance(task, ir.Construct):
|
|
520
|
+
assert len(task.values) >= 1, "Construct should have at least one value"
|
|
521
|
+
terms = [_translate_term(ctx, arg) for arg in task.values]
|
|
522
|
+
result_term = _translate_term(ctx, task.id_var)
|
|
523
|
+
terms.append(result_term)
|
|
524
|
+
assert result_term[1].type_name == lqp.TypeName.UINT128, \
|
|
525
|
+
f"Attempting to store a {task.id_var} in a type `{result_term[1].type_name}`"
|
|
526
|
+
|
|
527
|
+
return mk_primitive("rel_primitive_hash_tuple_uint128", [v for v, _ in terms])
|
|
528
|
+
elif isinstance(task, ir.Union):
|
|
529
|
+
# TODO: handle hoisted vars if needed
|
|
530
|
+
disjs = [_translate_to_formula(ctx, child) for child in task.tasks]
|
|
531
|
+
return mk_or(disjs)
|
|
532
|
+
elif isinstance(task, (ir.Aggregate, ir.Output, ir.Update)):
|
|
533
|
+
# Nothing to do here, handled in _translate_to_decls
|
|
534
|
+
return mk_and([])
|
|
535
|
+
elif isinstance(task, ir.Rank):
|
|
536
|
+
# Nothing to do here, handled in _translate_to_decls
|
|
537
|
+
return mk_and([])
|
|
538
|
+
else:
|
|
539
|
+
raise NotImplementedError(f"Unknown task type (formula): {type(task)}")
|
|
540
|
+
|
|
541
|
+
# Only used for translating terms on relatoms, which can be specialized values.
|
|
542
|
+
def _translate_relterm(ctx: TranslationCtx, term: ir.Value) -> Tuple[lqp.RelTerm, lqp.Type]:
|
|
543
|
+
if isinstance(term, ir.Literal) and term.type == types.Symbol:
|
|
544
|
+
if isinstance(term.value, str):
|
|
545
|
+
value = mk_value(term.value)
|
|
546
|
+
return mk_specialized_value(value), meta_type_to_lqp(types.String)
|
|
547
|
+
elif isinstance(term.value, int):
|
|
548
|
+
value = mk_value(term.value)
|
|
549
|
+
return mk_specialized_value(value), meta_type_to_lqp(types.Int64)
|
|
550
|
+
else:
|
|
551
|
+
raise NotImplementedError(f"Cannot specialize literal of type {type(term.value)}")
|
|
552
|
+
return _translate_term(ctx, term)
|
|
553
|
+
|
|
554
|
+
def _translate_term(ctx: TranslationCtx, term: ir.Value) -> Tuple[lqp.Term, lqp.Type]:
|
|
555
|
+
if isinstance(term, ir.ScalarType):
|
|
556
|
+
# TODO: ScalarType is not like other terms, should be handled separately.
|
|
557
|
+
return to_lqp_value(term.name, types.String), meta_type_to_lqp(types.String)
|
|
558
|
+
elif isinstance(term, ir.Var):
|
|
559
|
+
t = meta_type_to_lqp(term.type)
|
|
560
|
+
return _translate_var(ctx, term), t
|
|
561
|
+
else:
|
|
562
|
+
assert isinstance(term, ir.Literal), f"Cannot translate value {term!r} of type {type(term)} to LQP Term; neither Var nor Literal."
|
|
563
|
+
v = to_lqp_value(term.value, term.type)
|
|
564
|
+
return v, meta_type_to_lqp(term.type)
|
|
565
|
+
|
|
566
|
+
def _translate_to_atom(ctx: TranslationCtx, task: ir.Lookup) -> lqp.Formula:
|
|
567
|
+
if task.relation == builtins.cast:
|
|
568
|
+
assert len(task.args) == 3, f"expected three terms for {task.relation.name}, got {len(task.args)}"
|
|
569
|
+
|
|
570
|
+
terms = []
|
|
571
|
+
for arg in task.args[1:]:
|
|
572
|
+
term, _ = _translate_relterm(ctx, arg)
|
|
573
|
+
terms.append(term)
|
|
574
|
+
return lqp.Cast(input=terms[0], result=terms[1], meta=None)
|
|
575
|
+
|
|
576
|
+
if task.relation == builtins.join:
|
|
577
|
+
return _translate_join(ctx, task)
|
|
578
|
+
elif task.relation == builtins.infomap:
|
|
579
|
+
return _translate_infomap(ctx, task)
|
|
580
|
+
elif task.relation == builtins.louvain:
|
|
581
|
+
return _translate_louvain(ctx, task)
|
|
582
|
+
elif task.relation == builtins.label_propagation:
|
|
583
|
+
return _translate_label_propagation(ctx, task)
|
|
584
|
+
|
|
585
|
+
terms = []
|
|
586
|
+
term_types = []
|
|
587
|
+
for arg in task.args:
|
|
588
|
+
# Handle varargs, which come wrapped in a tuple.
|
|
589
|
+
if isinstance(arg, tuple):
|
|
590
|
+
for vararg in arg:
|
|
591
|
+
term, ty = _translate_relterm(ctx, vararg)
|
|
592
|
+
terms.append(term)
|
|
593
|
+
term_types.append(ty)
|
|
594
|
+
else:
|
|
595
|
+
term, ty = _translate_relterm(ctx, arg)
|
|
596
|
+
terms.append(term)
|
|
597
|
+
term_types.append(ty)
|
|
598
|
+
|
|
599
|
+
if builtins.is_pragma(task.relation):
|
|
600
|
+
lqp_name = pragma_to_lqp_name(task.relation.name)
|
|
601
|
+
return mk_pragma(lqp_name, terms)
|
|
602
|
+
|
|
603
|
+
if builtins.is_builtin(task.relation):
|
|
604
|
+
return build_primitive(task.relation.name, terms, term_types)
|
|
605
|
+
|
|
606
|
+
if helpers.is_external(task.relation):
|
|
607
|
+
return lqp.RelAtom(name=task.relation.name, terms=terms, meta=None)
|
|
608
|
+
|
|
609
|
+
projection, _ = _translate_bindings(ctx, list(task.args))
|
|
610
|
+
rid = get_relation_id(ctx, task.relation, projection)
|
|
611
|
+
return lqp.Atom(name=rid, terms=terms, meta=None)
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
def get_relation_id(ctx: TranslationCtx, relation: ir.Relation, projection: list[Tuple[lqp.Var, lqp.Type]] = []) -> lqp.RelationId:
|
|
615
|
+
types = "_".join([str(t.type_name) for (_, t) in projection])
|
|
616
|
+
if types:
|
|
617
|
+
types = "_" + types
|
|
618
|
+
if relation.id in ctx.def_names.id_to_name:
|
|
619
|
+
unique_name = ctx.def_names.id_to_name[relation.id]
|
|
620
|
+
else:
|
|
621
|
+
name = helpers.relation_name_prefix(relation) + relation.name
|
|
622
|
+
name = helpers.sanitize(name)
|
|
623
|
+
unique_name = ctx.def_names.get_name_by_id(relation.id, name)
|
|
624
|
+
|
|
625
|
+
return utils.gen_rel_id(ctx, unique_name, types)
|
|
626
|
+
|
|
627
|
+
def get_output_id(ctx: TranslationCtx, orig_name: str, metamodel_id: int) -> lqp.RelationId:
|
|
628
|
+
unique_name = ctx.output_names.get_name_by_id(metamodel_id, orig_name)
|
|
629
|
+
return utils.gen_rel_id(ctx, unique_name)
|
|
630
|
+
|
|
631
|
+
def _translate_bindings(ctx: TranslationCtx, bindings: list[ir.Value]) -> Tuple[list[Tuple[lqp.Var, lqp.Type]], list[lqp.Formula]]:
|
|
632
|
+
lqp_vars = []
|
|
633
|
+
conjuncts = []
|
|
634
|
+
for binding in bindings:
|
|
635
|
+
lqp_var, typ, eq = binding_to_lqp_var(ctx, binding)
|
|
636
|
+
lqp_vars.append((lqp_var, typ))
|
|
637
|
+
if eq is not None:
|
|
638
|
+
conjuncts.append(eq)
|
|
639
|
+
|
|
640
|
+
return lqp_vars, conjuncts
|
|
641
|
+
|
|
642
|
+
def binding_to_lqp_var(ctx: TranslationCtx, binding: ir.Value) -> Tuple[lqp.Var, lqp.Type, Union[None, lqp.Formula]]:
|
|
643
|
+
if isinstance(binding, ir.Var):
|
|
644
|
+
var, typ = _translate_term(ctx, binding)
|
|
645
|
+
assert isinstance(var, lqp.Var)
|
|
646
|
+
return var, typ, None
|
|
647
|
+
elif isinstance(binding, ir.Literal):
|
|
648
|
+
lqp_value = to_lqp_value(binding.value, binding.type)
|
|
649
|
+
var, formula = constant_to_var(ctx, lqp_value)
|
|
650
|
+
return var, meta_type_to_lqp(binding.type), formula
|
|
651
|
+
else:
|
|
652
|
+
raise Exception(f"Unsupported binding type: {type(binding)}")
|
|
653
|
+
|
|
654
|
+
def to_lqp_value(value: ir.PyValue, value_type: ir.Type) -> lqp.Value:
|
|
655
|
+
typ = meta_type_to_lqp(value_type)
|
|
656
|
+
|
|
657
|
+
# Ensure int values match the requested integer type.
|
|
658
|
+
if typ.type_name == lqp.TypeName.INT and isinstance(value, int):
|
|
659
|
+
assert lqp_types.INT_MIN <= value <= lqp_types.INT_MAX, f"{value} out of range for a 64-bit INT value"
|
|
660
|
+
val = value
|
|
661
|
+
elif typ.type_name == lqp.TypeName.INT128 and isinstance(value, int):
|
|
662
|
+
assert lqp_types.INT128_MIN <= value <= lqp_types.INT128_MAX, f"{value} out of range for an INT128 value"
|
|
663
|
+
val = lqp.Int128Value(value=value, meta=None)
|
|
664
|
+
elif typ.type_name == lqp.TypeName.UINT128 and isinstance(value, int):
|
|
665
|
+
assert lqp_types.UINT128_MIN <= value <= lqp_types.UINT128_MAX, f"{value} out of range for an UINT128 value"
|
|
666
|
+
val = lqp.UInt128Value(value=value, meta=None)
|
|
667
|
+
elif typ.type_name == lqp.TypeName.FLOAT and isinstance(value, float):
|
|
668
|
+
val = value
|
|
669
|
+
elif typ.type_name == lqp.TypeName.STRING and isinstance(value, str):
|
|
670
|
+
val = value
|
|
671
|
+
elif typ.type_name == lqp.TypeName.DECIMAL and isinstance(value, PyDecimal):
|
|
672
|
+
precision = typ.parameters[0].value
|
|
673
|
+
scale = typ.parameters[1].value
|
|
674
|
+
assert isinstance(precision, int) and isinstance(scale, int)
|
|
675
|
+
val = lqp.DecimalValue(precision=precision, scale=scale, value=value, meta=None)
|
|
676
|
+
elif typ.type_name == lqp.TypeName.DATE and isinstance(value, date):
|
|
677
|
+
val = lqp.DateValue(value=value, meta=None)
|
|
678
|
+
elif typ.type_name == lqp.TypeName.DATETIME and isinstance(value, datetime):
|
|
679
|
+
utc_value = value.astimezone(timezone.utc) if value.tzinfo is not None else value # Convert to UTC cf. Iceberg
|
|
680
|
+
val = lqp.DateTimeValue(value=utc_value, meta=None)
|
|
681
|
+
elif typ.type_name == lqp.TypeName.BOOLEAN and isinstance(value, bool):
|
|
682
|
+
val = lqp.BooleanValue(value=value, meta=None)
|
|
683
|
+
else:
|
|
684
|
+
raise Exception(f"Unsupported type for constant: {typ.type_name} with value {value} of type {type(value)}")
|
|
685
|
+
|
|
686
|
+
return mk_value(val)
|
|
687
|
+
|
|
688
|
+
def constant_to_var(ctx: TranslationCtx, value: lqp.Value, name_hint: str = "cvar") -> Tuple[lqp.Var, lqp.Formula]:
|
|
689
|
+
var = gen_unique_var(ctx, name_hint)
|
|
690
|
+
eq = mk_primitive("rel_primitive_eq", [var, value])
|
|
691
|
+
return var, eq
|
|
692
|
+
|
|
693
|
+
def _extract_pyrel_error_ids(ctx: TranslationCtx, model: ir.Model) -> list[Tuple[lqp.RelationId, str]]:
|
|
694
|
+
effects = collect_by_type(ir.Update, model)
|
|
695
|
+
pyrel_error_attrs = []
|
|
696
|
+
# We use a separate counter here to avoid modifying the current model.
|
|
697
|
+
i = 1
|
|
698
|
+
for effect in effects:
|
|
699
|
+
if "pyrel_error_attrs" not in effect.relation.name:
|
|
700
|
+
continue
|
|
701
|
+
projection, _ = _translate_bindings(ctx, _effect_bindings(effect))
|
|
702
|
+
rel_id = get_relation_id(ctx, effect.relation, projection)
|
|
703
|
+
name = f"{effect.relation.name}_{i}"
|
|
704
|
+
pyrel_error_attrs.append((rel_id, name))
|
|
705
|
+
i += 1
|
|
706
|
+
|
|
707
|
+
return pyrel_error_attrs
|
|
708
|
+
|
|
709
|
+
# Translate a relation reference into an abstraction over its fields.
|
|
710
|
+
def _translate_relation_ref(ctx: TranslationCtx, relation: ir.Relation) -> lqp.Abstraction:
|
|
711
|
+
projection = []
|
|
712
|
+
for field in relation.fields:
|
|
713
|
+
var = gen_unique_var(ctx, field.name)
|
|
714
|
+
typ = meta_type_to_lqp(field.type)
|
|
715
|
+
projection.append((var, typ))
|
|
716
|
+
|
|
717
|
+
rid = get_relation_id(ctx, relation, projection)
|
|
718
|
+
atom = lqp.Atom(name=rid, terms=[var for (var, _) in projection], meta=None)
|
|
719
|
+
return mk_abstraction(projection, atom)
|
|
720
|
+
|
|
721
|
+
# Common translation logic for graph algorithms.
|
|
722
|
+
# task.args[0] : normalized weight list (int64, int64, float)
|
|
723
|
+
# task.args[1] : normalized node count (relation or constant int64)
|
|
724
|
+
# task.args[2] : normalized edge count (relation or constant int64)
|
|
725
|
+
# task.args[3:-3] : algorithm parameters (var or constant)
|
|
726
|
+
# task.args[-3] : diagnostic info
|
|
727
|
+
# task.args[-2] : node index
|
|
728
|
+
# task.args[-1] : community ident
|
|
729
|
+
def _translate_graph_common(name: str, ctx: TranslationCtx, task: ir.Lookup):
|
|
730
|
+
abstractions = []
|
|
731
|
+
|
|
732
|
+
assert isinstance(task.args[0], ir.Relation), \
|
|
733
|
+
f"Expected relation as first arg to {name}, got {task.args[0]}:{type(task.args[0])}"
|
|
734
|
+
abstractions.append(_translate_relation_ref(ctx, task.args[0]))
|
|
735
|
+
|
|
736
|
+
# Allow constant args for node and edge count
|
|
737
|
+
for arg in task.args[1:3]:
|
|
738
|
+
if isinstance(arg, ir.Relation):
|
|
739
|
+
abst = _translate_relation_ref(ctx, arg)
|
|
740
|
+
typ = abst.vars[0][1]
|
|
741
|
+
assert typ.type_name == lqp.TypeName.INT, \
|
|
742
|
+
f"Expected Int64 types for node and edge counts, got type {typ.type_name}"
|
|
743
|
+
abstractions.append(abst)
|
|
744
|
+
else:
|
|
745
|
+
var, typ, eq = binding_to_lqp_var(ctx, arg)
|
|
746
|
+
assert eq is not None, \
|
|
747
|
+
f"Expected equality formula for {name} arg {arg}:{type(arg)}"
|
|
748
|
+
abstractions.append(mk_abstraction([(var, typ)], mk_and([eq])))
|
|
749
|
+
|
|
750
|
+
for arg in task.args[3:-3]:
|
|
751
|
+
var, typ, eq = binding_to_lqp_var(ctx, arg)
|
|
752
|
+
if eq:
|
|
753
|
+
abstractions.append(mk_abstraction([(var, typ)], mk_and([eq])))
|
|
754
|
+
else:
|
|
755
|
+
print(f"Primitive graph algorithm arg without eq:\n var:{var}, typ:{typ}\n arg:{arg}:{type(arg)}")
|
|
756
|
+
abstractions.append(mk_abstraction([(var, typ)], mk_and([])))
|
|
757
|
+
|
|
758
|
+
terms = []
|
|
759
|
+
for arg in task.args[-3:]:
|
|
760
|
+
term, _ = _translate_relterm(ctx, arg)
|
|
761
|
+
terms.append(term)
|
|
762
|
+
|
|
763
|
+
return (abstractions, terms)
|
|
764
|
+
|
|
765
|
+
def _translate_infomap(ctx: TranslationCtx, task: ir.Lookup) -> lqp.Formula:
|
|
766
|
+
abstractions, terms = _translate_graph_common("infomap", ctx, task)
|
|
767
|
+
|
|
768
|
+
return lqp.FFI(
|
|
769
|
+
meta=None,
|
|
770
|
+
name="rel_primitive_infomap",
|
|
771
|
+
args=abstractions,
|
|
772
|
+
terms=terms,
|
|
773
|
+
)
|
|
774
|
+
|
|
775
|
+
def _translate_louvain(ctx: TranslationCtx, task: ir.Lookup) -> lqp.Formula:
|
|
776
|
+
abstractions, terms = _translate_graph_common("louvain", ctx, task)
|
|
777
|
+
|
|
778
|
+
return lqp.FFI(
|
|
779
|
+
meta=None,
|
|
780
|
+
name="rel_primitive_louvain",
|
|
781
|
+
args=abstractions,
|
|
782
|
+
terms=terms,
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
def _translate_label_propagation(ctx: TranslationCtx, task: ir.Lookup) -> lqp.Formula:
|
|
786
|
+
abstractions, terms = _translate_graph_common("label_propagation", ctx, task)
|
|
787
|
+
|
|
788
|
+
return lqp.FFI(
|
|
789
|
+
meta=None,
|
|
790
|
+
name="rel_primitive_async_label_propagation",
|
|
791
|
+
args=abstractions,
|
|
792
|
+
terms=terms,
|
|
793
|
+
)
|
|
794
|
+
|
|
795
|
+
# Hard-coded implementation of Rel's string_join
|
|
796
|
+
def _translate_join(ctx: TranslationCtx, task: ir.Lookup) -> lqp.Formula:
|
|
797
|
+
assert len(task.args) == 3
|
|
798
|
+
(strs, separator, target) = task.args
|
|
799
|
+
assert isinstance(separator, ir.Node)
|
|
800
|
+
assert isinstance(target, ir.Var)
|
|
801
|
+
assert isinstance(strs, tuple)
|
|
802
|
+
|
|
803
|
+
# Enumerate the strings we're going to be reducing over
|
|
804
|
+
enumerated_conjunctions = []
|
|
805
|
+
index_var, index_type = gen_unique_var(ctx, "idx"), meta_type_to_lqp(types.Int64)
|
|
806
|
+
string_var, string_type = gen_unique_var(ctx, "s"), meta_type_to_lqp(types.String)
|
|
807
|
+
for i, s in enumerate(strs):
|
|
808
|
+
index = to_lqp_value(i, types.Int64)
|
|
809
|
+
string = _translate_term(ctx, s)[0]
|
|
810
|
+
eq_idx = mk_primitive("rel_primitive_eq", [index_var, index])
|
|
811
|
+
eq_string = mk_primitive("rel_primitive_eq", [string_var, string])
|
|
812
|
+
enumerated_conjunctions.append(mk_and([eq_idx, eq_string]))
|
|
813
|
+
body = mk_abstraction([(index_var, index_type), (string_var, string_type)], mk_or(enumerated_conjunctions))
|
|
814
|
+
|
|
815
|
+
# Make the function we're reducing
|
|
816
|
+
a_var, a_type = gen_unique_var(ctx, "a"), meta_type_to_lqp(types.String)
|
|
817
|
+
b_var, b_type = gen_unique_var(ctx, "b"), meta_type_to_lqp(types.String)
|
|
818
|
+
curr_var, curr_type = gen_unique_var(ctx, "curr"), meta_type_to_lqp(types.String)
|
|
819
|
+
res_var, res_type = gen_unique_var(ctx, "res"), meta_type_to_lqp(types.String)
|
|
820
|
+
|
|
821
|
+
sep, _ = _translate_term(ctx, separator)
|
|
822
|
+
|
|
823
|
+
op = mk_abstraction(
|
|
824
|
+
[(a_var, a_type), (b_var, b_type), (curr_var, curr_type)],
|
|
825
|
+
mk_exists([(res_var, res_type)],
|
|
826
|
+
mk_and([
|
|
827
|
+
mk_primitive("rel_primitive_concat", [res_var, b_var, curr_var]),
|
|
828
|
+
mk_primitive("rel_primitive_concat", [a_var, sep, res_var])
|
|
829
|
+
])
|
|
830
|
+
)
|
|
831
|
+
)
|
|
832
|
+
|
|
833
|
+
output_term = _translate_term(ctx, target)[0]
|
|
834
|
+
|
|
835
|
+
return lqp.Reduce(meta=None, op=op, body=body, terms=[output_term])
|
|
836
|
+
|
|
837
|
+
def _translate_var(ctx: TranslationCtx, term: ir.Var) -> lqp.Var:
|
|
838
|
+
name = ctx.var_names.get_name_by_id(term.id, term.name)
|
|
839
|
+
return lqp.Var(name=name, meta=None)
|